Merge in ast_strftime branch, which changes timestamps to be accurate to the microsec...
[asterisk/asterisk.git] / main / asterisk.c
index de0f4c1..56c5889 100644 (file)
@@ -188,13 +188,13 @@ struct console {
 
 struct ast_atexit {
        void (*func)(void);
-       AST_LIST_ENTRY(ast_atexit) list;
+       AST_RWLIST_ENTRY(ast_atexit) list;
 };
 
-static AST_LIST_HEAD_STATIC(atexits, ast_atexit);
+static AST_RWLIST_HEAD_STATIC(atexits, ast_atexit);
 
-time_t ast_startuptime;
-time_t ast_lastreloadtime;
+struct timeval ast_startuptime;
+struct timeval ast_lastreloadtime;
 
 static History *el_hist;
 static EditLine *el;
@@ -252,12 +252,12 @@ static struct {
 
 #if !defined(LOW_MEMORY)
 struct file_version {
-       AST_LIST_ENTRY(file_version) list;
+       AST_RWLIST_ENTRY(file_version) list;
        const char *file;
        char *version;
 };
 
-static AST_LIST_HEAD_STATIC(file_versions, file_version);
+static AST_RWLIST_HEAD_STATIC(file_versions, file_version);
 
 void ast_register_file_version(const char *file, const char *version)
 {
@@ -275,36 +275,36 @@ void ast_register_file_version(const char *file, const char *version)
        new->file = file;
        new->version = (char *) new + sizeof(*new);
        memcpy(new->version, work, version_length);
-       AST_LIST_LOCK(&file_versions);
-       AST_LIST_INSERT_HEAD(&file_versions, new, list);
-       AST_LIST_UNLOCK(&file_versions);
+       AST_RWLIST_WRLOCK(&file_versions);
+       AST_RWLIST_INSERT_HEAD(&file_versions, new, list);
+       AST_RWLIST_UNLOCK(&file_versions);
 }
 
 void ast_unregister_file_version(const char *file)
 {
        struct file_version *find;
 
-       AST_LIST_LOCK(&file_versions);
-       AST_LIST_TRAVERSE_SAFE_BEGIN(&file_versions, find, list) {
+       AST_RWLIST_WRLOCK(&file_versions);
+       AST_RWLIST_TRAVERSE_SAFE_BEGIN(&file_versions, find, list) {
                if (!strcasecmp(find->file, file)) {
-                       AST_LIST_REMOVE_CURRENT(&file_versions, list);
+                       AST_RWLIST_REMOVE_CURRENT(&file_versions, list);
                        break;
                }
        }
-       AST_LIST_TRAVERSE_SAFE_END;
-       AST_LIST_UNLOCK(&file_versions);
+       AST_RWLIST_TRAVERSE_SAFE_END;
+       AST_RWLIST_UNLOCK(&file_versions);
 
        if (find)
                ast_free(find);
 }
 
 struct thread_list_t {
-       AST_LIST_ENTRY(thread_list_t) list;
+       AST_RWLIST_ENTRY(thread_list_t) list;
        char *name;
        pthread_t id;
 };
 
-static AST_LIST_HEAD_STATIC(thread_list, thread_list_t);
+static AST_RWLIST_HEAD_STATIC(thread_list, thread_list_t);
 
 static const char show_threads_help[] =
 "Usage: core show threads\n"
@@ -318,24 +318,24 @@ void ast_register_thread(char *name)
                return;
        new->id = pthread_self();
        new->name = name; /* steal the allocated memory for the thread name */
-       AST_LIST_LOCK(&thread_list);
-       AST_LIST_INSERT_HEAD(&thread_list, new, list);
-       AST_LIST_UNLOCK(&thread_list);
+       AST_RWLIST_WRLOCK(&thread_list);
+       AST_RWLIST_INSERT_HEAD(&thread_list, new, list);
+       AST_RWLIST_UNLOCK(&thread_list);
 }
 
 void ast_unregister_thread(void *id)
 {
        struct thread_list_t *x;
 
-       AST_LIST_LOCK(&thread_list);
-       AST_LIST_TRAVERSE_SAFE_BEGIN(&thread_list, x, list) {
+       AST_RWLIST_WRLOCK(&thread_list);
+       AST_RWLIST_TRAVERSE_SAFE_BEGIN(&thread_list, x, list) {
                if ((void *) x->id == id) {
-                       AST_LIST_REMOVE_CURRENT(&thread_list, list);
+                       AST_RWLIST_REMOVE_CURRENT(&thread_list, list);
                        break;
                }
        }
-       AST_LIST_TRAVERSE_SAFE_END;
-       AST_LIST_UNLOCK(&thread_list);
+       AST_RWLIST_TRAVERSE_SAFE_END;
+       AST_RWLIST_UNLOCK(&thread_list);
        if (x) {
                ast_free(x->name);
                ast_free(x);
@@ -346,7 +346,7 @@ void ast_unregister_thread(void *id)
 static int handle_show_settings(int fd, int argc, char *argv[])
 {
        char buf[BUFSIZ];
-       struct tm tm;
+       struct ast_tm tm;
 
        ast_cli(fd, "\nPBX Core settings\n");
        ast_cli(fd, "-----------------\n");
@@ -366,11 +366,11 @@ static int handle_show_settings(int fd, int argc, char *argv[])
        ast_cli(fd, "  Min Free Memory:             %ld MB\n", option_minmemfree);
 #endif
        if (ast_localtime(&ast_startuptime, &tm, NULL)) {
-               strftime(buf, sizeof(buf), "%H:%M:%S", &tm);
+               ast_strftime(buf, sizeof(buf), "%H:%M:%S", &tm);
                ast_cli(fd, "  Startup time:                %s\n", buf);
        }
        if (ast_localtime(&ast_lastreloadtime, &tm, NULL)) {
-               strftime(buf, sizeof(buf), "%H:%M:%S", &tm);
+               ast_strftime(buf, sizeof(buf), "%H:%M:%S", &tm);
                ast_cli(fd, "  Last reload time:            %s\n", buf);
        }
        ast_cli(fd, "  System:                      %s/%s built by %s on %s %s\n", ast_build_os, ast_build_kernel, ast_build_user, ast_build_machine, ast_build_date);
@@ -408,12 +408,12 @@ static int handle_show_threads(int fd, int argc, char *argv[])
        int count = 0;
        struct thread_list_t *cur;
 
-       AST_LIST_LOCK(&thread_list);
-       AST_LIST_TRAVERSE(&thread_list, cur, list) {
+       AST_RWLIST_RDLOCK(&thread_list);
+       AST_RWLIST_TRAVERSE(&thread_list, cur, list) {
                ast_cli(fd, "%p %s\n", (void *)cur->id, cur->name);
                count++;
        }
-        AST_LIST_UNLOCK(&thread_list);
+        AST_RWLIST_UNLOCK(&thread_list);
        ast_cli(fd, "%d threads listed.\n", count);
        return 0;
 }
@@ -623,8 +623,8 @@ static int handle_show_version_files(int fd, int argc, char *argv[])
 
        ast_cli(fd, FORMAT, "File", "Revision");
        ast_cli(fd, FORMAT, "----", "--------");
-       AST_LIST_LOCK(&file_versions);
-       AST_LIST_TRAVERSE(&file_versions, iterator, list) {
+       AST_RWLIST_RDLOCK(&file_versions);
+       AST_RWLIST_TRAVERSE(&file_versions, iterator, list) {
                if (havename && strcasecmp(iterator->file, argv[4]))
                        continue;
 
@@ -636,7 +636,7 @@ static int handle_show_version_files(int fd, int argc, char *argv[])
                if (havename)
                        break;
        }
-       AST_LIST_UNLOCK(&file_versions);
+       AST_RWLIST_UNLOCK(&file_versions);
        if (!havename) {
                ast_cli(fd, "%d files listed.\n", count_files);
        }
@@ -658,14 +658,14 @@ static char *complete_show_version_files(const char *line, const char *word, int
        if (pos != 3)
                return NULL;
 
-       AST_LIST_LOCK(&file_versions);
-       AST_LIST_TRAVERSE(&file_versions, find, list) {
+       AST_RWLIST_RDLOCK(&file_versions);
+       AST_RWLIST_TRAVERSE(&file_versions, find, list) {
                if (!strncasecmp(word, find->file, matchlen) && ++which > state) {
                        ret = ast_strdup(find->file);
                        break;
                }
        }
-       AST_LIST_UNLOCK(&file_versions);
+       AST_RWLIST_UNLOCK(&file_versions);
 
        return ret;
 }
@@ -676,28 +676,28 @@ int ast_register_atexit(void (*func)(void))
        int res = -1;
        struct ast_atexit *ae;
        ast_unregister_atexit(func);    
-       AST_LIST_LOCK(&atexits);
+       AST_RWLIST_WRLOCK(&atexits);
        if ((ae = ast_calloc(1, sizeof(*ae)))) {
-               AST_LIST_INSERT_HEAD(&atexits, ae, list);
+               AST_RWLIST_INSERT_HEAD(&atexits, ae, list);
                ae->func = func;
                res = 0;
        }
-       AST_LIST_UNLOCK(&atexits);
+       AST_RWLIST_UNLOCK(&atexits);
        return res;
 }
 
 void ast_unregister_atexit(void (*func)(void))
 {
        struct ast_atexit *ae;
-       AST_LIST_LOCK(&atexits);
-       AST_LIST_TRAVERSE_SAFE_BEGIN(&atexits, ae, list) {
+       AST_RWLIST_WRLOCK(&atexits);
+       AST_RWLIST_TRAVERSE_SAFE_BEGIN(&atexits, ae, list) {
                if (ae->func == func) {
-                       AST_LIST_REMOVE_CURRENT(&atexits, list);
+                       AST_RWLIST_REMOVE_CURRENT(&atexits, list);
                        break;
                }
        }
-       AST_LIST_TRAVERSE_SAFE_END
-       AST_LIST_UNLOCK(&atexits);
+       AST_RWLIST_TRAVERSE_SAFE_END
+       AST_RWLIST_UNLOCK(&atexits);
 }
 
 static int fdprint(int fd, const char *s)
@@ -1192,12 +1192,12 @@ int ast_set_priority(int pri)
 static void ast_run_atexits(void)
 {
        struct ast_atexit *ae;
-       AST_LIST_LOCK(&atexits);
-       AST_LIST_TRAVERSE(&atexits, ae, list) {
+       AST_RWLIST_RDLOCK(&atexits);
+       AST_RWLIST_TRAVERSE(&atexits, ae, list) {
                if (ae->func) 
                        ae->func();
        }
-       AST_LIST_UNLOCK(&atexits);
+       AST_RWLIST_UNLOCK(&atexits);
 }
 
 static void quit_handler(int num, int nice, int safeshutdown, int restart)
@@ -1451,12 +1451,6 @@ static const char version_help[] =
 "Usage: core show version\n"
 "       Shows Asterisk version information.\n";
 
-#if defined(MARKO_BDAY)
-static const char markobday_help[] =
-"Usage: marko show birthday\n"
-"       Shows time until/since Mark Spencer's 30th birthday.\n";
-#endif
-
 static int handle_version(int fd, int argc, char *argv[])
 {
        if (argc != 3)
@@ -1467,73 +1461,6 @@ static int handle_version(int fd, int argc, char *argv[])
        return RESULT_SUCCESS;
 }
 
-#if defined(MARKO_BDAY)
-static void print_markobdaystr(int fd, time_t timeval, const char *prefix)
-{
-       int x; /* the main part - years, weeks, etc. */
-       struct ast_str *out;
-
-#define SECOND (1)
-#define MINUTE (SECOND*60)
-#define HOUR (MINUTE*60)
-#define DAY (HOUR*24)
-#define WEEK (DAY*7)
-#define YEAR (DAY*365)
-#define NEEDCOMMA(x) ((x)? ",": "")    /* define if we need a comma */
-       if (timeval < 0)        /* invalid, nothing to show */
-               return;
-
-       out = ast_str_alloca(256);
-       if (timeval > YEAR) {
-               x = (timeval / YEAR);
-               timeval -= (x * YEAR);
-               ast_str_append(&out, 0, "%d year%s%s ", x, ESS(x),NEEDCOMMA(timeval));
-       }
-       if (timeval > WEEK) {
-               x = (timeval / WEEK);
-               timeval -= (x * WEEK);
-               ast_str_append(&out, 0, "%d week%s%s ", x, ESS(x),NEEDCOMMA(timeval));
-       }
-       if (timeval > DAY) {
-               x = (timeval / DAY);
-               timeval -= (x * DAY);
-               ast_str_append(&out, 0, "%d day%s%s ", x, ESS(x),NEEDCOMMA(timeval));
-       }
-       if (timeval > HOUR) {
-               x = (timeval / HOUR);
-               timeval -= (x * HOUR);
-               ast_str_append(&out, 0, "%d hour%s%s ", x, ESS(x),NEEDCOMMA(timeval));
-       }
-       if (timeval > MINUTE) {
-               x = (timeval / MINUTE);
-               timeval -= (x * MINUTE);
-               ast_str_append(&out, 0, "%d minute%s%s ", x, ESS(x),NEEDCOMMA(timeval));
-       }
-       x = timeval;
-       if (x > 0 || out->used == 0)    /* if there is nothing, print 0 seconds */
-               ast_str_append(&out, 0, "%d second%s ", x, ESS(x));
-       ast_cli(fd, "%s: %s\n", prefix, out->str);
-}
-
-static int handle_markobday(int fd, int argc, char *argv[])
-{
-       time_t markobdaystarttime = 1176008400; /* 2007-04-08 00:00:00 */
-       time_t markobdayendtime = 1176094799;   /* 2007-04-08 23:59:59 */
-       time_t curtime;
-
-       curtime = time(NULL);
-       if (markobdaystarttime && markobdayendtime) {
-               if (curtime >= markobdaystarttime && curtime <= markobdayendtime)
-                       ast_cli(fd, "Happy 30th birthday Marko!\n");
-               else if (curtime > markobdayendtime)
-                       print_markobdaystr(fd, curtime - markobdayendtime, "Time since Mark Spencer's 30th birthday");
-               else
-                       print_markobdaystr(fd, markobdaystarttime - curtime, "Time until Mark Spencer's 30th birthday");
-       }
-       return RESULT_SUCCESS;
-}
-#endif
-
 #if 0
 static int handle_quit(int fd, int argc, char *argv[])
 {
@@ -1709,12 +1636,6 @@ static struct ast_cli_entry cli_asterisk[] = {
        handle_version, "Display version info",
        version_help },
 
-#if defined(MARKO_BDAY)
-       { { "marko", "show", "birthday", NULL },
-       handle_markobday, "Display time until/since Mark Spencer's 30th birthday",
-       markobday_help },
-#endif
-
        { { "!", NULL },
        handle_bang, "Execute a shell command",
        bang_help },
@@ -1839,8 +1760,8 @@ static char *cli_prompt(EditLine *el)
                        if (*t == '%') {
                                char hostname[MAXHOSTNAMELEN]="";
                                int i;
-                               time_t ts;
-                               struct tm tm;
+                               struct timeval ts = ast_tvnow();
+                               struct ast_tm tm = { 0, };
 #ifdef linux
                                FILE *LOADAVG;
 #endif
@@ -1862,10 +1783,8 @@ static char *cli_prompt(EditLine *el)
                                        color_used = ((fgcolor == COLOR_WHITE) && (bgcolor == COLOR_BLACK)) ? 0 : 1;
                                        break;
                                case 'd': /* date */
-                                       memset(&tm, 0, sizeof(tm));
-                                       time(&ts);
                                        if (ast_localtime(&ts, &tm, NULL))
-                                               strftime(p, sizeof(prompt) - strlen(prompt), "%Y-%m-%d", &tm);
+                                               ast_strftime(p, sizeof(prompt) - strlen(prompt), "%Y-%m-%d", &tm);
                                        break;
                                case 'h': /* hostname */
                                        if (!gethostname(hostname, sizeof(hostname) - 1))
@@ -1919,10 +1838,8 @@ static char *cli_prompt(EditLine *el)
                                        strncat(p, ast_config_AST_SYSTEM_NAME, sizeof(prompt) - strlen(prompt) - 1);
                                        break;
                                case 't': /* time */
-                                       memset(&tm, 0, sizeof(tm));
-                                       time(&ts);
                                        if (ast_localtime(&ts, &tm, NULL))
-                                               strftime(p, sizeof(prompt) - strlen(prompt), "%H:%M:%S", &tm);
+                                               ast_strftime(p, sizeof(prompt) - strlen(prompt), "%H:%M:%S", &tm);
                                        break;
                                case '#': /* process console or remote? */
                                        if (!ast_opt_remote) 
@@ -2282,10 +2199,6 @@ static void ast_remotecontrol(char * data)
        fdprint(ast_consock, tmp);
        snprintf(tmp, sizeof(tmp), "core set debug atleast %d", option_debug);
        fdprint(ast_consock, tmp);
-#if defined(MARKO_BDAY)
-       snprintf(tmp, sizeof(tmp), "marko show birthday");
-       fdprint(ast_consock, tmp);
-#endif
        if (ast_opt_mute) {
                snprintf(tmp, sizeof(tmp), "log and verbose output currently muted ('logger unmute' to unmute)");
                fdprint(ast_consock, tmp);
@@ -2315,6 +2228,9 @@ static void ast_remotecontrol(char * data)
        for (;;) {
                ebuf = (char *)el_gets(el, &num);
 
+               if (!ebuf && write(1, "", 1) < 0)
+                       break;
+
                if (!ast_strlen_zero(ebuf)) {
                        if (ebuf[strlen(ebuf)-1] == '\n')
                                ebuf[strlen(ebuf)-1] = '\0';
@@ -3023,7 +2939,7 @@ int main(int argc, char *argv[])
        __ast_mm_init();
 #endif 
 
-       time(&ast_startuptime);
+       ast_startuptime = ast_tvnow();
        ast_cli_register_multiple(cli_asterisk, sizeof(cli_asterisk) / sizeof(struct ast_cli_entry));
 
        if (ast_opt_console) {
@@ -3040,6 +2956,10 @@ int main(int argc, char *argv[])
 
                for (;;) {
                        buf = (char *)el_gets(el, &num);
+
+                       if (!buf && write(1, "", 1) < 0)
+                               goto lostterm;
+
                        if (buf) {
                                if (buf[strlen(buf)-1] == '\n')
                                        buf[strlen(buf)-1] = '\0';
@@ -3062,5 +2982,6 @@ int main(int argc, char *argv[])
 
        monitor_sig_flags(NULL);
 
+lostterm:
        return 0;
 }