Merge slepp's sub-second expiration timer although hopefully it will never have to...
[asterisk/asterisk.git] / asterisk.c
index 6566bb7..d1b0dad 100755 (executable)
@@ -40,7 +40,6 @@
 #include <asterisk/lock.h>
 #include <sys/socket.h>
 #include <sys/un.h>
-#include <sys/select.h>
 #include <sys/wait.h>
 #include <string.h>
 #include <errno.h>
 #include "asterisk.h"
 #include <asterisk/config.h>
 
+#if  defined(__FreeBSD__)
+#include <netdb.h>
+#endif
+
 #define AST_MAX_CONNECTS 128
 #define NUM_MSGS 64
 
@@ -881,18 +884,40 @@ static char *cli_prompt(EditLine *el)
 {
        static char prompt[200];
        char *pfmt;
+       int color_used=0;
+       char term_code[20];
 
        if ((pfmt = getenv("ASTERISK_PROMPT"))) {
                char *t = pfmt, *p = prompt;
                memset(prompt, 0, sizeof(prompt));
                while (*t != '\0' && *p < sizeof(prompt)) {
                        if (*t == '%') {
+                               char hostname[256];
+                               int i;
+                               struct timeval tv;
+                               struct tm tm;
+                               FILE *LOADAVG;
+                               int fgcolor = COLOR_WHITE, bgcolor = COLOR_BLACK;
+
                                t++;
                                switch (*t) {
-                                       char hostname[256];
-                                       struct timeval tv;
-                                       struct tm tm;
-                                       FILE *LOADAVG;
+                                       case 'C': /* color */
+                                               t++;
+                                               if (sscanf(t, "%d;%d%n", &fgcolor, &bgcolor, &i) == 2) {
+                                                       strncat(p, term_color_code(term_code, fgcolor, bgcolor, sizeof(term_code)),sizeof(prompt) - strlen(prompt));
+                                                       t += i - 1;
+                                               } else if (sscanf(t, "%d%n", &fgcolor, &i) == 1) {
+                                                       strncat(p, term_color_code(term_code, fgcolor, 0, sizeof(term_code)),sizeof(prompt) - strlen(prompt));
+                                                       t += i - 1;
+                                               }
+
+                                               /* If the color has been reset correctly, then there's no need to reset it later */
+                                               if ((fgcolor == COLOR_WHITE) && (bgcolor == COLOR_BLACK)) {
+                                                       color_used = 0;
+                                               } else {
+                                                       color_used = 1;
+                                               }
+                                               break;
                                        case 'd': /* date */
                                                memset(&tm, 0, sizeof(struct tm));
                                                gettimeofday(&tv, NULL);
@@ -907,6 +932,19 @@ static char *cli_prompt(EditLine *el)
                                                        strncat(p, "localhost", sizeof(prompt) - strlen(prompt));
                                                }
                                                break;
+                                       case 'H': /* short hostname */
+                                               if (!gethostname(hostname, sizeof(hostname) - 1)) {
+                                                       for (i=0;i<sizeof(hostname);i++) {
+                                                               if (hostname[i] == '.') {
+                                                                       hostname[i] = '\0';
+                                                                       break;
+                                                               }
+                                                       }
+                                                       strncat(p, hostname, sizeof(prompt) - strlen(prompt));
+                                               } else {
+                                                       strncat(p, "localhost", sizeof(prompt) - strlen(prompt));
+                                               }
+                                               break;
 #ifdef linux
                                        case 'l': /* load avg */
                                                t++;
@@ -968,6 +1006,15 @@ static char *cli_prompt(EditLine *el)
                                t++;
                        }
                }
+               if (color_used) {
+                       /* Force colors back to normal at end */
+                       term_color_code(term_code, COLOR_WHITE, COLOR_BLACK, sizeof(term_code));
+                       if (strlen(term_code) > sizeof(prompt) - strlen(prompt)) {
+                               strncat(prompt + sizeof(prompt) - strlen(term_code) - 1, term_code, strlen(term_code));
+                       } else {
+                               strncat(p, term_code, sizeof(term_code));
+                       }
+               }
        } else if (remotehostname)
                snprintf(prompt, sizeof(prompt), ASTERISK_PROMPT2, remotehostname);
        else
@@ -1664,25 +1711,144 @@ int main(int argc, char *argv[])
                        } else {
                                if (option_remote)
                                        ast_cli(STDOUT_FILENO, "\nUse EXIT or QUIT to exit the asterisk console\n");
-                               else
-                                       ast_cli(STDOUT_FILENO, "\nUse STOP NOW to shutdown Asterisk\n");
                        }
                }
 
        } else {
                /* Do nothing */
-               poll(NULL,0, -1);
+               for(;;) 
+                       poll(NULL,0, -1);
        }
        return 0;
 }
 
+
+#if  defined(__FreeBSD__)
+
+/* duh? ERANGE value copied from web... */
+#define ERANGE 34
+#undef gethostbyname
+
+int gethostbyname_r (const char *name,
+                    struct hostent *ret,
+                    char *buf,
+                    size_t buflen,
+                    struct hostent **result,
+                    int *h_errnop);
+
+int gethostbyname_r (const char *name,
+                    struct hostent *ret,
+                    char *buf,
+                    size_t buflen,
+                    struct hostent **result,
+                    int *h_errnop) {
+
+  int hsave;
+  struct hostent *ph;
+  static ast_mutex_t __mutex = AST_MUTEX_INITIALIZER;
+  ast_mutex_lock(&__mutex); /* begin critical area */
+  hsave = h_errno;
+
+  ph = gethostbyname(name);
+  *h_errnop = h_errno; /* copy h_errno to *h_herrnop */
+  if (ph == NULL) {
+    *result = NULL;
+  } else {
+    char **p, **q;
+    char *pbuf;
+    int nbytes=0;
+    int naddr=0, naliases=0;
+    /* determine if we have enough space in buf */
+
+    /* count how many addresses */
+    for (p = ph->h_addr_list; *p != 0; p++) {
+      nbytes += ph->h_length; /* addresses */
+      nbytes += sizeof(*p); /* pointers */
+      naddr++;
+    }
+    nbytes += sizeof(*p); /* one more for the terminating NULL */
+
+    /* count how many aliases, and total length of strings */
+
+    for (p = ph->h_aliases; *p != 0; p++) {
+      nbytes += (strlen(*p)+1); /* aliases */
+      nbytes += sizeof(*p);  /* pointers */
+      naliases++;
+    }
+    nbytes += sizeof(*p); /* one more for the terminating NULL */
+
+    /* here nbytes is the number of bytes required in buffer */
+    /* as a terminator must be there, the minimum value is ph->h_length */
+    if(nbytes > buflen) {
+      *result = NULL;
+      pthread_mutex_unlock(&__mutex); /* end critical area */
+      return ERANGE; /* not enough space in buf!! */
+    }
+
+    /* There is enough space. Now we need to do a deep copy! */
+    /* Allocation in buffer:
+       from [0] to [(naddr-1) * sizeof(*p)]:
+       pointers to addresses
+       at [naddr * sizeof(*p)]:
+       NULL
+       from [(naddr+1) * sizeof(*p)] to [(naddr+naliases) * sizeof(*p)] :
+       pointers to aliases
+       at [(naddr+naliases+1) * sizeof(*p)]:
+       NULL
+       then naddr addresses (fixed length), and naliases aliases (asciiz).
+    */
+
+    *ret = *ph;   /* copy whole structure (not its address!) */
+
+    /* copy addresses */
+    q = (char **)buf; /* pointer to pointers area (type: char **) */
+    ret->h_addr_list = q; /* update pointer to address list */
+    pbuf = buf + ((naddr+naliases+2)*sizeof(*p)); /* skip that area */
+    for (p = ph->h_addr_list; *p != 0; p++) {
+      memcpy(pbuf, *p, ph->h_length); /* copy address bytes */
+      *q++ = pbuf; /* the pointer is the one inside buf... */
+      pbuf += ph->h_length; /* advance pbuf */
+    }
+    *q++ = NULL; /* address list terminator */
+
+    /* copy aliases */
+
+    ret->h_aliases = q; /* update pointer to aliases list */
+    for (p = ph->h_aliases; *p != 0; p++) {
+      strcpy(pbuf, *p); /* copy alias strings */
+      *q++ = pbuf; /* the pointer is the one inside buf... */
+      pbuf += strlen(*p); /* advance pbuf */
+      *pbuf++ = 0; /* string terminator */
+    }
+    *q++ = NULL; /* terminator */
+
+    strcpy(pbuf, ph->h_name); /* copy alias strings */
+    ret->h_name = pbuf;
+    pbuf += strlen(ph->h_name); /* advance pbuf */
+    *pbuf++ = 0; /* string terminator */
+
+    *result = ret;  /* and let *result point to structure */
+
+  }
+  h_errno = hsave;  /* restore h_errno */
+
+  ast_mutex_unlock(&__mutex); /* end critical area */
+
+  return (*result != NULL);
+
+}
+
+
+#endif
+
 struct hostent *ast_gethostbyname(const char *host, struct ast_hostent *hp)
 {
        int res;
        int herrno;
        struct hostent *result = NULL;
-       /* XXX Does BSD do this differently? XXX */
+
        res = gethostbyname_r(host, &hp->hp, hp->buf, sizeof(hp->buf), &result, &herrno);
+
        if (res)
                return NULL;
        return &hp->hp;