asterisk.c 44 KB

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