asterisk.c 50 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939
  1. /*
  2. * Asterisk -- A telephony toolkit for Linux.
  3. *
  4. * Top level source file for asterisk
  5. *
  6. * Copyright (C) 1999-2004, Digium, Inc.
  7. *
  8. * Mark Spencer <markster@digium.com>
  9. *
  10. * This program is free software, distributed under the terms of
  11. * the GNU General Public License
  12. */
  13. #include <unistd.h>
  14. #include <stdlib.h>
  15. #include <sys/poll.h>
  16. #include <asterisk/logger.h>
  17. #include <asterisk/options.h>
  18. #include <asterisk/cli.h>
  19. #include <asterisk/channel.h>
  20. #include <asterisk/ulaw.h>
  21. #include <asterisk/alaw.h>
  22. #include <asterisk/callerid.h>
  23. #include <asterisk/module.h>
  24. #include <asterisk/image.h>
  25. #include <asterisk/tdd.h>
  26. #include <asterisk/term.h>
  27. #include <asterisk/manager.h>
  28. #include <asterisk/pbx.h>
  29. #include <asterisk/enum.h>
  30. #include <asterisk/rtp.h>
  31. #include <asterisk/app.h>
  32. #include <asterisk/lock.h>
  33. #include <asterisk/utils.h>
  34. #include <asterisk/file.h>
  35. #include <sys/resource.h>
  36. #include <fcntl.h>
  37. #include <stdio.h>
  38. #include <signal.h>
  39. #include <sched.h>
  40. #include <asterisk/io.h>
  41. #include <asterisk/lock.h>
  42. #include <sys/socket.h>
  43. #include <sys/un.h>
  44. #include <sys/wait.h>
  45. #include <string.h>
  46. #include <errno.h>
  47. #include <ctype.h>
  48. #include "editline/histedit.h"
  49. #include "asterisk.h"
  50. #include <asterisk/config.h>
  51. #include <asterisk/config_pvt.h>
  52. #include <sys/resource.h>
  53. #include <grp.h>
  54. #include <pwd.h>
  55. #if defined(__FreeBSD__) || defined( __NetBSD__ )
  56. #include <netdb.h>
  57. #endif
  58. #define AST_MAX_CONNECTS 128
  59. #define NUM_MSGS 64
  60. #define WELCOME_MESSAGE ast_verbose( "Asterisk " ASTERISK_VERSION ", Copyright (C) 1999-2004 Digium.\n"); \
  61. ast_verbose( "Written by Mark Spencer <markster@digium.com>\n"); \
  62. ast_verbose( "=========================================================================\n")
  63. int option_verbose=0;
  64. int option_debug=0;
  65. int option_nofork=0;
  66. int option_quiet=0;
  67. int option_console=0;
  68. int option_highpriority=0;
  69. int option_remote=0;
  70. int option_exec=0;
  71. int option_initcrypto=0;
  72. int option_nocolor;
  73. int option_dumpcore = 0;
  74. int option_cache_record_files = 0;
  75. int option_overrideconfig = 0;
  76. int option_reconnect = 0;
  77. int fully_booted = 0;
  78. char record_cache_dir[AST_CACHE_DIR_LEN] = AST_TMP_DIR;
  79. static int ast_socket = -1; /* UNIX Socket for allowing remote control */
  80. static int ast_consock = -1; /* UNIX Socket for controlling another asterisk */
  81. int ast_mainpid;
  82. struct console {
  83. int fd; /* File descriptor */
  84. int p[2]; /* Pipe */
  85. pthread_t t; /* Thread of handler */
  86. };
  87. static struct ast_atexit {
  88. void (*func)(void);
  89. struct ast_atexit *next;
  90. } *atexits = NULL;
  91. AST_MUTEX_DEFINE_STATIC(atexitslock);
  92. time_t ast_startuptime;
  93. time_t ast_lastreloadtime;
  94. static History *el_hist = NULL;
  95. static EditLine *el = NULL;
  96. static char *remotehostname;
  97. struct console consoles[AST_MAX_CONNECTS];
  98. char defaultlanguage[MAX_LANGUAGE] = DEFAULT_LANGUAGE;
  99. static int ast_el_add_history(char *);
  100. static int ast_el_read_history(char *);
  101. static int ast_el_write_history(char *);
  102. char ast_config_AST_CONFIG_DIR[AST_CONFIG_MAX_PATH];
  103. char ast_config_AST_CONFIG_FILE[AST_CONFIG_MAX_PATH];
  104. char ast_config_AST_MODULE_DIR[AST_CONFIG_MAX_PATH];
  105. char ast_config_AST_SPOOL_DIR[AST_CONFIG_MAX_PATH];
  106. char ast_config_AST_VAR_DIR[AST_CONFIG_MAX_PATH];
  107. char ast_config_AST_LOG_DIR[AST_CONFIG_MAX_PATH];
  108. char ast_config_AST_AGI_DIR[AST_CONFIG_MAX_PATH];
  109. char ast_config_AST_DB[AST_CONFIG_MAX_PATH];
  110. char ast_config_AST_KEY_DIR[AST_CONFIG_MAX_PATH];
  111. char ast_config_AST_PID[AST_CONFIG_MAX_PATH];
  112. char ast_config_AST_SOCKET[AST_CONFIG_MAX_PATH];
  113. char ast_config_AST_RUN_DIR[AST_CONFIG_MAX_PATH];
  114. static char *_argv[256];
  115. static int shuttingdown = 0;
  116. static int restartnow = 0;
  117. static pthread_t consolethread = AST_PTHREADT_NULL;
  118. int ast_register_atexit(void (*func)(void))
  119. {
  120. int res = -1;
  121. struct ast_atexit *ae;
  122. ast_unregister_atexit(func);
  123. ae = malloc(sizeof(struct ast_atexit));
  124. ast_mutex_lock(&atexitslock);
  125. if (ae) {
  126. memset(ae, 0, sizeof(struct ast_atexit));
  127. ae->next = atexits;
  128. ae->func = func;
  129. atexits = ae;
  130. res = 0;
  131. }
  132. ast_mutex_unlock(&atexitslock);
  133. return res;
  134. }
  135. void ast_unregister_atexit(void (*func)(void))
  136. {
  137. struct ast_atexit *ae, *prev = NULL;
  138. ast_mutex_lock(&atexitslock);
  139. ae = atexits;
  140. while(ae) {
  141. if (ae->func == func) {
  142. if (prev)
  143. prev->next = ae->next;
  144. else
  145. atexits = ae->next;
  146. break;
  147. }
  148. prev = ae;
  149. ae = ae->next;
  150. }
  151. ast_mutex_unlock(&atexitslock);
  152. }
  153. static int fdprint(int fd, const char *s)
  154. {
  155. return write(fd, s, strlen(s) + 1);
  156. }
  157. /* NULL handler so we can collect the child exit status */
  158. static void null_sig_handler(int signal)
  159. {
  160. }
  161. int ast_safe_system(const char *s)
  162. {
  163. /* XXX This function needs some optimization work XXX */
  164. pid_t pid;
  165. int x;
  166. int res;
  167. struct rusage rusage;
  168. int status;
  169. void (*prev_handler) = signal(SIGCHLD, null_sig_handler);
  170. pid = fork();
  171. if (pid == 0) {
  172. /* Close file descriptors and launch system command */
  173. for (x=STDERR_FILENO + 1; x<4096;x++) {
  174. close(x);
  175. }
  176. res = execl("/bin/sh", "/bin/sh", "-c", s, NULL);
  177. exit(1);
  178. } else if (pid > 0) {
  179. for(;;) {
  180. res = wait4(pid, &status, 0, &rusage);
  181. if (res > -1) {
  182. if (WIFEXITED(status))
  183. res = WEXITSTATUS(status);
  184. else
  185. res = -1;
  186. break;
  187. } else {
  188. if (errno != EINTR)
  189. break;
  190. }
  191. }
  192. } else {
  193. ast_log(LOG_WARNING, "Fork failed: %s\n", strerror(errno));
  194. res = -1;
  195. }
  196. signal(SIGCHLD, prev_handler);
  197. return res;
  198. }
  199. /*
  200. * write the string to all attached console clients
  201. */
  202. static void ast_network_puts(const char *string)
  203. {
  204. int x;
  205. for (x=0;x<AST_MAX_CONNECTS; x++) {
  206. if (consoles[x].fd > -1)
  207. fdprint(consoles[x].p[1], string);
  208. }
  209. }
  210. /*
  211. * write the string to the console, and all attached
  212. * console clients
  213. */
  214. void ast_console_puts(const char *string)
  215. {
  216. fputs(string, stdout);
  217. fflush(stdout);
  218. ast_network_puts(string);
  219. }
  220. static void network_verboser(const char *s, int pos, int replace, int complete)
  221. /* ARGUSED */
  222. {
  223. if (replace) {
  224. char *t = alloca(strlen(s) + 2);
  225. if (t) {
  226. sprintf(t, "\r%s", s);
  227. if (complete)
  228. ast_network_puts(t);
  229. } else {
  230. ast_log(LOG_ERROR, "Out of memory\n");
  231. ast_network_puts(s);
  232. }
  233. } else {
  234. if (complete)
  235. ast_network_puts(s);
  236. }
  237. }
  238. static pthread_t lthread;
  239. static void *netconsole(void *vconsole)
  240. {
  241. struct console *con = vconsole;
  242. char hostname[MAXHOSTNAMELEN]="";
  243. char tmp[512];
  244. int res;
  245. struct pollfd fds[2];
  246. if (gethostname(hostname, sizeof(hostname)-1))
  247. strncpy(hostname, "<Unknown>", sizeof(hostname)-1);
  248. snprintf(tmp, sizeof(tmp), "%s/%d/%s\n", hostname, ast_mainpid, ASTERISK_VERSION);
  249. fdprint(con->fd, tmp);
  250. for(;;) {
  251. fds[0].fd = con->fd;
  252. fds[0].events = POLLIN;
  253. fds[1].fd = con->p[0];
  254. fds[1].events = POLLIN;
  255. res = poll(fds, 2, -1);
  256. if (res < 0) {
  257. if (errno != EINTR)
  258. ast_log(LOG_WARNING, "poll returned < 0: %s\n", strerror(errno));
  259. continue;
  260. }
  261. if (fds[0].revents) {
  262. res = read(con->fd, tmp, sizeof(tmp));
  263. if (res < 1) {
  264. break;
  265. }
  266. tmp[res] = 0;
  267. ast_cli_command(con->fd, tmp);
  268. }
  269. if (fds[1].revents) {
  270. res = read(con->p[0], tmp, sizeof(tmp));
  271. if (res < 1) {
  272. ast_log(LOG_ERROR, "read returned %d\n", res);
  273. break;
  274. }
  275. res = write(con->fd, tmp, res);
  276. if (res < 1)
  277. break;
  278. }
  279. }
  280. if (option_verbose > 2)
  281. ast_verbose(VERBOSE_PREFIX_3 "Remote UNIX connection disconnected\n");
  282. close(con->fd);
  283. close(con->p[0]);
  284. close(con->p[1]);
  285. con->fd = -1;
  286. return NULL;
  287. }
  288. static void *listener(void *unused)
  289. {
  290. struct sockaddr_un sun;
  291. int s;
  292. int len;
  293. int x;
  294. int flags;
  295. struct pollfd fds[1];
  296. pthread_attr_t attr;
  297. pthread_attr_init(&attr);
  298. pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
  299. for(;;) {
  300. if (ast_socket < 0)
  301. return NULL;
  302. fds[0].fd = ast_socket;
  303. fds[0].events= POLLIN;
  304. s = poll(fds, 1, -1);
  305. if (s < 0) {
  306. if (errno != EINTR)
  307. ast_log(LOG_WARNING, "poll returned error: %s\n", strerror(errno));
  308. continue;
  309. }
  310. len = sizeof(sun);
  311. s = accept(ast_socket, (struct sockaddr *)&sun, &len);
  312. if (s < 0) {
  313. if (errno != EINTR)
  314. ast_log(LOG_WARNING, "Accept returned %d: %s\n", s, strerror(errno));
  315. } else {
  316. for (x=0;x<AST_MAX_CONNECTS;x++) {
  317. if (consoles[x].fd < 0) {
  318. if (socketpair(AF_LOCAL, SOCK_STREAM, 0, consoles[x].p)) {
  319. ast_log(LOG_ERROR, "Unable to create pipe: %s\n", strerror(errno));
  320. consoles[x].fd = -1;
  321. fdprint(s, "Server failed to create pipe\n");
  322. close(s);
  323. break;
  324. }
  325. flags = fcntl(consoles[x].p[1], F_GETFL);
  326. fcntl(consoles[x].p[1], F_SETFL, flags | O_NONBLOCK);
  327. consoles[x].fd = s;
  328. if (ast_pthread_create(&consoles[x].t, &attr, netconsole, &consoles[x])) {
  329. ast_log(LOG_ERROR, "Unable to spawn thread to handle connection: %s\n", strerror(errno));
  330. consoles[x].fd = -1;
  331. fdprint(s, "Server failed to spawn thread\n");
  332. close(s);
  333. }
  334. break;
  335. }
  336. }
  337. if (x >= AST_MAX_CONNECTS) {
  338. fdprint(s, "No more connections allowed\n");
  339. ast_log(LOG_WARNING, "No more connections allowed\n");
  340. close(s);
  341. } else if (consoles[x].fd > -1) {
  342. if (option_verbose > 2)
  343. ast_verbose(VERBOSE_PREFIX_3 "Remote UNIX connection\n");
  344. }
  345. }
  346. }
  347. return NULL;
  348. }
  349. static int ast_makesocket(void)
  350. {
  351. struct sockaddr_un sun;
  352. int res;
  353. int x;
  354. for (x=0;x<AST_MAX_CONNECTS;x++)
  355. consoles[x].fd = -1;
  356. unlink((char *)ast_config_AST_SOCKET);
  357. ast_socket = socket(PF_LOCAL, SOCK_STREAM, 0);
  358. if (ast_socket < 0) {
  359. ast_log(LOG_WARNING, "Unable to create control socket: %s\n", strerror(errno));
  360. return -1;
  361. }
  362. memset(&sun, 0, sizeof(sun));
  363. sun.sun_family = AF_LOCAL;
  364. strncpy(sun.sun_path, (char *)ast_config_AST_SOCKET, sizeof(sun.sun_path)-1);
  365. res = bind(ast_socket, (struct sockaddr *)&sun, sizeof(sun));
  366. if (res) {
  367. ast_log(LOG_WARNING, "Unable to bind socket to %s: %s\n", (char *)ast_config_AST_SOCKET, strerror(errno));
  368. close(ast_socket);
  369. ast_socket = -1;
  370. return -1;
  371. }
  372. res = listen(ast_socket, 2);
  373. if (res < 0) {
  374. ast_log(LOG_WARNING, "Unable to listen on socket %s: %s\n", (char *)ast_config_AST_SOCKET, strerror(errno));
  375. close(ast_socket);
  376. ast_socket = -1;
  377. return -1;
  378. }
  379. ast_register_verbose(network_verboser);
  380. ast_pthread_create(&lthread, NULL, listener, NULL);
  381. return 0;
  382. }
  383. static int ast_tryconnect(void)
  384. {
  385. struct sockaddr_un sun;
  386. int res;
  387. ast_consock = socket(PF_LOCAL, SOCK_STREAM, 0);
  388. if (ast_consock < 0) {
  389. ast_log(LOG_WARNING, "Unable to create socket: %s\n", strerror(errno));
  390. return 0;
  391. }
  392. memset(&sun, 0, sizeof(sun));
  393. sun.sun_family = AF_LOCAL;
  394. strncpy(sun.sun_path, (char *)ast_config_AST_SOCKET, sizeof(sun.sun_path)-1);
  395. res = connect(ast_consock, (struct sockaddr *)&sun, sizeof(sun));
  396. if (res) {
  397. close(ast_consock);
  398. ast_consock = -1;
  399. return 0;
  400. } else
  401. return 1;
  402. }
  403. static void urg_handler(int num)
  404. {
  405. /* Called by soft_hangup to interrupt the poll, read, or other
  406. system call. We don't actually need to do anything though. */
  407. /* Cannot EVER ast_log from within a signal handler */
  408. if (option_debug)
  409. printf("Urgent handler\n");
  410. signal(num, urg_handler);
  411. return;
  412. }
  413. static void hup_handler(int num)
  414. {
  415. if (option_verbose > 1)
  416. printf("Received HUP signal -- Reloading configs\n");
  417. if (restartnow)
  418. execvp(_argv[0], _argv);
  419. /* XXX This could deadlock XXX */
  420. ast_module_reload(NULL);
  421. }
  422. static void child_handler(int sig)
  423. {
  424. /* Must not ever ast_log or ast_verbose within signal handler */
  425. int n, status;
  426. /*
  427. * Reap all dead children -- not just one
  428. */
  429. for (n = 0; wait4(-1, &status, WNOHANG, NULL) > 0; n++)
  430. ;
  431. if (n == 0 && option_debug)
  432. printf("Huh? Child handler, but nobody there?\n");
  433. }
  434. static void set_title(char *text)
  435. {
  436. /* Set an X-term or screen title */
  437. if (getenv("TERM") && strstr(getenv("TERM"), "xterm"))
  438. fprintf(stdout, "\033]2;%s\007", text);
  439. }
  440. static void set_icon(char *text)
  441. {
  442. if (getenv("TERM") && strstr(getenv("TERM"), "xterm"))
  443. fprintf(stdout, "\033]1;%s\007", text);
  444. }
  445. static int set_priority(int pri)
  446. {
  447. struct sched_param sched;
  448. memset(&sched, 0, sizeof(sched));
  449. /* We set ourselves to a high priority, that we might pre-empt everything
  450. else. If your PBX has heavy activity on it, this is a good thing. */
  451. #ifdef __linux__
  452. if (pri) {
  453. sched.sched_priority = 10;
  454. if (sched_setscheduler(0, SCHED_RR, &sched)) {
  455. ast_log(LOG_WARNING, "Unable to set high priority\n");
  456. return -1;
  457. } else
  458. if (option_verbose)
  459. ast_verbose("Set to realtime thread\n");
  460. } else {
  461. sched.sched_priority = 0;
  462. if (sched_setscheduler(0, SCHED_OTHER, &sched)) {
  463. ast_log(LOG_WARNING, "Unable to set normal priority\n");
  464. return -1;
  465. }
  466. }
  467. #else
  468. if (pri) {
  469. if (setpriority(PRIO_PROCESS, 0, -10) == -1) {
  470. ast_log(LOG_WARNING, "Unable to set high priority\n");
  471. return -1;
  472. } else
  473. if (option_verbose)
  474. ast_verbose("Set to high priority\n");
  475. } else {
  476. if (setpriority(PRIO_PROCESS, 0, 0) == -1) {
  477. ast_log(LOG_WARNING, "Unable to set normal priority\n");
  478. return -1;
  479. }
  480. }
  481. #endif
  482. return 0;
  483. }
  484. static void ast_run_atexits(void)
  485. {
  486. struct ast_atexit *ae;
  487. ast_mutex_lock(&atexitslock);
  488. ae = atexits;
  489. while(ae) {
  490. if (ae->func)
  491. ae->func();
  492. ae = ae->next;
  493. }
  494. ast_mutex_unlock(&atexitslock);
  495. }
  496. static void quit_handler(int num, int nice, int safeshutdown, int restart)
  497. {
  498. char filename[80] = "";
  499. time_t s,e;
  500. int x;
  501. if (safeshutdown) {
  502. shuttingdown = 1;
  503. if (!nice) {
  504. /* Begin shutdown routine, hanging up active channels */
  505. ast_begin_shutdown(1);
  506. if (option_verbose && option_console)
  507. ast_verbose("Beginning asterisk %s....\n", restart ? "restart" : "shutdown");
  508. time(&s);
  509. for(;;) {
  510. time(&e);
  511. /* Wait up to 15 seconds for all channels to go away */
  512. if ((e - s) > 15)
  513. break;
  514. if (!ast_active_channels())
  515. break;
  516. if (!shuttingdown)
  517. break;
  518. /* Sleep 1/10 of a second */
  519. usleep(100000);
  520. }
  521. } else {
  522. if (nice < 2)
  523. ast_begin_shutdown(0);
  524. if (option_verbose && option_console)
  525. ast_verbose("Waiting for inactivity to perform %s...\n", restart ? "restart" : "halt");
  526. for(;;) {
  527. if (!ast_active_channels())
  528. break;
  529. if (!shuttingdown)
  530. break;
  531. sleep(1);
  532. }
  533. }
  534. if (!shuttingdown) {
  535. if (option_verbose && option_console)
  536. ast_verbose("Asterisk %s cancelled.\n", restart ? "restart" : "shutdown");
  537. return;
  538. }
  539. }
  540. if (option_console || option_remote) {
  541. if (getenv("HOME"))
  542. snprintf(filename, sizeof(filename), "%s/.asterisk_history", getenv("HOME"));
  543. if (!ast_strlen_zero(filename))
  544. ast_el_write_history(filename);
  545. if (el != NULL)
  546. el_end(el);
  547. if (el_hist != NULL)
  548. history_end(el_hist);
  549. }
  550. if (option_verbose)
  551. ast_verbose("Executing last minute cleanups\n");
  552. ast_run_atexits();
  553. /* Called on exit */
  554. if (option_verbose && option_console)
  555. ast_verbose("Asterisk %s ending (%d).\n", ast_active_channels() ? "uncleanly" : "cleanly", num);
  556. else if (option_debug)
  557. ast_log(LOG_DEBUG, "Asterisk ending (%d).\n", num);
  558. manager_event(EVENT_FLAG_SYSTEM, "Shutdown", "Shutdown: %s\r\nRestart: %s\r\n", ast_active_channels() ? "Uncleanly" : "Cleanly", restart ? "True" : "False");
  559. if (ast_socket > -1) {
  560. close(ast_socket);
  561. ast_socket = -1;
  562. }
  563. if (ast_consock > -1)
  564. close(ast_consock);
  565. if (ast_socket > -1)
  566. unlink((char *)ast_config_AST_SOCKET);
  567. if (!option_remote) unlink((char *)ast_config_AST_PID);
  568. printf(term_quit());
  569. if (restart) {
  570. if (option_verbose || option_console)
  571. ast_verbose("Preparing for Asterisk restart...\n");
  572. /* Mark all FD's for closing on exec */
  573. for (x=3;x<32768;x++) {
  574. fcntl(x, F_SETFD, FD_CLOEXEC);
  575. }
  576. if (option_verbose || option_console)
  577. ast_verbose("Restarting Asterisk NOW...\n");
  578. restartnow = 1;
  579. /* close logger */
  580. close_logger();
  581. /* If there is a consolethread running send it a SIGHUP
  582. so it can execvp, otherwise we can do it ourselves */
  583. if (consolethread != AST_PTHREADT_NULL) {
  584. pthread_kill(consolethread, SIGHUP);
  585. /* Give the signal handler some time to complete */
  586. sleep(2);
  587. } else
  588. execvp(_argv[0], _argv);
  589. } else {
  590. /* close logger */
  591. close_logger();
  592. }
  593. exit(0);
  594. }
  595. static void __quit_handler(int num)
  596. {
  597. quit_handler(num, 0, 1, 0);
  598. }
  599. static const char *fix_header(char *outbuf, int maxout, const char *s, char *cmp)
  600. {
  601. const char *c;
  602. if (!strncmp(s, cmp, strlen(cmp))) {
  603. c = s + strlen(cmp);
  604. term_color(outbuf, cmp, COLOR_GRAY, 0, maxout);
  605. return c;
  606. }
  607. return NULL;
  608. }
  609. static void console_verboser(const char *s, int pos, int replace, int complete)
  610. {
  611. char tmp[80];
  612. const char *c=NULL;
  613. /* Return to the beginning of the line */
  614. if (!pos) {
  615. fprintf(stdout, "\r");
  616. if ((c = fix_header(tmp, sizeof(tmp), s, VERBOSE_PREFIX_4)) ||
  617. (c = fix_header(tmp, sizeof(tmp), s, VERBOSE_PREFIX_3)) ||
  618. (c = fix_header(tmp, sizeof(tmp), s, VERBOSE_PREFIX_2)) ||
  619. (c = fix_header(tmp, sizeof(tmp), s, VERBOSE_PREFIX_1)))
  620. fputs(tmp, stdout);
  621. }
  622. if (c)
  623. fputs(c + pos,stdout);
  624. else
  625. fputs(s + pos,stdout);
  626. fflush(stdout);
  627. if (complete)
  628. /* Wake up a poll()ing console */
  629. if (option_console && consolethread != AST_PTHREADT_NULL)
  630. pthread_kill(consolethread, SIGURG);
  631. }
  632. static int ast_all_zeros(char *s)
  633. {
  634. while(*s) {
  635. if (*s > 32)
  636. return 0;
  637. s++;
  638. }
  639. return 1;
  640. }
  641. static void consolehandler(char *s)
  642. {
  643. printf(term_end());
  644. fflush(stdout);
  645. /* Called when readline data is available */
  646. if (s && !ast_all_zeros(s))
  647. ast_el_add_history(s);
  648. /* Give the console access to the shell */
  649. if (s) {
  650. /* The real handler for bang */
  651. if (s[0] == '!') {
  652. if (s[1])
  653. ast_safe_system(s+1);
  654. else
  655. ast_safe_system(getenv("SHELL") ? getenv("SHELL") : "/bin/sh");
  656. } else
  657. ast_cli_command(STDOUT_FILENO, s);
  658. } else
  659. fprintf(stdout, "\nUse \"quit\" to exit\n");
  660. }
  661. static int remoteconsolehandler(char *s)
  662. {
  663. int ret = 0;
  664. /* Called when readline data is available */
  665. if (s && !ast_all_zeros(s))
  666. ast_el_add_history(s);
  667. /* Give the console access to the shell */
  668. if (s) {
  669. /* The real handler for bang */
  670. if (s[0] == '!') {
  671. if (s[1])
  672. ast_safe_system(s+1);
  673. else
  674. ast_safe_system(getenv("SHELL") ? getenv("SHELL") : "/bin/sh");
  675. ret = 1;
  676. }
  677. if ((strncasecmp(s, "quit", 4) == 0 || strncasecmp(s, "exit", 4) == 0) &&
  678. (s[4] == '\0' || isspace(s[4]))) {
  679. quit_handler(0, 0, 0, 0);
  680. ret = 1;
  681. }
  682. } else
  683. fprintf(stdout, "\nUse \"quit\" to exit\n");
  684. return ret;
  685. }
  686. static char quit_help[] =
  687. "Usage: quit\n"
  688. " Exits Asterisk.\n";
  689. static char abort_halt_help[] =
  690. "Usage: abort shutdown\n"
  691. " Causes Asterisk to abort an executing shutdown or restart, and resume normal\n"
  692. " call operations.\n";
  693. static char shutdown_now_help[] =
  694. "Usage: stop now\n"
  695. " Shuts down a running Asterisk immediately, hanging up all active calls .\n";
  696. static char shutdown_gracefully_help[] =
  697. "Usage: stop gracefully\n"
  698. " Causes Asterisk to not accept new calls, and exit when all\n"
  699. " active calls have terminated normally.\n";
  700. static char shutdown_when_convenient_help[] =
  701. "Usage: stop when convenient\n"
  702. " Causes Asterisk to perform a shutdown when all active calls have ended.\n";
  703. static char restart_now_help[] =
  704. "Usage: restart now\n"
  705. " Causes Asterisk to hangup all calls and exec() itself performing a cold\n"
  706. " restart.\n";
  707. static char restart_gracefully_help[] =
  708. "Usage: restart gracefully\n"
  709. " Causes Asterisk to stop accepting new calls and exec() itself performing a cold\n"
  710. " restart when all active calls have ended.\n";
  711. static char restart_when_convenient_help[] =
  712. "Usage: restart when convenient\n"
  713. " Causes Asterisk to perform a cold restart when all active calls have ended.\n";
  714. static char bang_help[] =
  715. "Usage: !<command>\n"
  716. " Executes a given shell command\n";
  717. #if 0
  718. static int handle_quit(int fd, int argc, char *argv[])
  719. {
  720. if (argc != 1)
  721. return RESULT_SHOWUSAGE;
  722. quit_handler(0, 0, 1, 0);
  723. return RESULT_SUCCESS;
  724. }
  725. #endif
  726. static int no_more_quit(int fd, int argc, char *argv[])
  727. {
  728. if (argc != 1)
  729. return RESULT_SHOWUSAGE;
  730. ast_cli(fd, "The QUIT and EXIT commands may no longer be used to shutdown the PBX.\n"
  731. "Please use STOP NOW instead, if you wish to shutdown the PBX.\n");
  732. return RESULT_SUCCESS;
  733. }
  734. static int handle_shutdown_now(int fd, int argc, char *argv[])
  735. {
  736. if (argc != 2)
  737. return RESULT_SHOWUSAGE;
  738. quit_handler(0, 0 /* Not nice */, 1 /* safely */, 0 /* not restart */);
  739. return RESULT_SUCCESS;
  740. }
  741. static int handle_shutdown_gracefully(int fd, int argc, char *argv[])
  742. {
  743. if (argc != 2)
  744. return RESULT_SHOWUSAGE;
  745. quit_handler(0, 1 /* nicely */, 1 /* safely */, 0 /* no restart */);
  746. return RESULT_SUCCESS;
  747. }
  748. static int handle_shutdown_when_convenient(int fd, int argc, char *argv[])
  749. {
  750. if (argc != 3)
  751. return RESULT_SHOWUSAGE;
  752. quit_handler(0, 2 /* really nicely */, 1 /* safely */, 0 /* don't restart */);
  753. return RESULT_SUCCESS;
  754. }
  755. static int handle_restart_now(int fd, int argc, char *argv[])
  756. {
  757. if (argc != 2)
  758. return RESULT_SHOWUSAGE;
  759. quit_handler(0, 0 /* not nicely */, 1 /* safely */, 1 /* restart */);
  760. return RESULT_SUCCESS;
  761. }
  762. static int handle_restart_gracefully(int fd, int argc, char *argv[])
  763. {
  764. if (argc != 2)
  765. return RESULT_SHOWUSAGE;
  766. quit_handler(0, 1 /* nicely */, 1 /* safely */, 1 /* restart */);
  767. return RESULT_SUCCESS;
  768. }
  769. static int handle_restart_when_convenient(int fd, int argc, char *argv[])
  770. {
  771. if (argc != 3)
  772. return RESULT_SHOWUSAGE;
  773. quit_handler(0, 2 /* really nicely */, 1 /* safely */, 1 /* restart */);
  774. return RESULT_SUCCESS;
  775. }
  776. static int handle_abort_halt(int fd, int argc, char *argv[])
  777. {
  778. if (argc != 2)
  779. return RESULT_SHOWUSAGE;
  780. ast_cancel_shutdown();
  781. shuttingdown = 0;
  782. return RESULT_SUCCESS;
  783. }
  784. static int handle_bang(int fd, int argc, char *argv[])
  785. {
  786. return RESULT_SUCCESS;
  787. }
  788. #define ASTERISK_PROMPT "*CLI> "
  789. #define ASTERISK_PROMPT2 "%s*CLI> "
  790. static struct ast_cli_entry aborthalt = { { "abort", "halt", NULL }, handle_abort_halt, "Cancel a running halt", abort_halt_help };
  791. static struct ast_cli_entry quit = { { "quit", NULL }, no_more_quit, "Exit Asterisk", quit_help };
  792. static struct ast_cli_entry astexit = { { "exit", NULL }, no_more_quit, "Exit Asterisk", quit_help };
  793. static struct ast_cli_entry astshutdownnow = { { "stop", "now", NULL }, handle_shutdown_now, "Shut down Asterisk immediately", shutdown_now_help };
  794. static struct ast_cli_entry astshutdowngracefully = { { "stop", "gracefully", NULL }, handle_shutdown_gracefully, "Gracefully shut down Asterisk", shutdown_gracefully_help };
  795. static struct ast_cli_entry astshutdownwhenconvenient = { { "stop", "when","convenient", NULL }, handle_shutdown_when_convenient, "Shut down Asterisk at empty call volume", shutdown_when_convenient_help };
  796. static struct ast_cli_entry astrestartnow = { { "restart", "now", NULL }, handle_restart_now, "Restart Asterisk immediately", restart_now_help };
  797. static struct ast_cli_entry astrestartgracefully = { { "restart", "gracefully", NULL }, handle_restart_gracefully, "Restart Asterisk gracefully", restart_gracefully_help };
  798. static struct ast_cli_entry astrestartwhenconvenient= { { "restart", "when", "convenient", NULL }, handle_restart_when_convenient, "Restart Asterisk at empty call volume", restart_when_convenient_help };
  799. static struct ast_cli_entry astbang = { { "!", NULL }, handle_bang, "Execute a shell command", bang_help };
  800. static int ast_el_read_char(EditLine *el, char *cp)
  801. {
  802. int num_read=0;
  803. int lastpos=0;
  804. struct pollfd fds[2];
  805. int res;
  806. int max;
  807. char buf[512];
  808. for (;;) {
  809. max = 1;
  810. fds[0].fd = ast_consock;
  811. fds[0].events = POLLIN;
  812. if (!option_exec) {
  813. fds[1].fd = STDIN_FILENO;
  814. fds[1].events = POLLIN;
  815. max++;
  816. }
  817. res = poll(fds, max, -1);
  818. if (res < 0) {
  819. if (errno == EINTR)
  820. continue;
  821. ast_log(LOG_ERROR, "poll failed: %s\n", strerror(errno));
  822. break;
  823. }
  824. if (!option_exec && fds[1].revents) {
  825. num_read = read(STDIN_FILENO, cp, 1);
  826. if (num_read < 1) {
  827. break;
  828. } else
  829. return (num_read);
  830. }
  831. if (fds[0].revents) {
  832. res = read(ast_consock, buf, sizeof(buf) - 1);
  833. /* if the remote side disappears exit */
  834. if (res < 1) {
  835. fprintf(stderr, "\nDisconnected from Asterisk server\n");
  836. if (!option_reconnect) {
  837. quit_handler(0, 0, 0, 0);
  838. } else {
  839. int tries;
  840. int reconnects_per_second = 20;
  841. fprintf(stderr, "Attempting to reconnect for 30 seconds\n");
  842. for (tries=0;tries<30 * reconnects_per_second;tries++) {
  843. if (ast_tryconnect()) {
  844. fprintf(stderr, "Reconnect succeeded after %.3f seconds\n", 1.0 / reconnects_per_second * tries);
  845. printf(term_quit());
  846. WELCOME_MESSAGE;
  847. break;
  848. } else {
  849. usleep(1000000 / reconnects_per_second);
  850. }
  851. }
  852. if (tries >= 30 * reconnects_per_second) {
  853. fprintf(stderr, "Failed to reconnect for 30 seconds. Quitting.\n");
  854. quit_handler(0, 0, 0, 0);
  855. }
  856. }
  857. }
  858. buf[res] = '\0';
  859. if (!option_exec && !lastpos)
  860. write(STDOUT_FILENO, "\r", 1);
  861. write(STDOUT_FILENO, buf, res);
  862. if ((buf[res-1] == '\n') || (buf[res-2] == '\n')) {
  863. *cp = CC_REFRESH;
  864. return(1);
  865. } else {
  866. lastpos = 1;
  867. }
  868. }
  869. }
  870. *cp = '\0';
  871. return (0);
  872. }
  873. static char *cli_prompt(EditLine *el)
  874. {
  875. static char prompt[200];
  876. char *pfmt;
  877. int color_used=0;
  878. char term_code[20];
  879. if ((pfmt = getenv("ASTERISK_PROMPT"))) {
  880. char *t = pfmt, *p = prompt;
  881. memset(prompt, 0, sizeof(prompt));
  882. while (*t != '\0' && *p < sizeof(prompt)) {
  883. if (*t == '%') {
  884. char hostname[MAXHOSTNAMELEN]="";
  885. int i;
  886. struct timeval tv;
  887. struct tm tm;
  888. #ifdef linux
  889. FILE *LOADAVG;
  890. #endif
  891. int fgcolor = COLOR_WHITE, bgcolor = COLOR_BLACK;
  892. t++;
  893. switch (*t) {
  894. case 'C': /* color */
  895. t++;
  896. if (sscanf(t, "%d;%d%n", &fgcolor, &bgcolor, &i) == 2) {
  897. strncat(p, term_color_code(term_code, fgcolor, bgcolor, sizeof(term_code)),sizeof(prompt) - strlen(prompt) - 1);
  898. t += i - 1;
  899. } else if (sscanf(t, "%d%n", &fgcolor, &i) == 1) {
  900. strncat(p, term_color_code(term_code, fgcolor, 0, sizeof(term_code)),sizeof(prompt) - strlen(prompt) - 1);
  901. t += i - 1;
  902. }
  903. /* If the color has been reset correctly, then there's no need to reset it later */
  904. if ((fgcolor == COLOR_WHITE) && (bgcolor == COLOR_BLACK)) {
  905. color_used = 0;
  906. } else {
  907. color_used = 1;
  908. }
  909. break;
  910. case 'd': /* date */
  911. memset(&tm, 0, sizeof(struct tm));
  912. gettimeofday(&tv, NULL);
  913. if (localtime_r(&(tv.tv_sec), &tm)) {
  914. strftime(p, sizeof(prompt) - strlen(prompt), "%Y-%m-%d", &tm);
  915. }
  916. break;
  917. case 'h': /* hostname */
  918. if (!gethostname(hostname, sizeof(hostname) - 1)) {
  919. strncat(p, hostname, sizeof(prompt) - strlen(prompt) - 1);
  920. } else {
  921. strncat(p, "localhost", sizeof(prompt) - strlen(prompt) - 1);
  922. }
  923. break;
  924. case 'H': /* short hostname */
  925. if (!gethostname(hostname, sizeof(hostname) - 1)) {
  926. for (i=0;i<sizeof(hostname);i++) {
  927. if (hostname[i] == '.') {
  928. hostname[i] = '\0';
  929. break;
  930. }
  931. }
  932. strncat(p, hostname, sizeof(prompt) - strlen(prompt) - 1);
  933. } else {
  934. strncat(p, "localhost", sizeof(prompt) - strlen(prompt) - 1);
  935. }
  936. break;
  937. #ifdef linux
  938. case 'l': /* load avg */
  939. t++;
  940. if ((LOADAVG = fopen("/proc/loadavg", "r"))) {
  941. float avg1, avg2, avg3;
  942. int actproc, totproc, npid, which;
  943. fscanf(LOADAVG, "%f %f %f %d/%d %d",
  944. &avg1, &avg2, &avg3, &actproc, &totproc, &npid);
  945. if (sscanf(t, "%d", &which) == 1) {
  946. switch (which) {
  947. case 1:
  948. snprintf(p, sizeof(prompt) - strlen(prompt), "%.2f", avg1);
  949. break;
  950. case 2:
  951. snprintf(p, sizeof(prompt) - strlen(prompt), "%.2f", avg2);
  952. break;
  953. case 3:
  954. snprintf(p, sizeof(prompt) - strlen(prompt), "%.2f", avg3);
  955. break;
  956. case 4:
  957. snprintf(p, sizeof(prompt) - strlen(prompt), "%d/%d", actproc, totproc);
  958. break;
  959. case 5:
  960. snprintf(p, sizeof(prompt) - strlen(prompt), "%d", npid);
  961. break;
  962. }
  963. }
  964. }
  965. break;
  966. #endif
  967. case 't': /* time */
  968. memset(&tm, 0, sizeof(struct tm));
  969. gettimeofday(&tv, NULL);
  970. if (localtime_r(&(tv.tv_sec), &tm)) {
  971. strftime(p, sizeof(prompt) - strlen(prompt), "%H:%M:%S", &tm);
  972. }
  973. break;
  974. case '#': /* process console or remote? */
  975. if (! option_remote) {
  976. strncat(p, "#", sizeof(prompt) - strlen(prompt) - 1);
  977. } else {
  978. strncat(p, ">", sizeof(prompt) - strlen(prompt) - 1);
  979. }
  980. break;
  981. case '%': /* literal % */
  982. strncat(p, "%", sizeof(prompt) - strlen(prompt) - 1);
  983. break;
  984. case '\0': /* % is last character - prevent bug */
  985. t--;
  986. break;
  987. }
  988. while (*p != '\0') {
  989. p++;
  990. }
  991. t++;
  992. } else {
  993. *p = *t;
  994. p++;
  995. t++;
  996. }
  997. }
  998. if (color_used) {
  999. /* Force colors back to normal at end */
  1000. term_color_code(term_code, COLOR_WHITE, COLOR_BLACK, sizeof(term_code));
  1001. if (strlen(term_code) > sizeof(prompt) - strlen(prompt)) {
  1002. strncat(prompt + sizeof(prompt) - strlen(term_code) - 1, term_code, strlen(term_code));
  1003. } else {
  1004. strncat(p, term_code, sizeof(term_code));
  1005. }
  1006. }
  1007. } else if (remotehostname)
  1008. snprintf(prompt, sizeof(prompt), ASTERISK_PROMPT2, remotehostname);
  1009. else
  1010. snprintf(prompt, sizeof(prompt), ASTERISK_PROMPT);
  1011. return(prompt);
  1012. }
  1013. static char **ast_el_strtoarr(char *buf)
  1014. {
  1015. char **match_list = NULL, *retstr;
  1016. size_t match_list_len;
  1017. int matches = 0;
  1018. match_list_len = 1;
  1019. while ( (retstr = strsep(&buf, " ")) != NULL) {
  1020. if (!strcmp(retstr, AST_CLI_COMPLETE_EOF))
  1021. break;
  1022. if (matches + 1 >= match_list_len) {
  1023. match_list_len <<= 1;
  1024. match_list = realloc(match_list, match_list_len * sizeof(char *));
  1025. }
  1026. match_list[matches++] = strdup(retstr);
  1027. }
  1028. if (!match_list)
  1029. return (char **) NULL;
  1030. if (matches>= match_list_len)
  1031. match_list = realloc(match_list, (match_list_len + 1) * sizeof(char *));
  1032. match_list[matches] = (char *) NULL;
  1033. return match_list;
  1034. }
  1035. static int ast_el_sort_compare(const void *i1, const void *i2)
  1036. {
  1037. char *s1, *s2;
  1038. s1 = ((char **)i1)[0];
  1039. s2 = ((char **)i2)[0];
  1040. return strcasecmp(s1, s2);
  1041. }
  1042. static int ast_cli_display_match_list(char **matches, int len, int max)
  1043. {
  1044. int i, idx, limit, count;
  1045. int screenwidth = 0;
  1046. int numoutput = 0, numoutputline = 0;
  1047. screenwidth = ast_get_termcols(STDOUT_FILENO);
  1048. /* find out how many entries can be put on one line, with two spaces between strings */
  1049. limit = screenwidth / (max + 2);
  1050. if (limit == 0)
  1051. limit = 1;
  1052. /* how many lines of output */
  1053. count = len / limit;
  1054. if (count * limit < len)
  1055. count++;
  1056. idx = 1;
  1057. qsort(&matches[0], (size_t)(len + 1), sizeof(char *), ast_el_sort_compare);
  1058. for (; count > 0; count--) {
  1059. numoutputline = 0;
  1060. for (i=0; i < limit && matches[idx]; i++, idx++) {
  1061. /* Don't print dupes */
  1062. if ( (matches[idx+1] != NULL && strcmp(matches[idx], matches[idx+1]) == 0 ) ) {
  1063. i--;
  1064. free(matches[idx]);
  1065. matches[idx] = NULL;
  1066. continue;
  1067. }
  1068. numoutput++; numoutputline++;
  1069. fprintf(stdout, "%-*s ", max, matches[idx]);
  1070. free(matches[idx]);
  1071. matches[idx] = NULL;
  1072. }
  1073. if (numoutputline > 0)
  1074. fprintf(stdout, "\n");
  1075. }
  1076. return numoutput;
  1077. }
  1078. static char *cli_complete(EditLine *el, int ch)
  1079. {
  1080. int len=0;
  1081. char *ptr;
  1082. int nummatches = 0;
  1083. char **matches;
  1084. int retval = CC_ERROR;
  1085. char buf[2048];
  1086. int res;
  1087. LineInfo *lf = (LineInfo *)el_line(el);
  1088. *(char *)lf->cursor = '\0';
  1089. ptr = (char *)lf->cursor;
  1090. if (ptr) {
  1091. while (ptr > lf->buffer) {
  1092. if (isspace(*ptr)) {
  1093. ptr++;
  1094. break;
  1095. }
  1096. ptr--;
  1097. }
  1098. }
  1099. len = lf->cursor - ptr;
  1100. if (option_remote) {
  1101. snprintf(buf, sizeof(buf),"_COMMAND NUMMATCHES \"%s\" \"%s\"", lf->buffer, ptr);
  1102. fdprint(ast_consock, buf);
  1103. res = read(ast_consock, buf, sizeof(buf));
  1104. buf[res] = '\0';
  1105. nummatches = atoi(buf);
  1106. if (nummatches > 0) {
  1107. char *mbuf;
  1108. int mlen = 0, maxmbuf = 2048;
  1109. /* Start with a 2048 byte buffer */
  1110. mbuf = malloc(maxmbuf);
  1111. if (!mbuf)
  1112. return (char *)(CC_ERROR);
  1113. snprintf(buf, sizeof(buf),"_COMMAND MATCHESARRAY \"%s\" \"%s\"", lf->buffer, ptr);
  1114. fdprint(ast_consock, buf);
  1115. res = 0;
  1116. mbuf[0] = '\0';
  1117. while (!strstr(mbuf, AST_CLI_COMPLETE_EOF) && res != -1) {
  1118. if (mlen + 1024 > maxmbuf) {
  1119. /* Every step increment buffer 1024 bytes */
  1120. maxmbuf += 1024;
  1121. mbuf = realloc(mbuf, maxmbuf);
  1122. if (!mbuf)
  1123. return (char *)(CC_ERROR);
  1124. }
  1125. /* Only read 1024 bytes at a time */
  1126. res = read(ast_consock, mbuf + mlen, 1024);
  1127. if (res > 0)
  1128. mlen += res;
  1129. }
  1130. mbuf[mlen] = '\0';
  1131. matches = ast_el_strtoarr(mbuf);
  1132. free(mbuf);
  1133. } else
  1134. matches = (char **) NULL;
  1135. } else {
  1136. nummatches = ast_cli_generatornummatches((char *)lf->buffer,ptr);
  1137. matches = ast_cli_completion_matches((char *)lf->buffer,ptr);
  1138. }
  1139. if (matches) {
  1140. int i;
  1141. int matches_num, maxlen, match_len;
  1142. if (matches[0][0] != '\0') {
  1143. el_deletestr(el, (int) len);
  1144. el_insertstr(el, matches[0]);
  1145. retval = CC_REFRESH;
  1146. }
  1147. if (nummatches == 1) {
  1148. /* Found an exact match */
  1149. el_insertstr(el, " ");
  1150. retval = CC_REFRESH;
  1151. } else {
  1152. /* Must be more than one match */
  1153. for (i=1, maxlen=0; matches[i]; i++) {
  1154. match_len = strlen(matches[i]);
  1155. if (match_len > maxlen)
  1156. maxlen = match_len;
  1157. }
  1158. matches_num = i - 1;
  1159. if (matches_num >1) {
  1160. fprintf(stdout, "\n");
  1161. ast_cli_display_match_list(matches, nummatches, maxlen);
  1162. retval = CC_REDISPLAY;
  1163. } else {
  1164. el_insertstr(el," ");
  1165. retval = CC_REFRESH;
  1166. }
  1167. }
  1168. free(matches);
  1169. }
  1170. return (char *)(long)retval;
  1171. }
  1172. static int ast_el_initialize(void)
  1173. {
  1174. HistEvent ev;
  1175. char *editor = getenv("AST_EDITOR");
  1176. if (el != NULL)
  1177. el_end(el);
  1178. if (el_hist != NULL)
  1179. history_end(el_hist);
  1180. el = el_init("asterisk", stdin, stdout, stderr);
  1181. el_set(el, EL_PROMPT, cli_prompt);
  1182. el_set(el, EL_EDITMODE, 1);
  1183. el_set(el, EL_EDITOR, editor ? editor : "emacs");
  1184. el_hist = history_init();
  1185. if (!el || !el_hist)
  1186. return -1;
  1187. /* setup history with 100 entries */
  1188. history(el_hist, &ev, H_SETSIZE, 100);
  1189. el_set(el, EL_HIST, history, el_hist);
  1190. el_set(el, EL_ADDFN, "ed-complete", "Complete argument", cli_complete);
  1191. /* Bind <tab> to command completion */
  1192. el_set(el, EL_BIND, "^I", "ed-complete", NULL);
  1193. /* Bind ? to command completion */
  1194. el_set(el, EL_BIND, "?", "ed-complete", NULL);
  1195. /* Bind ^D to redisplay */
  1196. el_set(el, EL_BIND, "^D", "ed-redisplay", NULL);
  1197. return 0;
  1198. }
  1199. static int ast_el_add_history(char *buf)
  1200. {
  1201. HistEvent ev;
  1202. if (el_hist == NULL || el == NULL)
  1203. ast_el_initialize();
  1204. if (strlen(buf) > 256)
  1205. return 0;
  1206. return (history(el_hist, &ev, H_ENTER, buf));
  1207. }
  1208. static int ast_el_write_history(char *filename)
  1209. {
  1210. HistEvent ev;
  1211. if (el_hist == NULL || el == NULL)
  1212. ast_el_initialize();
  1213. return (history(el_hist, &ev, H_SAVE, filename));
  1214. }
  1215. static int ast_el_read_history(char *filename)
  1216. {
  1217. char buf[256];
  1218. FILE *f;
  1219. int ret = -1;
  1220. if (el_hist == NULL || el == NULL)
  1221. ast_el_initialize();
  1222. if ((f = fopen(filename, "r")) == NULL)
  1223. return ret;
  1224. while (!feof(f)) {
  1225. fgets(buf, sizeof(buf), f);
  1226. if (!strcmp(buf, "_HiStOrY_V2_\n"))
  1227. continue;
  1228. if (ast_all_zeros(buf))
  1229. continue;
  1230. if ((ret = ast_el_add_history(buf)) == -1)
  1231. break;
  1232. }
  1233. fclose(f);
  1234. return ret;
  1235. }
  1236. static void ast_remotecontrol(char * data)
  1237. {
  1238. char buf[80];
  1239. int res;
  1240. char filename[80] = "";
  1241. char *hostname;
  1242. char *cpid;
  1243. char *version;
  1244. int pid;
  1245. char tmp[80];
  1246. char *stringp=NULL;
  1247. char *ebuf;
  1248. int num = 0;
  1249. read(ast_consock, buf, sizeof(buf));
  1250. if (data)
  1251. write(ast_consock, data, strlen(data) + 1);
  1252. stringp=buf;
  1253. hostname = strsep(&stringp, "/");
  1254. cpid = strsep(&stringp, "/");
  1255. version = strsep(&stringp, "\n");
  1256. if (!version)
  1257. version = "<Version Unknown>";
  1258. stringp=hostname;
  1259. strsep(&stringp, ".");
  1260. if (cpid)
  1261. pid = atoi(cpid);
  1262. else
  1263. pid = -1;
  1264. snprintf(tmp, sizeof(tmp), "set verbose atleast %d", option_verbose);
  1265. fdprint(ast_consock, tmp);
  1266. snprintf(tmp, sizeof(tmp), "set debug atleast %d", option_debug);
  1267. fdprint(ast_consock, tmp);
  1268. ast_verbose("Connected to Asterisk %s currently running on %s (pid = %d)\n", version, hostname, pid);
  1269. remotehostname = hostname;
  1270. if (getenv("HOME"))
  1271. snprintf(filename, sizeof(filename), "%s/.asterisk_history", getenv("HOME"));
  1272. if (el_hist == NULL || el == NULL)
  1273. ast_el_initialize();
  1274. el_set(el, EL_GETCFN, ast_el_read_char);
  1275. if (!ast_strlen_zero(filename))
  1276. ast_el_read_history(filename);
  1277. ast_cli_register(&quit);
  1278. ast_cli_register(&astexit);
  1279. #if 0
  1280. ast_cli_register(&astshutdown);
  1281. #endif
  1282. if (option_exec && data) { /* hack to print output then exit if asterisk -rx is used */
  1283. char tempchar;
  1284. struct pollfd fds[0];
  1285. fds[0].fd = ast_consock;
  1286. fds[0].events = POLLIN;
  1287. fds[0].revents = 0;
  1288. while(poll(fds, 1, 100) > 0) {
  1289. ast_el_read_char(el, &tempchar);
  1290. }
  1291. return;
  1292. }
  1293. for(;;) {
  1294. ebuf = (char *)el_gets(el, &num);
  1295. if (ebuf && !ast_strlen_zero(ebuf)) {
  1296. if (ebuf[strlen(ebuf)-1] == '\n')
  1297. ebuf[strlen(ebuf)-1] = '\0';
  1298. if (!remoteconsolehandler(ebuf)) {
  1299. res = write(ast_consock, ebuf, strlen(ebuf) + 1);
  1300. if (res < 1) {
  1301. ast_log(LOG_WARNING, "Unable to write: %s\n", strerror(errno));
  1302. break;
  1303. }
  1304. }
  1305. }
  1306. }
  1307. printf("\nDisconnected from Asterisk server\n");
  1308. }
  1309. static int show_version(void)
  1310. {
  1311. printf("Asterisk " ASTERISK_VERSION "\n");
  1312. return 0;
  1313. }
  1314. static int show_cli_help(void) {
  1315. printf("Asterisk " ASTERISK_VERSION ", Copyright (C) 2000-2004, Digium.\n");
  1316. printf("Usage: asterisk [OPTIONS]\n");
  1317. printf("Valid Options:\n");
  1318. printf(" -V Display version number and exit\n");
  1319. printf(" -C <configfile> Use an alternate configuration file\n");
  1320. printf(" -G <group> Run as a group other than the caller\n");
  1321. printf(" -U <user> Run as a user other than the caller\n");
  1322. printf(" -c Provide console CLI\n");
  1323. printf(" -d Enable extra debugging\n");
  1324. printf(" -f Do not fork\n");
  1325. printf(" -g Dump core in case of a crash\n");
  1326. printf(" -h This help screen\n");
  1327. printf(" -i Initialize crypto keys at startup\n");
  1328. printf(" -n Disable console colorization\n");
  1329. printf(" -p Run as pseudo-realtime thread\n");
  1330. printf(" -q Quiet mode (suppress output)\n");
  1331. printf(" -r Connect to Asterisk on this machine\n");
  1332. printf(" -R Connect to Asterisk, and attempt to reconnect if disconnected\n");
  1333. printf(" -t Record soundfiles in /var/tmp and move them where they belong after they are done.\n");
  1334. printf(" -v Increase verbosity (multiple v's = more verbose)\n");
  1335. printf(" -x <cmd> Execute command <cmd> (only valid with -r)\n");
  1336. printf("\n");
  1337. return 0;
  1338. }
  1339. static void ast_readconfig(void) {
  1340. struct ast_config *cfg;
  1341. struct ast_variable *v;
  1342. char *config = ASTCONFPATH;
  1343. if (option_overrideconfig == 1) {
  1344. cfg = ast_load((char *)ast_config_AST_CONFIG_FILE);
  1345. if (!cfg)
  1346. ast_log(LOG_WARNING, "Unable to open specified master config file '%s', using builtin defaults\n", ast_config_AST_CONFIG_FILE);
  1347. } else {
  1348. cfg = ast_load(config);
  1349. }
  1350. /* init with buildtime config */
  1351. strncpy((char *)ast_config_AST_CONFIG_DIR,AST_CONFIG_DIR,sizeof(ast_config_AST_CONFIG_DIR)-1);
  1352. strncpy((char *)ast_config_AST_SPOOL_DIR,AST_SPOOL_DIR,sizeof(ast_config_AST_SPOOL_DIR)-1);
  1353. strncpy((char *)ast_config_AST_MODULE_DIR,AST_MODULE_DIR,sizeof(ast_config_AST_VAR_DIR)-1);
  1354. strncpy((char *)ast_config_AST_VAR_DIR,AST_VAR_DIR,sizeof(ast_config_AST_VAR_DIR)-1);
  1355. strncpy((char *)ast_config_AST_LOG_DIR,AST_LOG_DIR,sizeof(ast_config_AST_LOG_DIR)-1);
  1356. strncpy((char *)ast_config_AST_AGI_DIR,AST_AGI_DIR,sizeof(ast_config_AST_AGI_DIR)-1);
  1357. strncpy((char *)ast_config_AST_DB,AST_DB,sizeof(ast_config_AST_DB)-1);
  1358. strncpy((char *)ast_config_AST_KEY_DIR,AST_KEY_DIR,sizeof(ast_config_AST_KEY_DIR)-1);
  1359. strncpy((char *)ast_config_AST_PID,AST_PID,sizeof(ast_config_AST_PID)-1);
  1360. strncpy((char *)ast_config_AST_SOCKET,AST_SOCKET,sizeof(ast_config_AST_SOCKET)-1);
  1361. strncpy((char *)ast_config_AST_RUN_DIR,AST_RUN_DIR,sizeof(ast_config_AST_RUN_DIR)-1);
  1362. /* no asterisk.conf? no problem, use buildtime config! */
  1363. if (!cfg) {
  1364. return;
  1365. }
  1366. v = ast_variable_browse(cfg, "directories");
  1367. while(v) {
  1368. if (!strcasecmp(v->name, "astetcdir")) {
  1369. strncpy((char *)ast_config_AST_CONFIG_DIR,v->value,sizeof(ast_config_AST_CONFIG_DIR)-1);
  1370. } else if (!strcasecmp(v->name, "astspooldir")) {
  1371. strncpy((char *)ast_config_AST_SPOOL_DIR,v->value,sizeof(ast_config_AST_SPOOL_DIR)-1);
  1372. } else if (!strcasecmp(v->name, "astvarlibdir")) {
  1373. strncpy((char *)ast_config_AST_VAR_DIR,v->value,sizeof(ast_config_AST_VAR_DIR)-1);
  1374. snprintf((char *)ast_config_AST_DB,sizeof(ast_config_AST_DB),"%s/%s",v->value,"astdb");
  1375. } else if (!strcasecmp(v->name, "astlogdir")) {
  1376. strncpy((char *)ast_config_AST_LOG_DIR,v->value,sizeof(ast_config_AST_LOG_DIR)-1);
  1377. } else if (!strcasecmp(v->name, "astagidir")) {
  1378. strncpy((char *)ast_config_AST_AGI_DIR,v->value,sizeof(ast_config_AST_AGI_DIR)-1);
  1379. } else if (!strcasecmp(v->name, "astrundir")) {
  1380. snprintf((char *)ast_config_AST_PID,sizeof(ast_config_AST_PID),"%s/%s",v->value,"asterisk.pid");
  1381. snprintf((char *)ast_config_AST_SOCKET,sizeof(ast_config_AST_SOCKET),"%s/%s",v->value,"asterisk.ctl");
  1382. strncpy((char *)ast_config_AST_RUN_DIR,v->value,sizeof(ast_config_AST_RUN_DIR)-1);
  1383. } else if (!strcasecmp(v->name, "astmoddir")) {
  1384. strncpy((char *)ast_config_AST_MODULE_DIR,v->value,sizeof(ast_config_AST_MODULE_DIR)-1);
  1385. }
  1386. v = v->next;
  1387. }
  1388. v = ast_variable_browse(cfg, "options");
  1389. while(v) {
  1390. if(!strcasecmp(v->name, "verbose")) {
  1391. option_verbose= atoi(v->value);
  1392. } else if (!strcasecmp(v->name, "debug")) {
  1393. option_debug= ast_true(v->value);
  1394. } else if (!strcasecmp(v->name, "nofork")) {
  1395. option_nofork = ast_true(v->value);
  1396. } else if (!strcasecmp(v->name, "quiet")) {
  1397. option_quiet = ast_true(v->value);
  1398. } else if (!strcasecmp(v->name, "console")) {
  1399. option_console = ast_true(v->value);
  1400. } else if (!strcasecmp(v->name, "highpriority")) {
  1401. option_highpriority = ast_true(v->value);
  1402. } else if (!strcasecmp(v->name, "initcrypto")) {
  1403. option_initcrypto = ast_true(v->value);
  1404. } else if (!strcasecmp(v->name, "nocolor")) {
  1405. option_nocolor = ast_true(v->value);
  1406. } else if (!strcasecmp(v->name, "dumpcore")) {
  1407. option_dumpcore = ast_true(v->value);
  1408. } else if (!strcasecmp(v->name, "cache_record_files")) {
  1409. option_cache_record_files = ast_true(v->value);
  1410. } else if (!strcasecmp(v->name, "record_cache_dir")) {
  1411. strncpy(record_cache_dir,v->value,AST_CACHE_DIR_LEN);
  1412. }
  1413. v = v->next;
  1414. }
  1415. ast_destroy(cfg);
  1416. }
  1417. int main(int argc, char *argv[])
  1418. {
  1419. int c;
  1420. char filename[80] = "";
  1421. char hostname[MAXHOSTNAMELEN]="";
  1422. char tmp[80];
  1423. char * xarg = NULL;
  1424. int x;
  1425. FILE *f;
  1426. sigset_t sigs;
  1427. int num;
  1428. char *buf;
  1429. char *runuser=NULL, *rungroup=NULL;
  1430. struct pollfd silly_macos[1];
  1431. /* Remember original args for restart */
  1432. if (argc > sizeof(_argv) / sizeof(_argv[0]) - 1) {
  1433. fprintf(stderr, "Truncating argument size to %d\n", (int)(sizeof(_argv) / sizeof(_argv[0])) - 1);
  1434. argc = sizeof(_argv) / sizeof(_argv[0]) - 1;
  1435. }
  1436. for (x=0;x<argc;x++)
  1437. _argv[x] = argv[x];
  1438. _argv[x] = NULL;
  1439. /* if the progname is rasterisk consider it a remote console */
  1440. if ( argv[0] && (strstr(argv[0], "rasterisk")) != NULL) {
  1441. option_remote++;
  1442. option_nofork++;
  1443. }
  1444. if (gethostname(hostname, sizeof(hostname)-1))
  1445. strncpy(hostname, "<Unknown>", sizeof(hostname)-1);
  1446. ast_mainpid = getpid();
  1447. ast_ulaw_init();
  1448. ast_alaw_init();
  1449. callerid_init();
  1450. ast_utils_init();
  1451. tdd_init();
  1452. if (getenv("HOME"))
  1453. snprintf(filename, sizeof(filename), "%s/.asterisk_history", getenv("HOME"));
  1454. /* Check if we're root */
  1455. /*
  1456. if (geteuid()) {
  1457. ast_log(LOG_ERROR, "Must be run as root\n");
  1458. exit(1);
  1459. }
  1460. */
  1461. /* Check for options */
  1462. while((c=getopt(argc, argv, "thfdvVqprRgcinx:U:G:C:")) != -1) {
  1463. switch(c) {
  1464. case 'd':
  1465. option_debug++;
  1466. option_nofork++;
  1467. break;
  1468. case 'c':
  1469. option_console++;
  1470. option_nofork++;
  1471. break;
  1472. case 'f':
  1473. option_nofork++;
  1474. break;
  1475. case 'n':
  1476. option_nocolor++;
  1477. break;
  1478. case 'r':
  1479. option_remote++;
  1480. option_nofork++;
  1481. break;
  1482. case 'R':
  1483. option_remote++;
  1484. option_nofork++;
  1485. option_reconnect++;
  1486. break;
  1487. case 'p':
  1488. option_highpriority++;
  1489. break;
  1490. case 'v':
  1491. option_verbose++;
  1492. option_nofork++;
  1493. break;
  1494. case 'q':
  1495. option_quiet++;
  1496. break;
  1497. case 't':
  1498. option_cache_record_files++;
  1499. break;
  1500. case 'x':
  1501. option_exec++;
  1502. xarg = optarg;
  1503. break;
  1504. case 'C':
  1505. strncpy((char *)ast_config_AST_CONFIG_FILE,optarg,sizeof(ast_config_AST_CONFIG_FILE) - 1);
  1506. option_overrideconfig++;
  1507. break;
  1508. case 'i':
  1509. option_initcrypto++;
  1510. break;
  1511. case'g':
  1512. option_dumpcore++;
  1513. break;
  1514. case 'h':
  1515. show_cli_help();
  1516. exit(0);
  1517. case 'V':
  1518. show_version();
  1519. exit(0);
  1520. case 'U':
  1521. runuser = optarg;
  1522. break;
  1523. case 'G':
  1524. rungroup = optarg;
  1525. break;
  1526. case '?':
  1527. exit(1);
  1528. }
  1529. }
  1530. if (option_dumpcore) {
  1531. struct rlimit l;
  1532. memset(&l, 0, sizeof(l));
  1533. l.rlim_cur = RLIM_INFINITY;
  1534. l.rlim_max = RLIM_INFINITY;
  1535. if (setrlimit(RLIMIT_CORE, &l)) {
  1536. ast_log(LOG_WARNING, "Unable to disable core size resource limit: %s\n", strerror(errno));
  1537. }
  1538. }
  1539. if (option_console && !option_verbose)
  1540. ast_verbose("[ Reading Master Configuration ]");
  1541. ast_readconfig();
  1542. if (set_priority(option_highpriority)) {
  1543. exit(1);
  1544. }
  1545. if (rungroup) {
  1546. struct group *gr;
  1547. gr = getgrnam(rungroup);
  1548. if (!gr) {
  1549. ast_log(LOG_WARNING, "No such group '%s'!\n", rungroup);
  1550. exit(1);
  1551. }
  1552. if (setgid(gr->gr_gid)) {
  1553. ast_log(LOG_WARNING, "Unable to setgid to %d (%s)\n", gr->gr_gid, rungroup);
  1554. exit(1);
  1555. }
  1556. if (option_verbose)
  1557. ast_verbose("Running as group '%s'\n", rungroup);
  1558. }
  1559. if (runuser) {
  1560. struct passwd *pw;
  1561. pw = getpwnam(runuser);
  1562. if (!pw) {
  1563. ast_log(LOG_WARNING, "No such user '%s'!\n", runuser);
  1564. exit(1);
  1565. }
  1566. if (setuid(pw->pw_uid)) {
  1567. ast_log(LOG_WARNING, "Unable to setuid to %d (%s)\n", pw->pw_uid, runuser);
  1568. exit(1);
  1569. }
  1570. if (option_verbose)
  1571. ast_verbose("Running as user '%s'\n", runuser);
  1572. }
  1573. term_init();
  1574. printf(term_end());
  1575. fflush(stdout);
  1576. if (option_console && !option_verbose)
  1577. ast_verbose("[ Initializing Custom Configuration Options]");
  1578. /* custom config setup */
  1579. register_config_cli();
  1580. read_ast_cust_config();
  1581. if (option_console) {
  1582. if (el_hist == NULL || el == NULL)
  1583. ast_el_initialize();
  1584. if (!ast_strlen_zero(filename))
  1585. ast_el_read_history(filename);
  1586. }
  1587. if (ast_tryconnect()) {
  1588. /* One is already running */
  1589. if (option_remote) {
  1590. if (option_exec) {
  1591. ast_remotecontrol(xarg);
  1592. quit_handler(0, 0, 0, 0);
  1593. exit(0);
  1594. }
  1595. printf(term_quit());
  1596. ast_register_verbose(console_verboser);
  1597. WELCOME_MESSAGE;
  1598. ast_remotecontrol(NULL);
  1599. quit_handler(0, 0, 0, 0);
  1600. exit(0);
  1601. } else {
  1602. ast_log(LOG_ERROR, "Asterisk already running on %s. Use 'asterisk -r' to connect.\n", (char *)ast_config_AST_SOCKET);
  1603. printf(term_quit());
  1604. exit(1);
  1605. }
  1606. } else if (option_remote || option_exec) {
  1607. ast_log(LOG_ERROR, "Unable to connect to remote asterisk\n");
  1608. printf(term_quit());
  1609. exit(1);
  1610. }
  1611. /* Blindly write pid file since we couldn't connect */
  1612. unlink((char *)ast_config_AST_PID);
  1613. f = fopen((char *)ast_config_AST_PID, "w");
  1614. if (f) {
  1615. fprintf(f, "%d\n", getpid());
  1616. fclose(f);
  1617. } else
  1618. ast_log(LOG_WARNING, "Unable to open pid file '%s': %s\n", (char *)ast_config_AST_PID, strerror(errno));
  1619. if (!option_verbose && !option_debug && !option_nofork && !option_console) {
  1620. daemon(0,0);
  1621. /* Blindly re-write pid file since we are forking */
  1622. unlink((char *)ast_config_AST_PID);
  1623. f = fopen((char *)ast_config_AST_PID, "w");
  1624. if (f) {
  1625. fprintf(f, "%d\n", getpid());
  1626. fclose(f);
  1627. } else
  1628. ast_log(LOG_WARNING, "Unable to open pid file '%s': %s\n", (char *)ast_config_AST_PID, strerror(errno));
  1629. }
  1630. /* Test recursive mutex locking. */
  1631. if (test_for_thread_safety())
  1632. ast_verbose("Warning! Asterisk is not thread safe.\n");
  1633. ast_makesocket();
  1634. sigemptyset(&sigs);
  1635. sigaddset(&sigs, SIGHUP);
  1636. sigaddset(&sigs, SIGTERM);
  1637. sigaddset(&sigs, SIGINT);
  1638. sigaddset(&sigs, SIGPIPE);
  1639. sigaddset(&sigs, SIGWINCH);
  1640. pthread_sigmask(SIG_BLOCK, &sigs, NULL);
  1641. if (option_console || option_verbose || option_remote)
  1642. ast_register_verbose(console_verboser);
  1643. /* Print a welcome message if desired */
  1644. if (option_verbose || option_console) {
  1645. WELCOME_MESSAGE;
  1646. }
  1647. if (option_console && !option_verbose)
  1648. ast_verbose("[ Booting...");
  1649. signal(SIGURG, urg_handler);
  1650. signal(SIGINT, __quit_handler);
  1651. signal(SIGTERM, __quit_handler);
  1652. signal(SIGHUP, hup_handler);
  1653. signal(SIGCHLD, child_handler);
  1654. signal(SIGPIPE, SIG_IGN);
  1655. /* ensure that the random number generators are seeded with a different value every time
  1656. Asterisk is started
  1657. */
  1658. srand((unsigned int) getpid() + (unsigned int) time(NULL));
  1659. srandom((unsigned int) getpid() + (unsigned int) time(NULL));
  1660. if (init_logger()) {
  1661. printf(term_quit());
  1662. exit(1);
  1663. }
  1664. if (init_manager()) {
  1665. printf(term_quit());
  1666. exit(1);
  1667. }
  1668. ast_rtp_init();
  1669. if (ast_image_init()) {
  1670. printf(term_quit());
  1671. exit(1);
  1672. }
  1673. if (ast_file_init()) {
  1674. printf(term_quit());
  1675. exit(1);
  1676. }
  1677. if (load_pbx()) {
  1678. printf(term_quit());
  1679. exit(1);
  1680. }
  1681. if (load_modules()) {
  1682. printf(term_quit());
  1683. exit(1);
  1684. }
  1685. if (init_framer()) {
  1686. printf(term_quit());
  1687. exit(1);
  1688. }
  1689. if (astdb_init()) {
  1690. printf(term_quit());
  1691. exit(1);
  1692. }
  1693. if (ast_enum_init()) {
  1694. printf(term_quit());
  1695. exit(1);
  1696. }
  1697. /* sync cust config and reload some internals in case a custom config handler binded to them */
  1698. read_ast_cust_config();
  1699. reload_logger(0);
  1700. reload_manager();
  1701. ast_enum_reload();
  1702. ast_rtp_reload();
  1703. /* We might have the option of showing a console, but for now just
  1704. do nothing... */
  1705. if (option_console && !option_verbose)
  1706. ast_verbose(" ]\n");
  1707. if (option_verbose || option_console)
  1708. ast_verbose(term_color(tmp, "Asterisk Ready.\n", COLOR_BRWHITE, COLOR_BLACK, sizeof(tmp)));
  1709. if (option_nofork)
  1710. consolethread = pthread_self();
  1711. fully_booted = 1;
  1712. pthread_sigmask(SIG_UNBLOCK, &sigs, NULL);
  1713. #ifdef __AST_DEBUG_MALLOC
  1714. __ast_mm_init();
  1715. #endif
  1716. time(&ast_startuptime);
  1717. ast_cli_register(&astshutdownnow);
  1718. ast_cli_register(&astshutdowngracefully);
  1719. ast_cli_register(&astrestartnow);
  1720. ast_cli_register(&astrestartgracefully);
  1721. ast_cli_register(&astrestartwhenconvenient);
  1722. ast_cli_register(&astshutdownwhenconvenient);
  1723. ast_cli_register(&aborthalt);
  1724. ast_cli_register(&astbang);
  1725. if (option_console) {
  1726. /* Console stuff now... */
  1727. /* Register our quit function */
  1728. char title[256];
  1729. set_icon("Asterisk");
  1730. snprintf(title, sizeof(title), "Asterisk Console on '%s' (pid %d)", hostname, ast_mainpid);
  1731. set_title(title);
  1732. ast_cli_register(&quit);
  1733. ast_cli_register(&astexit);
  1734. for (;;) {
  1735. buf = (char *)el_gets(el, &num);
  1736. if (buf) {
  1737. if (buf[strlen(buf)-1] == '\n')
  1738. buf[strlen(buf)-1] = '\0';
  1739. consolehandler((char *)buf);
  1740. } else {
  1741. if (write(STDOUT_FILENO, "\nUse EXIT or QUIT to exit the asterisk console\n",
  1742. strlen("\nUse EXIT or QUIT to exit the asterisk console\n")) < 0) {
  1743. /* Whoa, stdout disappeared from under us... Make /dev/null's */
  1744. int fd;
  1745. fd = open("/dev/null", O_RDWR);
  1746. if (fd > -1) {
  1747. dup2(fd, STDOUT_FILENO);
  1748. dup2(fd, STDIN_FILENO);
  1749. } else
  1750. ast_log(LOG_WARNING, "Failed to open /dev/null to recover from dead console. Bad things will happen!\n");
  1751. break;
  1752. }
  1753. }
  1754. }
  1755. }
  1756. /* Do nothing */
  1757. for(;;)
  1758. poll(silly_macos,0, -1);
  1759. return 0;
  1760. }