static int send_waveform_to_fd(char *waveform, int length, int fd) { int res; int x; #ifdef __PPC__ char c; #endif res = fork(); if (res < 0) ast_log(LOG_WARNING, "Fork failed\n"); if (res) return res; for (x=0; x<256; x++) { if (x != fd) close(x); } if (ast_opt_high_priority) ast_set_priority(0); /*IAS */ #ifdef __PPC__ for( x=0; x<length; x+=2) { c = *(waveform+x+1); *(waveform+x+1)=*(waveform+x); *(waveform+x)=c; } #endif write(fd,waveform,length); close(fd); exit(0); }
static int send_waveform_to_fd(char *waveform, int length, int fd) { int res; #if __BYTE_ORDER == __BIG_ENDIAN int x; char c; #endif res = ast_safe_fork(0); if (res < 0) ast_log(LOG_WARNING, "Fork failed\n"); if (res) { return res; } dup2(fd, 0); ast_close_fds_above_n(0); if (ast_opt_high_priority) ast_set_priority(0); #if __BYTE_ORDER == __BIG_ENDIAN for (x = 0; x < length; x += 2) { c = *(waveform + x + 1); *(waveform + x + 1) = *(waveform + x); *(waveform + x) = c; } #endif if (write(0, waveform, length) < 0) { /* Cannot log -- all FDs are already closed */ } close(fd); _exit(0); }
static int mp3play(const char *filename, unsigned int sampling_rate, int fd) { int res; char sampling_rate_str[8]; res = ast_safe_fork(0); if (res < 0) ast_log(LOG_WARNING, "Fork failed\n"); if (res) { return res; } if (ast_opt_high_priority) ast_set_priority(0); dup2(fd, STDOUT_FILENO); ast_close_fds_above_n(STDERR_FILENO); snprintf(sampling_rate_str, 8, "%u", sampling_rate); /* Execute mpg123, but buffer if it's a net connection */ if (!strncasecmp(filename, "http://", 7) && strstr(filename, ".m3u")) { char buffer_size_str[8]; snprintf(buffer_size_str, 8, "%u", (int) 0.5*2*sampling_rate/1000); // 0.5 seconds for a live stream /* Most commonly installed in /usr/local/bin */ execl(LOCAL_MPG_123, "mpg123", "-q", "-s", "-b", buffer_size_str, "-f", "8192", "--mono", "-r", sampling_rate_str, "-@", filename, (char *)NULL); /* But many places has it in /usr/bin */ execl(MPG_123, "mpg123", "-q", "-s", "-b", buffer_size_str, "-f", "8192", "--mono", "-r", sampling_rate_str, "-@", filename, (char *)NULL); /* As a last-ditch effort, try to use PATH */ execlp("mpg123", "mpg123", "-q", "-s", "-b", buffer_size_str, "-f", "8192", "--mono", "-r", sampling_rate_str, "-@", filename, (char *)NULL); } else if (!strncasecmp(filename, "http://", 7)) { char buffer_size_str[8]; snprintf(buffer_size_str, 8, "%u", 6*2*sampling_rate/1000); // 6 seconds for a remote MP3 file /* Most commonly installed in /usr/local/bin */ execl(LOCAL_MPG_123, "mpg123", "-q", "-s", "-b", buffer_size_str, "-f", "8192", "--mono", "-r", sampling_rate_str, filename, (char *)NULL); /* But many places has it in /usr/bin */ execl(MPG_123, "mpg123", "-q", "-s", "-b", buffer_size_str, "-f", "8192", "--mono", "-r", sampling_rate_str, filename, (char *)NULL); /* As a last-ditch effort, try to use PATH */ execlp("mpg123", "mpg123", "-q", "-s", "-b", buffer_size_str, "-f", "8192", "--mono", "-r", sampling_rate_str, filename, (char *)NULL); } else if (strstr(filename, ".m3u")) { /* Most commonly installed in /usr/local/bin */ execl(LOCAL_MPG_123, "mpg123", "-q", "-z", "-s", "-f", "8192", "--mono", "-r", sampling_rate_str, "-@", filename, (char *)NULL); /* But many places has it in /usr/bin */ execl(MPG_123, "mpg123", "-q", "-z", "-s", "-f", "8192", "--mono", "-r", sampling_rate_str, "-@", filename, (char *)NULL); /* As a last-ditch effort, try to use PATH */ execlp("mpg123", "mpg123", "-q", "-z", "-s", "-f", "8192", "--mono", "-r", sampling_rate_str, "-@", filename, (char *)NULL); } else { /* Most commonly installed in /usr/local/bin */ execl(MPG_123, "mpg123", "-q", "-s", "-f", "8192", "--mono", "-r", sampling_rate_str, filename, (char *)NULL); /* But many places has it in /usr/bin */ execl(LOCAL_MPG_123, "mpg123", "-q", "-s", "-f", "8192", "--mono", "-r", sampling_rate_str, filename, (char *)NULL); /* As a last-ditch effort, try to use PATH */ execlp("mpg123", "mpg123", "-q", "-s", "-f", "8192", "--mono", "-r", sampling_rate_str, filename, (char *)NULL); } /* Can't use ast_log since FD's are closed */ fprintf(stderr, "Execute of mpg123 failed\n"); _exit(0); }
static int icesencode(char *filename, int fd) { int res; res = ast_safe_fork(0); if (res < 0) ast_log(LOG_WARNING, "Fork failed\n"); if (res) { return res; } if (ast_opt_high_priority) ast_set_priority(0); dup2(fd, STDIN_FILENO); ast_close_fds_above_n(STDERR_FILENO); /* Most commonly installed in /usr/local/bin * But many places has it in /usr/bin * As a last-ditch effort, try to use PATH */ execl(path_LOCAL "ices2", "ices", filename, SENTINEL); execl(path_BIN "ices2", "ices", filename, SENTINEL); execlp("ices2", "ices", filename, SENTINEL); ast_debug(1, "Couldn't find ices version 2, attempting to use ices version 1."); execl(path_LOCAL "ices", "ices", filename, SENTINEL); execl(path_BIN "ices", "ices", filename, SENTINEL); execlp("ices", "ices", filename, SENTINEL); ast_log(LOG_WARNING, "Execute of ices failed, could not find command.\n"); close(fd); _exit(0); }
static pid_t spawn_ras(struct ast_channel *chan, char *args) { pid_t pid; char *c; char *argv[PPP_MAX_ARGS]; int argc = 0; char *stringp=NULL; /* Start by forking */ pid = ast_safe_fork(1); if (pid) { return pid; } /* Execute RAS on File handles */ dup2(ast_channel_fd(chan, 0), STDIN_FILENO); /* Drop high priority */ if (ast_opt_high_priority) ast_set_priority(0); /* Close other file descriptors */ ast_close_fds_above_n(STDERR_FILENO); /* Reset all arguments */ memset(argv, 0, sizeof(argv)); /* First argument is executable, followed by standard arguments for DAHDI PPP */ argv[argc++] = PPP_EXEC; argv[argc++] = "nodetach"; /* And all the other arguments */ stringp=args; c = strsep(&stringp, ","); while(c && strlen(c) && (argc < (PPP_MAX_ARGS - 4))) { argv[argc++] = c; c = strsep(&stringp, ","); } argv[argc++] = "plugin"; argv[argc++] = "dahdi.so"; argv[argc++] = "stdin"; /* Finally launch PPP */ execv(PPP_EXEC, argv); fprintf(stderr, "Failed to exec PPPD!\n"); exit(1); }
static int mp3play(char *filename, int fd) { int res; int x; sigset_t fullset, oldset; sigfillset(&fullset); pthread_sigmask(SIG_BLOCK, &fullset, &oldset); res = fork(); if (res < 0) ast_log(LOG_WARNING, "Fork failed\n"); if (res) { pthread_sigmask(SIG_SETMASK, &oldset, NULL); return res; } if (ast_opt_high_priority) ast_set_priority(0); signal(SIGPIPE, SIG_DFL); pthread_sigmask(SIG_UNBLOCK, &fullset, NULL); dup2(fd, STDOUT_FILENO); for (x=STDERR_FILENO + 1;x<256;x++) { if (x != STDOUT_FILENO) close(x); } /* Execute mpg123, but buffer if it's a net connection */ if (!strncasecmp(filename, "http://", 7)) { /* Most commonly installed in /usr/local/bin */ execl(LOCAL_MPG_123, "mpg123", "-q", "-s", "-b", "1024", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL); /* But many places has it in /usr/bin */ execl(MPG_123, "mpg123", "-q", "-s", "-b", "1024","-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL); /* As a last-ditch effort, try to use PATH */ execlp("mpg123", "mpg123", "-q", "-s", "-b", "1024", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL); } else { /* Most commonly installed in /usr/local/bin */ execl(MPG_123, "mpg123", "-q", "-s", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL); /* But many places has it in /usr/bin */ execl(LOCAL_MPG_123, "mpg123", "-q", "-s", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL); /* As a last-ditch effort, try to use PATH */ execlp("mpg123", "mpg123", "-q", "-s", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL); } ast_log(LOG_WARNING, "Execute of mpg123 failed\n"); _exit(0); }
static int mp3play(const char *filename, int fd) { int res; res = ast_safe_fork(0); if (res < 0) ast_log(LOG_WARNING, "Fork failed\n"); if (res) { return res; } if (ast_opt_high_priority) ast_set_priority(0); dup2(fd, STDOUT_FILENO); ast_close_fds_above_n(STDERR_FILENO); /* Execute mpg123, but buffer if it's a net connection */ if (!strncasecmp(filename, "http://", 7)) { /* Most commonly installed in /usr/local/bin */ execl(LOCAL_MPG_123, "mpg123", "-q", "-s", "-b", "1024", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL); /* But many places has it in /usr/bin */ execl(MPG_123, "mpg123", "-q", "-s", "-b", "1024","-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL); /* As a last-ditch effort, try to use PATH */ execlp("mpg123", "mpg123", "-q", "-s", "-b", "1024", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL); } else if (strstr(filename, ".m3u")) { /* Most commonly installed in /usr/local/bin */ execl(LOCAL_MPG_123, "mpg123", "-q", "-z", "-s", "-b", "1024", "-f", "8192", "--mono", "-r", "8000", "-@", filename, (char *)NULL); /* But many places has it in /usr/bin */ execl(MPG_123, "mpg123", "-q", "-z", "-s", "-b", "1024","-f", "8192", "--mono", "-r", "8000", "-@", filename, (char *)NULL); /* As a last-ditch effort, try to use PATH */ execlp("mpg123", "mpg123", "-q", "-z", "-s", "-b", "1024", "-f", "8192", "--mono", "-r", "8000", "-@", filename, (char *)NULL); } else { /* Most commonly installed in /usr/local/bin */ execl(MPG_123, "mpg123", "-q", "-s", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL); /* But many places has it in /usr/bin */ execl(LOCAL_MPG_123, "mpg123", "-q", "-s", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL); /* As a last-ditch effort, try to use PATH */ execlp("mpg123", "mpg123", "-q", "-s", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL); } /* Can't use ast_log since FD's are closed */ fprintf(stderr, "Execute of mpg123 failed\n"); _exit(0); }
static int send_waveform_to_fd(char *waveform, int length, int fd) { int res; int x; #ifdef __PPC__ char c; #endif sigset_t fullset, oldset; sigfillset(&fullset); pthread_sigmask(SIG_BLOCK, &fullset, &oldset); res = fork(); if (res < 0) ast_log(LOG_WARNING, "Fork failed\n"); if (res) { pthread_sigmask(SIG_SETMASK, &oldset, NULL); return res; } for (x=0;x<256;x++) { if (x != fd) close(x); } if (option_highpriority) ast_set_priority(0); signal(SIGPIPE, SIG_DFL); pthread_sigmask(SIG_UNBLOCK, &fullset, NULL); /*IAS */ #ifdef __PPC__ for( x=0; x<length; x+=2) { c = *(waveform+x+1); *(waveform+x+1)=*(waveform+x); *(waveform+x)=c; } #endif write(fd,waveform,length); close(fd); exit(0); }
static int NBScatplay(int fd) { int res; res = ast_safe_fork(0); if (res < 0) { ast_log(LOG_WARNING, "Fork failed\n"); } if (res) { return res; } if (ast_opt_high_priority) ast_set_priority(0); dup2(fd, STDOUT_FILENO); ast_close_fds_above_n(STDERR_FILENO); /* Most commonly installed in /usr/local/bin */ execl(NBSCAT, "nbscat8k", "-d", (char *)NULL); execl(LOCAL_NBSCAT, "nbscat8k", "-d", (char *)NULL); fprintf(stderr, "Execute of nbscat8k failed\n"); _exit(0); }
static int mp3play(char *filename, int fd) { int res; int x; res = fork(); if (res < 0) ast_log(LOG_WARNING, "Fork failed\n"); if (res) return res; if (ast_opt_high_priority) ast_set_priority(0); dup2(fd, STDOUT_FILENO); for (x=0;x<256;x++) { if (x != STDOUT_FILENO) close(x); } /* Execute mpg123, but buffer if it's a net connection */ if (!strncasecmp(filename, "http://", 7)) { /* Most commonly installed in /usr/local/bin */ execl(LOCAL_MPG_123, "mpg123", "-q", "-s", "-b", "1024", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL); /* But many places has it in /usr/bin */ execl(MPG_123, "mpg123", "-q", "-s", "-b", "1024","-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL); /* As a last-ditch effort, try to use PATH */ execlp("mpg123", "mpg123", "-q", "-s", "-b", "1024", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL); } else { /* Most commonly installed in /usr/local/bin */ execl(MPG_123, "mpg123", "-q", "-s", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL); /* But many places has it in /usr/bin */ execl(LOCAL_MPG_123, "mpg123", "-q", "-s", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL); /* As a last-ditch effort, try to use PATH */ execlp("mpg123", "mpg123", "-q", "-s", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL); } ast_log(LOG_WARNING, "Execute of mpg123 failed\n"); return -1; }
static int app_exec(struct ast_channel *chan, void *data) { struct ast_module_user *lu; struct playlist_entry *entry; const char *args = data; int child_stdin[2] = { 0,0 }; int child_stdout[2] = { 0,0 }; int child_stderr[2] = { 0,0 }; int res = -1; int test_available_fd = -1; int gen_active = 0; int pid; char *argv[32]; int argc = 1; char *buf, *command; FILE *child_commands = NULL; FILE *child_errors = NULL; FILE *child_events = NULL; struct ivr_localuser foo = { .playlist = AST_LIST_HEAD_INIT_VALUE, .finishlist = AST_LIST_HEAD_INIT_VALUE, }; struct ivr_localuser *u = &foo; sigset_t fullset, oldset; lu = ast_module_user_add(chan); sigfillset(&fullset); pthread_sigmask(SIG_BLOCK, &fullset, &oldset); u->abort_current_sound = 0; u->chan = chan; if (ast_strlen_zero(args)) { ast_log(LOG_WARNING, "ExternalIVR requires a command to execute\n"); ast_module_user_remove(lu); return -1; } buf = ast_strdupa(data); argc = ast_app_separate_args(buf, '|', argv, sizeof(argv) / sizeof(argv[0])); if (pipe(child_stdin)) { ast_chan_log(LOG_WARNING, chan, "Could not create pipe for child input: %s\n", strerror(errno)); goto exit; } if (pipe(child_stdout)) { ast_chan_log(LOG_WARNING, chan, "Could not create pipe for child output: %s\n", strerror(errno)); goto exit; } if (pipe(child_stderr)) { ast_chan_log(LOG_WARNING, chan, "Could not create pipe for child errors: %s\n", strerror(errno)); goto exit; } if (chan->_state != AST_STATE_UP) { ast_answer(chan); } if (ast_activate_generator(chan, &gen, u) < 0) { ast_chan_log(LOG_WARNING, chan, "Failed to activate generator\n"); goto exit; } else gen_active = 1; pid = fork(); if (pid < 0) { ast_log(LOG_WARNING, "Failed to fork(): %s\n", strerror(errno)); goto exit; } if (!pid) { /* child process */ int i; signal(SIGPIPE, SIG_DFL); pthread_sigmask(SIG_UNBLOCK, &fullset, NULL); if (ast_opt_high_priority) ast_set_priority(0); dup2(child_stdin[0], STDIN_FILENO); dup2(child_stdout[1], STDOUT_FILENO); dup2(child_stderr[1], STDERR_FILENO); for (i = STDERR_FILENO + 1; i < 1024; i++) close(i); execv(argv[0], argv); fprintf(stderr, "Failed to execute '%s': %s\n", argv[0], strerror(errno)); _exit(1); } else { /* parent process */ int child_events_fd = child_stdin[1]; int child_commands_fd = child_stdout[0]; int child_errors_fd = child_stderr[0]; struct ast_frame *f; int ms; int exception; int ready_fd; int waitfds[2] = { child_errors_fd, child_commands_fd }; struct ast_channel *rchan; pthread_sigmask(SIG_SETMASK, &oldset, NULL); close(child_stdin[0]); child_stdin[0] = 0; close(child_stdout[1]); child_stdout[1] = 0; close(child_stderr[1]); child_stderr[1] = 0; if (!(child_events = fdopen(child_events_fd, "w"))) { ast_chan_log(LOG_WARNING, chan, "Could not open stream for child events\n"); goto exit; } if (!(child_commands = fdopen(child_commands_fd, "r"))) { ast_chan_log(LOG_WARNING, chan, "Could not open stream for child commands\n"); goto exit; } if (!(child_errors = fdopen(child_errors_fd, "r"))) { ast_chan_log(LOG_WARNING, chan, "Could not open stream for child errors\n"); goto exit; } test_available_fd = open("/dev/null", O_RDONLY); setvbuf(child_events, NULL, _IONBF, 0); setvbuf(child_commands, NULL, _IONBF, 0); setvbuf(child_errors, NULL, _IONBF, 0); res = 0; while (1) { if (ast_test_flag(chan, AST_FLAG_ZOMBIE)) { ast_chan_log(LOG_NOTICE, chan, "Is a zombie\n"); res = -1; break; } if (ast_check_hangup(chan)) { ast_chan_log(LOG_NOTICE, chan, "Got check_hangup\n"); send_child_event(child_events, 'H', NULL, chan); res = -1; break; } ready_fd = 0; ms = 100; errno = 0; exception = 0; rchan = ast_waitfor_nandfds(&chan, 1, waitfds, 2, &exception, &ready_fd, &ms); if (!AST_LIST_EMPTY(&u->finishlist)) { AST_LIST_LOCK(&u->finishlist); while ((entry = AST_LIST_REMOVE_HEAD(&u->finishlist, list))) { send_child_event(child_events, 'F', entry->filename, chan); free(entry); } AST_LIST_UNLOCK(&u->finishlist); } if (rchan) { /* the channel has something */ f = ast_read(chan); if (!f) { ast_chan_log(LOG_NOTICE, chan, "Returned no frame\n"); send_child_event(child_events, 'H', NULL, chan); res = -1; break; } if (f->frametype == AST_FRAME_DTMF) { send_child_event(child_events, f->subclass, NULL, chan); if (u->option_autoclear) { if (!u->abort_current_sound && !u->playing_silence) send_child_event(child_events, 'T', NULL, chan); AST_LIST_LOCK(&u->playlist); while ((entry = AST_LIST_REMOVE_HEAD(&u->playlist, list))) { send_child_event(child_events, 'D', entry->filename, chan); free(entry); } if (!u->playing_silence) u->abort_current_sound = 1; AST_LIST_UNLOCK(&u->playlist); } } else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP)) { ast_chan_log(LOG_NOTICE, chan, "Got AST_CONTROL_HANGUP\n"); send_child_event(child_events, 'H', NULL, chan); ast_frfree(f); res = -1; break; } ast_frfree(f); } else if (ready_fd == child_commands_fd) { char input[1024]; if (exception || feof(child_commands)) { ast_chan_log(LOG_WARNING, chan, "Child process went away\n"); res = -1; break; } if (!fgets(input, sizeof(input), child_commands)) continue; command = ast_strip(input); ast_chan_log(LOG_DEBUG, chan, "got command '%s'\n", input); if (strlen(input) < 4) continue; if (input[0] == 'S') { if (ast_fileexists(&input[2], NULL, u->chan->language) == -1) { ast_chan_log(LOG_WARNING, chan, "Unknown file requested '%s'\n", &input[2]); send_child_event(child_events, 'Z', NULL, chan); strcpy(&input[2], "exception"); } if (!u->abort_current_sound && !u->playing_silence) send_child_event(child_events, 'T', NULL, chan); AST_LIST_LOCK(&u->playlist); while ((entry = AST_LIST_REMOVE_HEAD(&u->playlist, list))) { send_child_event(child_events, 'D', entry->filename, chan); free(entry); } if (!u->playing_silence) u->abort_current_sound = 1; entry = make_entry(&input[2]); if (entry) AST_LIST_INSERT_TAIL(&u->playlist, entry, list); AST_LIST_UNLOCK(&u->playlist); } else if (input[0] == 'A') { if (ast_fileexists(&input[2], NULL, u->chan->language) == -1) { ast_chan_log(LOG_WARNING, chan, "Unknown file requested '%s'\n", &input[2]); send_child_event(child_events, 'Z', NULL, chan); strcpy(&input[2], "exception"); } entry = make_entry(&input[2]); if (entry) { AST_LIST_LOCK(&u->playlist); AST_LIST_INSERT_TAIL(&u->playlist, entry, list); AST_LIST_UNLOCK(&u->playlist); } } else if (input[0] == 'H') { ast_chan_log(LOG_NOTICE, chan, "Hanging up: %s\n", &input[2]); send_child_event(child_events, 'H', NULL, chan); break; } else if (input[0] == 'O') { if (!strcasecmp(&input[2], "autoclear")) u->option_autoclear = 1; else if (!strcasecmp(&input[2], "noautoclear")) u->option_autoclear = 0; else ast_chan_log(LOG_WARNING, chan, "Unknown option requested '%s'\n", &input[2]); } } else if (ready_fd == child_errors_fd) { char input[1024]; if (exception || (dup2(child_commands_fd, test_available_fd) == -1) || feof(child_errors)) { ast_chan_log(LOG_WARNING, chan, "Child process went away\n"); res = -1; break; } if (fgets(input, sizeof(input), child_errors)) { command = ast_strip(input); ast_chan_log(LOG_NOTICE, chan, "stderr: %s\n", command); } } else if ((ready_fd < 0) && ms) { if (errno == 0 || errno == EINTR) continue; ast_chan_log(LOG_WARNING, chan, "Wait failed (%s)\n", strerror(errno)); break; } } } exit: if (gen_active) ast_deactivate_generator(chan); if (child_events) fclose(child_events); if (child_commands) fclose(child_commands); if (child_errors) fclose(child_errors); if (test_available_fd > -1) { close(test_available_fd); } if (child_stdin[0]) close(child_stdin[0]); if (child_stdin[1]) close(child_stdin[1]); if (child_stdout[0]) close(child_stdout[0]); if (child_stdout[1]) close(child_stdout[1]); if (child_stderr[0]) close(child_stderr[0]); if (child_stderr[1]) close(child_stderr[1]); while ((entry = AST_LIST_REMOVE_HEAD(&u->playlist, list))) free(entry); ast_module_user_remove(lu); return res; }
static pid_t spawn_ras(struct ast_channel *chan, char *args) { pid_t pid; int x; char *c; char *argv[PPP_MAX_ARGS]; int argc = 0; char *stringp=NULL; sigset_t fullset, oldset; sigfillset(&fullset); pthread_sigmask(SIG_BLOCK, &fullset, &oldset); /* Start by forking */ pid = fork(); if (pid) { pthread_sigmask(SIG_SETMASK, &oldset, NULL); return pid; } /* Restore original signal handlers */ for (x=0;x<NSIG;x++) signal(x, SIG_DFL); pthread_sigmask(SIG_UNBLOCK, &fullset, NULL); /* Execute RAS on File handles */ dup2(chan->fds[0], STDIN_FILENO); /* Drop high priority */ if (ast_opt_high_priority) ast_set_priority(0); /* Close other file descriptors */ for (x=STDERR_FILENO + 1;x<1024;x++) close(x); /* Reset all arguments */ memset(argv, 0, sizeof(argv)); /* First argument is executable, followed by standard arguments for dahdi PPP */ argv[argc++] = PPP_EXEC; argv[argc++] = "nodetach"; /* And all the other arguments */ stringp=args; c = strsep(&stringp, ","); while(c && strlen(c) && (argc < (PPP_MAX_ARGS - 4))) { argv[argc++] = c; c = strsep(&stringp, ","); } argv[argc++] = "plugin"; argv[argc++] = "dahdi.so"; argv[argc++] = "stdin"; /* Finally launch PPP */ execv(PPP_EXEC, argv); fprintf(stderr, "Failed to exec PPPD!\n"); exit(1); }