Merged revisions 71066 via svnmerge from
[asterisk/asterisk.git] / main / asterisk.c
index 14bfb81..3088c59 100644 (file)
@@ -61,6 +61,8 @@
 
 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 
+#undef sched_setscheduler
+#undef setpriority
 #include <unistd.h>
 #include <stdlib.h>
 #include <sys/time.h>
@@ -78,6 +80,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include <grp.h>
 #include <pwd.h>
 #include <sys/stat.h>
+#if defined(HAVE_SYSINFO)
+#include <sys/sysinfo.h>
+#endif
 #ifdef linux
 #include <sys/prctl.h>
 #ifdef HAVE_CAP
@@ -121,6 +126,7 @@ int daemon(int, int);  /* defined in libresolv of all places */
 #include "asterisk/version.h"
 #include "asterisk/linkedlists.h"
 #include "asterisk/devicestate.h"
+#include "asterisk/module.h"
 
 #include "asterisk/doxyref.h"          /* Doxygen documentation */
 
@@ -136,7 +142,7 @@ int daemon(int, int);  /* defined in libresolv of all places */
 
 /*! \brief Welcome message when starting a CLI interface */
 #define WELCOME_MESSAGE \
-    ast_verbose("Asterisk " ASTERISK_VERSION ", Copyright (C) 1999 - 2006 Digium, Inc. and others.\n" \
+    ast_verbose("Asterisk " ASTERISK_VERSION ", Copyright (C) 1999 - 2007 Digium, Inc. and others.\n" \
                 "Created by Mark Spencer <markster@digium.com>\n" \
                 "Asterisk comes with ABSOLUTELY NO WARRANTY; type 'core show warranty' for details.\n" \
                 "This is free software, with components licensed under the GNU General Public\n" \
@@ -161,6 +167,9 @@ int option_debug;                           /*!< Debug level */
 double option_maxload;                         /*!< Max load avg on system */
 int option_maxcalls;                           /*!< Max number of active calls */
 int option_maxfiles;                           /*!< Max number of open file handles (files, sockets) */
+#if defined(HAVE_SYSINFO)
+long option_minmemfree;                                /*!< Minimum amount of free system memory - stop accepting calls if free memory falls below this watermark */
+#endif
 
 /*! @} */
 
@@ -179,10 +188,10 @@ 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;
@@ -243,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)
 {
@@ -266,35 +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)
-               free(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"
@@ -308,27 +318,27 @@ 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) {
-               free(x->name);
-               free(x);
+               ast_free(x->name);
+               ast_free(x);
        }
 }
 
@@ -352,11 +362,14 @@ static int handle_show_settings(int fd, int argc, char *argv[])
        ast_cli(fd, "  Verbosity:                   %d\n", option_verbose);
        ast_cli(fd, "  Debug level:                 %d\n", option_debug);
        ast_cli(fd, "  Max load avg:                %lf\n", option_maxload);
-       if (localtime_r(&ast_startuptime, &tm)) {
+#if defined(HAVE_SYSINFO)
+       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_cli(fd, "  Startup time:                %s\n", buf);
        }
-       if (localtime_r(&ast_lastreloadtime, &tm)) {
+       if (ast_localtime(&ast_lastreloadtime, &tm, NULL)) {
                strftime(buf, sizeof(buf), "%H:%M:%S", &tm);
                ast_cli(fd, "  Last reload time:            %s\n", buf);
        }
@@ -395,16 +408,43 @@ 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;
 }
 
+#if defined(HAVE_SYSINFO)
+static const char show_sysinfo_help[] =
+"Usage: core show sysinfo\n"
+"       List current system information.\n";
+
+/*! \brief Give an overview of system statistics */
+static int handle_show_sysinfo(int fd, int argc, char *argv[])
+{
+       struct sysinfo sys_info;
+
+       if (sysinfo(&sys_info)) {
+               ast_cli(fd, "FAILED to retrieve system information\n\n");
+               return 0;
+       }
+       ast_cli(fd, "\nSystem Statistics\n");
+       ast_cli(fd, "-----------------\n");
+       ast_cli(fd, "  System Uptime:             %ld hours\n", sys_info.uptime/3600);
+       ast_cli(fd, "  Total RAM:                 %ld KiB\n", (sys_info.totalram / sys_info.mem_unit)/1024);
+       ast_cli(fd, "  Free RAM:                  %ld KiB\n", (sys_info.freeram / sys_info.mem_unit)/1024);
+       ast_cli(fd, "  Buffer RAM:                %ld KiB\n", (sys_info.bufferram / sys_info.mem_unit)/1024);
+       ast_cli(fd, "  Total Swap Space:          %ld KiB\n", (sys_info.totalswap / sys_info.mem_unit)/1024);
+       ast_cli(fd, "  Free Swap Space:           %ld KiB\n\n", (sys_info.freeswap / sys_info.mem_unit)/1024);
+       ast_cli(fd, "  Number of Processes:       %d \n\n", sys_info.procs);
+       return 0;
+}
+#endif
+
 struct profile_entry {
        const char *name;
        uint64_t        scale;  /* if non-zero, values are scaled by this */
@@ -583,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;
 
@@ -596,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);
        }
@@ -618,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;
 }
@@ -636,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)
@@ -894,9 +934,6 @@ static void *listener(void *unused)
        int x;
        int flags;
        struct pollfd fds[1];
-       pthread_attr_t attr;
-       pthread_attr_init(&attr);
-       pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
        for (;;) {
                if (ast_socket < 0)
                        return NULL;
@@ -928,7 +965,7 @@ static void *listener(void *unused)
                                        fcntl(consoles[x].p[1], F_SETFL, flags | O_NONBLOCK);
                                        consoles[x].fd = s;
                                        consoles[x].mute = ast_opt_mute;
-                                       if (ast_pthread_create_background(&consoles[x].t, &attr, netconsole, &consoles[x])) {
+                                       if (ast_pthread_create_detached_background(&consoles[x].t, NULL, netconsole, &consoles[x])) {
                                                ast_log(LOG_ERROR, "Unable to spawn thread to handle connection: %s\n", strerror(errno));
                                                close(consoles[x].p[0]);
                                                close(consoles[x].p[1]);
@@ -1133,10 +1170,8 @@ int ast_set_priority(int pri)
                                ast_verbose("Set to realtime thread\n");
        } else {
                sched.sched_priority = 0;
-               if (sched_setscheduler(0, SCHED_OTHER, &sched)) {
-                       ast_log(LOG_WARNING, "Unable to set normal priority\n");
-                       return -1;
-               }
+               /* According to the manpage, these parameters can never fail. */
+               sched_setscheduler(0, SCHED_OTHER, &sched);
        }
 #else
        if (pri) {
@@ -1147,10 +1182,8 @@ int ast_set_priority(int pri)
                        if (option_verbose)
                                ast_verbose("Set to high priority\n");
        } else {
-               if (setpriority(PRIO_PROCESS, 0, 0) == -1) {
-                       ast_log(LOG_WARNING, "Unable to set normal priority\n");
-                       return -1;
-               }
+               /* According to the manpage, these parameters can never fail. */
+               setpriority(PRIO_PROCESS, 0, 0);
        }
 #endif
        return 0;
@@ -1159,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)
@@ -1213,6 +1246,9 @@ static void quit_handler(int num, int nice, int safeshutdown, int restart)
                                ast_verbose("Asterisk %s cancelled.\n", restart ? "restart" : "shutdown");
                        return;
                }
+
+               if (nice)
+                       ast_module_shutdown();
        }
        if (ast_opt_console || ast_opt_remote) {
                if (getenv("HOME")) 
@@ -1230,8 +1266,7 @@ static void quit_handler(int num, int nice, int safeshutdown, int restart)
        /* Called on exit */
        if (option_verbose && ast_opt_console)
                ast_verbose("Asterisk %s ending (%d).\n", ast_active_channels() ? "uncleanly" : "cleanly", num);
-       if (option_debug)
-               ast_log(LOG_DEBUG, "Asterisk ending (%d).\n", num);
+       ast_debug(1, "Asterisk ending (%d).\n", num);
        manager_event(EVENT_FLAG_SYSTEM, "Shutdown", "Shutdown: %s\r\nRestart: %s\r\n", ast_active_channels() ? "Uncleanly" : "Cleanly", restart ? "True" : "False");
        if (ast_socket > -1) {
                pthread_cancel(lthread);
@@ -1614,6 +1649,12 @@ static struct ast_cli_entry cli_asterisk[] = {
        handle_show_threads, "Show running threads",
        show_threads_help },
 
+#if defined(HAVE_SYSINFO)
+       { { "core", "show", "sysinfo", NULL },
+       handle_show_sysinfo, "Show System Information",
+       show_sysinfo_help },
+#endif
+
        { { "core", "show", "profile", NULL },
        handle_show_profile, "Display profiling info",
        NULL },
@@ -1744,7 +1785,7 @@ static char *cli_prompt(EditLine *el)
                                case 'd': /* date */
                                        memset(&tm, 0, sizeof(tm));
                                        time(&ts);
-                                       if (localtime_r(&ts, &tm)) 
+                                       if (ast_localtime(&ts, &tm, NULL))
                                                strftime(p, sizeof(prompt) - strlen(prompt), "%Y-%m-%d", &tm);
                                        break;
                                case 'h': /* hostname */
@@ -1801,7 +1842,7 @@ static char *cli_prompt(EditLine *el)
                                case 't': /* time */
                                        memset(&tm, 0, sizeof(tm));
                                        time(&ts);
-                                       if (localtime_r(&ts, &tm))
+                                       if (ast_localtime(&ts, &tm, NULL))
                                                strftime(p, sizeof(prompt) - strlen(prompt), "%H:%M:%S", &tm);
                                        break;
                                case '#': /* process console or remote? */
@@ -1860,7 +1901,7 @@ static char **ast_el_strtoarr(char *buf)
                        }
                }
 
-               match_list[matches++] = strdup(retstr);
+               match_list[matches++] = ast_strdup(retstr);
        }
 
        if (!match_list)
@@ -1916,7 +1957,7 @@ static int ast_cli_display_match_list(char **matches, int len, int max)
                        /* Don't print dupes */
                        if ( (matches[idx+1] != NULL && strcmp(matches[idx], matches[idx+1]) == 0 ) ) {
                                i--;
-                               free(matches[idx]);
+                               ast_free(matches[idx]);
                                matches[idx] = NULL;
                                continue;
                        }
@@ -1924,7 +1965,7 @@ static int ast_cli_display_match_list(char **matches, int len, int max)
                        numoutput++;
                        numoutputline++;
                        fprintf(stdout, "%-*s  ", max, matches[idx]);
-                       free(matches[idx]);
+                       ast_free(matches[idx]);
                        matches[idx] = NULL;
                }
                if (numoutputline > 0)
@@ -1993,7 +2034,7 @@ static char *cli_complete(EditLine *el, int ch)
                        mbuf[mlen] = '\0';
 
                        matches = ast_el_strtoarr(mbuf);
-                       free(mbuf);
+                       ast_free(mbuf);
                } else
                        matches = (char **) NULL;
        } else {
@@ -2039,8 +2080,8 @@ static char *cli_complete(EditLine *el, int ch)
                        }
                }
                for (i = 0; matches[i]; i++)
-                       free(matches[i]);
-               free(matches);
+                       ast_free(matches[i]);
+               ast_free(matches);
        }
 
        return (char *)(long)retval;
@@ -2191,6 +2232,9 @@ static void ast_remotecontrol(char * data)
        for (;;) {
                ebuf = (char *)el_gets(el, &num);
 
+               if (!ebuf)
+                       break;
+
                if (!ast_strlen_zero(ebuf)) {
                        if (ebuf[strlen(ebuf)-1] == '\n')
                                ebuf[strlen(ebuf)-1] = '\0';
@@ -2213,7 +2257,7 @@ static int show_version(void)
 }
 
 static int show_cli_help(void) {
-       printf("Asterisk " ASTERISK_VERSION ", Copyright (C) 1999 - 2006, Digium, Inc. and others.\n");
+       printf("Asterisk " ASTERISK_VERSION ", Copyright (C) 1999 - 2007, Digium, Inc. and others.\n");
        printf("Usage: asterisk [OPTIONS]\n");
        printf("Valid Options:\n");
        printf("   -V              Display version number and exit\n");
@@ -2251,6 +2295,7 @@ static void ast_readconfig(void)
        struct ast_config *cfg;
        struct ast_variable *v;
        char *config = AST_CONFIG_FILE;
+       char hostname[MAXHOSTNAMELEN] = "";
 
        if (ast_opt_override_config) {
                cfg = ast_config_load(ast_config_AST_CONFIG_FILE);
@@ -2400,8 +2445,27 @@ static void ast_readconfig(void)
                        ast_copy_string(ast_config_AST_RUN_GROUP, v->value, sizeof(ast_config_AST_RUN_GROUP));
                } else if (!strcasecmp(v->name, "systemname")) {
                        ast_copy_string(ast_config_AST_SYSTEM_NAME, v->value, sizeof(ast_config_AST_SYSTEM_NAME));
+               } else if (!strcasecmp(v->name, "autosystemname")) {
+                       if (ast_true(v->value)) {
+                               if (!gethostname(hostname, sizeof(hostname) - 1))
+                                       ast_copy_string(ast_config_AST_SYSTEM_NAME, hostname, sizeof(ast_config_AST_SYSTEM_NAME));
+                               else {
+                                       if (ast_strlen_zero(ast_config_AST_SYSTEM_NAME)){
+                                               ast_copy_string(ast_config_AST_SYSTEM_NAME, "localhost", sizeof(ast_config_AST_SYSTEM_NAME));
+                                       }
+                                       ast_log(LOG_ERROR, "Cannot obtain hostname for this system.  Using '%s' instead.\n", ast_config_AST_SYSTEM_NAME);
+                               }
+                       }
                } else if (!strcasecmp(v->name, "languageprefix")) {
                        ast_language_is_prefix = ast_true(v->value);
+#if defined(HAVE_SYSINFO)
+               } else if (!strcasecmp(v->name, "minmemfree")) {
+                       /* specify the minimum amount of free memory to retain.  Asterisk should stop accepting new calls
+                        * if the amount of free memory falls below this watermark */
+                       if ((sscanf(v->value, "%ld", &option_minmemfree) != 1) || (option_minmemfree < 0)) {
+                               option_minmemfree = 0;
+                       }
+#endif
                }
        }
        ast_config_destroy(cfg);
@@ -2462,6 +2526,7 @@ int main(int argc, char *argv[])
        ast_alaw_init();
        callerid_init();
        ast_builtins_init();
+       ast_event_init();
        ast_utils_init();
        tdd_init();
        /* When Asterisk restarts after it has dropped the root privileges,
@@ -2472,8 +2537,15 @@ int main(int argc, char *argv[])
        if (getenv("HOME")) 
                snprintf(filename, sizeof(filename), "%s/.asterisk_history", getenv("HOME"));
        /* Check for options */
-       while ((c = getopt(argc, argv, "mtThfFdvVqprRgciInx:U:G:C:L:M:")) != -1) {
+       while ((c = getopt(argc, argv, "mtThfFdvVqprRgciInx:U:G:C:L:M:e:")) != -1) {
                switch (c) {
+#if defined(HAVE_SYSINFO)
+               case 'e':
+                       if ((sscanf(&optarg[1], "%ld", &option_minmemfree) != 1) || (option_minmemfree < 0)) {
+                               option_minmemfree = 0;
+                       }
+                       break;
+#endif
 #if HAVE_WORKING_FORK
                case 'F':
                        ast_set_flag(&ast_options, AST_OPT_FLAG_ALWAYS_FORK);
@@ -2782,7 +2854,7 @@ int main(int argc, char *argv[])
 
        threadstorage_init();
 
-       if (load_modules(1)) {          /* Load modules */
+       if (load_modules(1)) {          /* Load modules, pre-load only */
                printf(term_quit());
                exit(1);
        }
@@ -2878,13 +2950,9 @@ int main(int argc, char *argv[])
                /* Console stuff now... */
                /* Register our quit function */
                char title[256];
-               pthread_attr_t attr;
                pthread_t dont_care;
 
-               pthread_attr_init(&attr);
-               pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
-               ast_pthread_create(&dont_care, &attr, monitor_sig_flags, NULL);
-               pthread_attr_destroy(&attr);
+               ast_pthread_create_detached(&dont_care, NULL, monitor_sig_flags, NULL);
 
                set_icon("Asterisk");
                snprintf(title, sizeof(title), "Asterisk Console on '%s' (pid %ld)", hostname, (long)ast_mainpid);
@@ -2892,12 +2960,14 @@ int main(int argc, char *argv[])
 
                for (;;) {
                        buf = (char *)el_gets(el, &num);
-                       if (buf) {
-                               if (buf[strlen(buf)-1] == '\n')
-                                       buf[strlen(buf)-1] = '\0';
+                       if (!buf)
+                               break;
+
+                       if (buf[strlen(buf)-1] == '\n')
+                               buf[strlen(buf)-1] = '\0';
+                       consolehandler((char *)buf);
 
-                               consolehandler((char *)buf);
-                       } else if (ast_opt_remote && (write(STDOUT_FILENO, "\nUse EXIT or QUIT to exit the asterisk console\n",
+                       if (!buf && ast_opt_remote && (write(STDOUT_FILENO, "\nUse EXIT or QUIT to exit the asterisk console\n",
                                   strlen("\nUse EXIT or QUIT to exit the asterisk console\n")) < 0)) {
                                /* Whoa, stdout disappeared from under us... Make /dev/null's */
                                int fd;