asterisk.c
来自「在asterisk平台写注册命令的程序」· C语言 代码 · 共 2,332 行 · 第 1/5 页
C
2,332 行
ast_mutex_lock(&safe_system_lock); level = --safe_system_level; /* only restore the handler if we are the last one */ if (level == 0) signal(SIGCHLD, safe_system_prev_handler); ast_mutex_unlock(&safe_system_lock); return res;}/*! * write the string to all attached console clients */static void ast_network_puts(const char *string){ int x; for (x=0;x<AST_MAX_CONNECTS; x++) { if (consoles[x].fd > -1) fdprint(consoles[x].p[1], string); }}/*! * write the string to the console, and all attached * console clients */void ast_console_puts(const char *string){ fputs(string, stdout); fflush(stdout); ast_network_puts(string);}static void network_verboser(const char *s, int pos, int replace, int complete) /* ARGUSED */{ if (replace) { char *t = alloca(strlen(s) + 2); if (t) { sprintf(t, "\r%s", s); if (complete) ast_network_puts(t); } else { ast_log(LOG_ERROR, "Out of memory\n"); ast_network_puts(s); } } else { if (complete) ast_network_puts(s); }}static pthread_t lthread;static void *netconsole(void *vconsole){ struct console *con = vconsole; char hostname[MAXHOSTNAMELEN]=""; char tmp[512]; int res; struct pollfd fds[2]; if (gethostname(hostname, sizeof(hostname)-1)) ast_copy_string(hostname, "<Unknown>", sizeof(hostname)); snprintf(tmp, sizeof(tmp), "%s/%d/%s\n", hostname, ast_mainpid, ASTERISK_VERSION); fdprint(con->fd, tmp); for(;;) { fds[0].fd = con->fd; fds[0].events = POLLIN; fds[0].revents = 0; fds[1].fd = con->p[0]; fds[1].events = POLLIN; fds[1].revents = 0; res = poll(fds, 2, -1); if (res < 0) { if (errno != EINTR) ast_log(LOG_WARNING, "poll returned < 0: %s\n", strerror(errno)); continue; } if (fds[0].revents) { res = read(con->fd, tmp, sizeof(tmp)); if (res < 1) { break; } tmp[res] = 0; ast_cli_command(con->fd, tmp); } if (fds[1].revents) { res = read(con->p[0], tmp, sizeof(tmp)); if (res < 1) { ast_log(LOG_ERROR, "read returned %d\n", res); break; } res = write(con->fd, tmp, res); if (res < 1) break; } } if (option_verbose > 2) ast_verbose(VERBOSE_PREFIX_3 "Remote UNIX connection disconnected\n"); close(con->fd); close(con->p[0]); close(con->p[1]); con->fd = -1; return NULL;}static void *listener(void *unused){ struct sockaddr_un sunaddr; int s; socklen_t len; int x; int flags; struct pollfd fds[1]; pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); for(;;) { if (ast_socket < 0) return NULL; fds[0].fd = ast_socket; fds[0].events= POLLIN; s = poll(fds, 1, -1); pthread_testcancel(); if (s < 0) { if (errno != EINTR) ast_log(LOG_WARNING, "poll returned error: %s\n", strerror(errno)); continue; } len = sizeof(sunaddr); s = accept(ast_socket, (struct sockaddr *)&sunaddr, &len); if (s < 0) { if (errno != EINTR) ast_log(LOG_WARNING, "Accept returned %d: %s\n", s, strerror(errno)); } else { for (x=0;x<AST_MAX_CONNECTS;x++) { if (consoles[x].fd < 0) { if (socketpair(AF_LOCAL, SOCK_STREAM, 0, consoles[x].p)) { ast_log(LOG_ERROR, "Unable to create pipe: %s\n", strerror(errno)); consoles[x].fd = -1; fdprint(s, "Server failed to create pipe\n"); close(s); break; } flags = fcntl(consoles[x].p[1], F_GETFL); fcntl(consoles[x].p[1], F_SETFL, flags | O_NONBLOCK); consoles[x].fd = s; if (ast_pthread_create(&consoles[x].t, &attr, netconsole, &consoles[x])) { ast_log(LOG_ERROR, "Unable to spawn thread to handle connection: %s\n", strerror(errno)); close(consoles[x].p[0]); close(consoles[x].p[1]); consoles[x].fd = -1; fdprint(s, "Server failed to spawn thread\n"); close(s); } break; } } if (x >= AST_MAX_CONNECTS) { fdprint(s, "No more connections allowed\n"); ast_log(LOG_WARNING, "No more connections allowed\n"); close(s); } else if (consoles[x].fd > -1) { if (option_verbose > 2) ast_verbose(VERBOSE_PREFIX_3 "Remote UNIX connection\n"); } } } return NULL;}static int ast_makesocket(void){ struct sockaddr_un sunaddr; int res; int x; uid_t uid = -1; gid_t gid = -1; for (x = 0; x < AST_MAX_CONNECTS; x++) consoles[x].fd = -1; unlink(ast_config_AST_SOCKET); ast_socket = socket(PF_LOCAL, SOCK_STREAM, 0); if (ast_socket < 0) { ast_log(LOG_WARNING, "Unable to create control socket: %s\n", strerror(errno)); return -1; } memset(&sunaddr, 0, sizeof(sunaddr)); sunaddr.sun_family = AF_LOCAL; ast_copy_string(sunaddr.sun_path, ast_config_AST_SOCKET, sizeof(sunaddr.sun_path)); res = bind(ast_socket, (struct sockaddr *)&sunaddr, sizeof(sunaddr)); if (res) { ast_log(LOG_WARNING, "Unable to bind socket to %s: %s\n", ast_config_AST_SOCKET, strerror(errno)); close(ast_socket); ast_socket = -1; return -1; } res = listen(ast_socket, 2); if (res < 0) { ast_log(LOG_WARNING, "Unable to listen on socket %s: %s\n", ast_config_AST_SOCKET, strerror(errno)); close(ast_socket); ast_socket = -1; return -1; } ast_register_verbose(network_verboser); ast_pthread_create(<hread, NULL, listener, NULL); if (!ast_strlen_zero(ast_config_AST_CTL_OWNER)) { struct passwd *pw; if ((pw = getpwnam(ast_config_AST_CTL_OWNER)) == NULL) { ast_log(LOG_WARNING, "Unable to find uid of user %s\n", ast_config_AST_CTL_OWNER); } else { uid = pw->pw_uid; } } if (!ast_strlen_zero(ast_config_AST_CTL_GROUP)) { struct group *grp; if ((grp = getgrnam(ast_config_AST_CTL_GROUP)) == NULL) { ast_log(LOG_WARNING, "Unable to find gid of group %s\n", ast_config_AST_CTL_GROUP); } else { gid = grp->gr_gid; } } if (chown(ast_config_AST_SOCKET, uid, gid) < 0) ast_log(LOG_WARNING, "Unable to change ownership of %s: %s\n", ast_config_AST_SOCKET, strerror(errno)); if (!ast_strlen_zero(ast_config_AST_CTL_PERMISSIONS)) { int p1; mode_t p; sscanf(ast_config_AST_CTL_PERMISSIONS, "%o", &p1); p = p1; if ((chmod(ast_config_AST_SOCKET, p)) < 0) ast_log(LOG_WARNING, "Unable to change file permissions of %s: %s\n", ast_config_AST_SOCKET, strerror(errno)); } return 0;}static int ast_tryconnect(void){ struct sockaddr_un sunaddr; int res; ast_consock = socket(PF_LOCAL, SOCK_STREAM, 0); if (ast_consock < 0) { ast_log(LOG_WARNING, "Unable to create socket: %s\n", strerror(errno)); return 0; } memset(&sunaddr, 0, sizeof(sunaddr)); sunaddr.sun_family = AF_LOCAL; ast_copy_string(sunaddr.sun_path, (char *)ast_config_AST_SOCKET, sizeof(sunaddr.sun_path)); res = connect(ast_consock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)); if (res) { close(ast_consock); ast_consock = -1; return 0; } else return 1;}/*! Urgent handler Called by soft_hangup to interrupt the poll, read, or other system call. We don't actually need to do anything though. Remember: Cannot EVER ast_log from within a signal handler */static void urg_handler(int num){ signal(num, urg_handler); return;}static void hup_handler(int num){ if (option_verbose > 1) printf("Received HUP signal -- Reloading configs\n"); if (restartnow) execvp(_argv[0], _argv); /* XXX This could deadlock XXX */ ast_module_reload(NULL); signal(num, hup_handler);}static void child_handler(int sig){ /* Must not ever ast_log or ast_verbose within signal handler */ int n, status; /* * Reap all dead children -- not just one */ for (n = 0; wait4(-1, &status, WNOHANG, NULL) > 0; n++) ; if (n == 0 && option_debug) printf("Huh? Child handler, but nobody there?\n"); signal(sig, child_handler);}/*! Set an X-term or screen title */static void set_title(char *text){ if (getenv("TERM") && strstr(getenv("TERM"), "xterm")) fprintf(stdout, "\033]2;%s\007", text);}static void set_icon(char *text){ if (getenv("TERM") && strstr(getenv("TERM"), "xterm")) fprintf(stdout, "\033]1;%s\007", text);}/*! We set ourselves to a high priority, that we might pre-empt everything else. If your PBX has heavy activity on it, this is a good thing. */int ast_set_priority(int pri){ struct sched_param sched; memset(&sched, 0, sizeof(sched));#ifdef __linux__ if (pri) { sched.sched_priority = 10; if (sched_setscheduler(0, SCHED_RR, &sched)) { ast_log(LOG_WARNING, "Unable to set high priority\n"); return -1; } else if (option_verbose) ast_verbose("Set to realtime thread\n"); } else { sched.sched_priority = 0; if (sched_setscheduler(0, SCHED_OTHER, &sched)) { ast_log(LOG_WARNING, "Unable to set normal priority\n"); return -1; } }#else if (pri) { if (setpriority(PRIO_PROCESS, 0, -10) == -1) { ast_log(LOG_WARNING, "Unable to set high priority\n"); return -1; } else if (option_verbose) ast_verbose("Set to high priority\n"); } else { if (setpriority(PRIO_PROCESS, 0, 0) == -1) { ast_log(LOG_WARNING, "Unable to set normal priority\n"); return -1; } }#endif return 0;}static void ast_run_atexits(void){ struct ast_atexit *ae; ast_mutex_lock(&atexitslock); ae = atexits; while(ae) { if (ae->func) ae->func(); ae = ae->next; } ast_mutex_unlock(&atexitslock);}static void quit_handler(int num, int nice, int safeshutdown, int restart){ char filename[80] = ""; time_t s,e; int x; /* Try to get as many CDRs as possible submitted to the backend engines (if in batch mode) */ ast_cdr_engine_term(); if (safeshutdown) { shuttingdown = 1; if (!nice) { /* Begin shutdown routine, hanging up active channels */ ast_begin_shutdown(1); if (option_verbose && option_console) ast_verbose("Beginning asterisk %s....\n", restart ? "restart" : "shutdown"); time(&s); for(;;) { time(&e); /* Wait up to 15 seconds for all channels to go away */ if ((e - s) > 15) break; if (!ast_active_channels()) break; if (!shuttingdown) break; /* Sleep 1/10 of a second */ usleep(100000); } } else { if (nice < 2) ast_begin_shutdown(0); if (option_verbose && option_console) ast_verbose("Waiting for inactivity to perform %s...\n", restart ? "restart" : "halt"); for(;;) { if (!ast_active_channels()) break; if (!shuttingdown) break; sleep(1); } } if (!shuttingdown) { if (option_verbose && option_console) ast_verbose("Asterisk %s cancelled.\n", restart ? "restart" : "shutdown"); return; } } if (option_console || option_remote) { if (getenv("HOME")) snprintf(filename, sizeof(filename), "%s/.asterisk_history", getenv("HOME")); if (!ast_strlen_zero(filename)) ast_el_write_history(filename); if (el != NULL) el_end(el); if (el_hist != NULL) history_end(el_hist); } if (option_verbose) ast_verbose("Executing last minute cleanups\n"); ast_run_atexits(); /* Called on exit */ if (option_verbose && option_console) ast_verbose("Asterisk %s ending (%d).\n", ast_active_channels() ? "uncleanly" : "cleanly", num); else if (option_debug) ast_log(LOG_DEBUG, "Asterisk ending (%d).\n", num); manager_event(EVENT_FLAG_SYSTEM, "Shutdown", "Shutdown: %s\r\nRestart: %s\r\n", ast_active_channels() ? "Uncleanly" : "Cleanly", restart ? "True" : "False"); if (ast_socket > -1) { pthread_cancel(lthread); close(ast_socket); ast_socket = -1; unlink(ast_config_AST_SOCKET); } if (ast_consock > -1) close(ast_consock); if (!option_remote) unlink((char *)ast_config_AST_PID); printf(term_quit()); if (restart) { if (option_verbose || option_console) ast_verbose("Preparing for Asterisk restart...\n"); /* Mark all FD's for closing on exec */ for (x=3;x<32768;x++) { fcntl(x, F_SETFD, FD_CLOEXEC); } if (option_verbose || option_console) ast_verbose("Restarting Asterisk NOW...\n"); restartnow = 1; /* close logger */ close_logger(); /* If there is a consolethread running send it a SIGHUP so it can execvp, otherwise we can do it ourselves */ if ((consolethread != AST_PTHREADT_NULL) && (consolethread != pthread_self())) { pthread_kill(consolethread, SIGHUP); /* Give the signal handler some time to complete */ sleep(2); } else execvp(_argv[0], _argv);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?