Fix command completion and remove compile time warnings
[asterisk/asterisk.git] / asterisk.c
index 5e1d812..a003093 100755 (executable)
@@ -168,8 +168,8 @@ int ast_safe_system(const char *s)
                for (x=STDERR_FILENO + 1; x<4096;x++) {
                        close(x);
                }
                for (x=STDERR_FILENO + 1; x<4096;x++) {
                        close(x);
                }
-               res = system(s);
-               exit(res);
+               res = execl("/bin/sh", "/bin/sh", "-c", s, NULL);
+               exit(1);
        } else if (pid > 0) {
                for(;;) {
                        res = wait4(pid, &status, 0, &rusage);
        } else if (pid > 0) {
                for(;;) {
                        res = wait4(pid, &status, 0, &rusage);
@@ -879,9 +879,96 @@ static int ast_el_read_char(EditLine *el, char *cp)
 
 static char *cli_prompt(EditLine *el)
 {
 
 static char *cli_prompt(EditLine *el)
 {
-       static char prompt[80];
-
-       if (remotehostname)
+       static char prompt[200];
+       char *pfmt;
+
+       if ((pfmt = getenv("ASTERISK_PROMPT"))) {
+               char *t = pfmt, *p = prompt;
+               memset(prompt, 0, sizeof(prompt));
+               while (*t != '\0' && *p < sizeof(prompt)) {
+                       if (*t == '%') {
+                               t++;
+                               switch (*t) {
+                                       char hostname[256];
+                                       struct timeval tv;
+                                       struct tm tm;
+                                       FILE *LOADAVG;
+                                       case 'd': /* date */
+                                               memset(&tm, 0, sizeof(struct tm));
+                                               gettimeofday(&tv, NULL);
+                                               if (localtime_r(&(tv.tv_sec), &tm)) {
+                                                       strftime(p, sizeof(prompt) - strlen(prompt), "%Y-%m-%d", &tm);
+                                               }
+                                               break;
+                                       case 'h': /* hostname */
+                                               if (!gethostname(hostname, sizeof(hostname) - 1)) {
+                                                       strncat(p, hostname, sizeof(prompt) - strlen(prompt));
+                                               } else {
+                                                       strncat(p, "localhost", sizeof(prompt) - strlen(prompt));
+                                               }
+                                               break;
+#ifdef linux
+                                       case 'l': /* load avg */
+                                               t++;
+                                               if ((LOADAVG = fopen("/proc/loadavg", "r"))) {
+                                                       float avg1, avg2, avg3;
+                                                       int actproc, totproc, npid, which;
+                                                       fscanf(LOADAVG, "%f %f %f %d/%d %d",
+                                                               &avg1, &avg2, &avg3, &actproc, &totproc, &npid);
+                                                       if (sscanf(t, "%d", &which) == 1) {
+                                                               switch (which) {
+                                                                       case 1:
+                                                                               snprintf(p, sizeof(prompt) - strlen(prompt), "%.2f", avg1);
+                                                                               break;
+                                                                       case 2:
+                                                                               snprintf(p, sizeof(prompt) - strlen(prompt), "%.2f", avg2);
+                                                                               break;
+                                                                       case 3:
+                                                                               snprintf(p, sizeof(prompt) - strlen(prompt), "%.2f", avg3);
+                                                                               break;
+                                                                       case 4:
+                                                                               snprintf(p, sizeof(prompt) - strlen(prompt), "%d/%d", actproc, totproc);
+                                                                               break;
+                                                                       case 5:
+                                                                               snprintf(p, sizeof(prompt) - strlen(prompt), "%d", npid);
+                                                                               break;
+                                                               }
+                                                       }
+                                               }
+                                               break;
+#endif
+                                       case 't': /* time */
+                                               memset(&tm, 0, sizeof(struct tm));
+                                               gettimeofday(&tv, NULL);
+                                               if (localtime_r(&(tv.tv_sec), &tm)) {
+                                                       strftime(p, sizeof(prompt) - strlen(prompt), "%H:%M:%S", &tm);
+                                               }
+                                               break;
+                                       case '#': /* process console or remote? */
+                                               if (! option_remote) {
+                                                       strncat(p, "#", sizeof(prompt) - strlen(prompt));
+                                               } else {
+                                                       strncat(p, ">", sizeof(prompt) - strlen(prompt));
+                                               }
+                                               break;
+                                       case '%': /* literal % */
+                                               strncat(p, "%", sizeof(prompt) - strlen(prompt));
+                                               break;
+                                       case '\0': /* % is last character - prevent bug */
+                                               t--;
+                                               break;
+                               }
+                               while (*p != '\0') {
+                                       p++;
+                               }
+                               t++;
+                       } else {
+                               *p = *t;
+                               p++;
+                               t++;
+                       }
+               }
+       } else if (remotehostname)
                snprintf(prompt, sizeof(prompt), ASTERISK_PROMPT2, remotehostname);
        else
                snprintf(prompt, sizeof(prompt), ASTERISK_PROMPT);
                snprintf(prompt, sizeof(prompt), ASTERISK_PROMPT2, remotehostname);
        else
                snprintf(prompt, sizeof(prompt), ASTERISK_PROMPT);
@@ -898,12 +985,14 @@ static char **ast_el_strtoarr(char *buf)
         match_list_len = 1;
        while ( (retstr = strsep(&buf, " ")) != NULL) {
 
         match_list_len = 1;
        while ( (retstr = strsep(&buf, " ")) != NULL) {
 
+               if (!strcmp(retstr, AST_CLI_COMPLETE_EOF))
+                       break;
                 if (matches + 1 >= match_list_len) {
                         match_list_len <<= 1;
                         match_list = realloc(match_list, match_list_len * sizeof(char *));
                }
 
                 if (matches + 1 >= match_list_len) {
                         match_list_len <<= 1;
                         match_list = realloc(match_list, match_list_len * sizeof(char *));
                }
 
-               match_list[matches++] = retstr;
+               match_list[matches++] = strdup(retstr);
        }
 
         if (!match_list)
        }
 
         if (!match_list)
@@ -977,7 +1066,7 @@ static char *cli_complete(EditLine *el, int ch)
        int nummatches = 0;
        char **matches;
        int retval = CC_ERROR;
        int nummatches = 0;
        char **matches;
        int retval = CC_ERROR;
-       char buf[1024];
+       char buf[2048];
        int res;
 
        LineInfo *lf = (LineInfo *)el_line(el);
        int res;
 
        LineInfo *lf = (LineInfo *)el_line(el);
@@ -1004,12 +1093,32 @@ static char *cli_complete(EditLine *el, int ch)
                nummatches = atoi(buf);
 
                if (nummatches > 0) {
                nummatches = atoi(buf);
 
                if (nummatches > 0) {
+                       char *mbuf;
+                       int mlen = 0, maxmbuf = 2048;
+                       /* Start with a 2048 byte buffer */
+                       mbuf = malloc(maxmbuf);
+                       if (!mbuf)
+                               return (char *)(CC_ERROR);
                        snprintf(buf, sizeof(buf),"_COMMAND MATCHESARRAY \"%s\" \"%s\"", lf->buffer, ptr); 
                        fdprint(ast_consock, buf);
                        snprintf(buf, sizeof(buf),"_COMMAND MATCHESARRAY \"%s\" \"%s\"", lf->buffer, ptr); 
                        fdprint(ast_consock, buf);
-                       res = read(ast_consock, buf, sizeof(buf));
-                       buf[res] = '\0';
+                       res = 0;
+                       while (!strstr(mbuf, AST_CLI_COMPLETE_EOF) && res != -1) {
+                               if (mlen + 1024 > maxmbuf) {
+                                       /* Every step increment buffer 1024 bytes */
+                                       maxmbuf += 1024;
+                                       mbuf = realloc(mbuf, maxmbuf);
+                                       if (!mbuf)
+                                               return (char *)(CC_ERROR);
+                               }
+                               /* Only read 1024 bytes at a time */
+                               res = read(ast_consock, mbuf + mlen, 1024);
+                               if (res > 0)
+                                       mlen += res;
+                       }
+                       mbuf[mlen] = '\0';
 
 
-                       matches = ast_el_strtoarr(buf);
+                       matches = ast_el_strtoarr(mbuf);
+                       free(mbuf);
                } else
                        matches = (char **) NULL;
 
                } else
                        matches = (char **) NULL;
 
@@ -1085,6 +1194,8 @@ static int ast_el_initialize(void)
        el_set(el, EL_BIND, "^I", "ed-complete", NULL);
        /* Bind ? to command completion */
        el_set(el, EL_BIND, "?", "ed-complete", NULL);
        el_set(el, EL_BIND, "^I", "ed-complete", NULL);
        /* Bind ? to command completion */
        el_set(el, EL_BIND, "?", "ed-complete", NULL);
+       /* Bind ^D to redisplay */
+       el_set(el, EL_BIND, "^D", "ed-redisplay", NULL);
 
        return 0;
 }
 
        return 0;
 }