void run(int phase) { init_outbuf(); init(); match(phase); flush_outbuf(); }
int main(int argc, char **argv) { int childpid; int sfd = -1; int fd; char *p, *ptyslave=NULL; int i = 1; int off_argv; int calculated_pipename = 0; int highest_pipe_num = 0; program_name = argv[0]; if(argc<4) { usage(argv[0]); exit(1); } init_outbuf(); if (!strcmp(argv[1],"-daemon")) { daemon_init(); ++i; } off_argv = i; strn_cpy(pipename, sizeof(pipename), argv[i++]); strn_cpy(log_dir, sizeof(log_dir), argv[i]); strn_cpy(statusfile, sizeof(statusfile), log_dir); strn_cat(statusfile, sizeof(statusfile), STATUSFILENAME); #ifdef DEBUG status("%s: pid is : %d\n", argv[0], getpid()); #endif /* Get values for LOG file handling from the environment */ if ((p = getenv("RUN_ERL_LOG_ALIVE_MINUTES"))) { log_alive_minutes = atoi(p); if (!log_alive_minutes) { ERROR1(LOG_ERR,"Minimum value for RUN_ERL_LOG_ALIVE_MINUTES is 1 " "(current value is %s)",p); } log_activity_minutes = log_alive_minutes / 3; if (!log_activity_minutes) { ++log_activity_minutes; } } if ((p = getenv("RUN_ERL_LOG_ACTIVITY_MINUTES"))) { log_activity_minutes = atoi(p); if (!log_activity_minutes) { ERROR1(LOG_ERR,"Minimum value for RUN_ERL_LOG_ACTIVITY_MINUTES is 1 " "(current value is %s)",p); } } if ((p = getenv("RUN_ERL_LOG_ALIVE_FORMAT"))) { if (strlen(p) > ALIVE_BUFFSIZ) { ERROR1(LOG_ERR, "RUN_ERL_LOG_ALIVE_FORMAT can contain a maximum of " "%d characters", ALIVE_BUFFSIZ); } strn_cpy(log_alive_format, sizeof(log_alive_format), p); } else { strn_cpy(log_alive_format, sizeof(log_alive_format), DEFAULT_LOG_ALIVE_FORMAT); } if ((p = getenv("RUN_ERL_LOG_ALIVE_IN_UTC")) && strcmp(p,"0")) { ++log_alive_in_gmt; } if ((p = getenv("RUN_ERL_LOG_GENERATIONS"))) { log_generations = atoi(p); if (log_generations < LOG_MIN_GENERATIONS) ERROR1(LOG_ERR,"Minimum RUN_ERL_LOG_GENERATIONS is %d", LOG_MIN_GENERATIONS); if (log_generations > LOG_MAX_GENERATIONS) ERROR1(LOG_ERR,"Maximum RUN_ERL_LOG_GENERATIONS is %d", LOG_MAX_GENERATIONS); } if ((p = getenv("RUN_ERL_LOG_MAXSIZE"))) { log_maxsize = atoi(p); if (log_maxsize < LOG_MIN_MAXSIZE) ERROR1(LOG_ERR,"Minimum RUN_ERL_LOG_MAXSIZE is %d", LOG_MIN_MAXSIZE); } /* * Create FIFOs and open them */ if(*pipename && pipename[strlen(pipename)-1] == '/') { /* The user wishes us to find a unique pipe name in the specified */ /* directory */ DIR *dirp; struct dirent *direntp; calculated_pipename = 1; dirp = opendir(pipename); if(!dirp) { ERRNO_ERR1(LOG_ERR,"Can't access pipe directory '%s'.", pipename); exit(1); } /* Check the directory for existing pipes */ while((direntp=readdir(dirp)) != NULL) { if(strncmp(direntp->d_name,PIPE_STUBNAME,PIPE_STUBLEN)==0) { int num = atoi(direntp->d_name+PIPE_STUBLEN+1); if(num > highest_pipe_num) highest_pipe_num = num; } } closedir(dirp); strn_catf(pipename, sizeof(pipename), "%s.%d", PIPE_STUBNAME, highest_pipe_num+1); } /* if */ for(;;) { /* write FIFO - is read FIFO for `to_erl' program */ strn_cpy(fifo1, sizeof(fifo1), pipename); strn_cat(fifo1, sizeof(fifo1), ".r"); if (create_fifo(fifo1, PERM) < 0) { ERRNO_ERR1(LOG_ERR,"Cannot create FIFO %s for writing.", fifo1); exit(1); } /* read FIFO - is write FIFO for `to_erl' program */ strn_cpy(fifo2, sizeof(fifo2), pipename); strn_cat(fifo2, sizeof(fifo2), ".w"); /* Check that nobody is running run_erl already */ if ((fd = sf_open(fifo2, O_WRONLY|DONT_BLOCK_PLEASE, 0)) >= 0) { /* Open as client succeeded -- run_erl is already running! */ sf_close(fd); if (calculated_pipename) { ++highest_pipe_num; strn_catf(pipename, sizeof(pipename), "%s.%d", PIPE_STUBNAME, highest_pipe_num+1); continue; } fprintf(stderr, "Erlang already running on pipe %s.\n", pipename); exit(1); } if (create_fifo(fifo2, PERM) < 0) { ERRNO_ERR1(LOG_ERR,"Cannot create FIFO %s for reading.", fifo2); exit(1); } break; } /* * Open master pseudo-terminal */ if ((mfd = open_pty_master(&ptyslave, &sfd)) < 0) { ERRNO_ERR0(LOG_ERR,"Could not open pty master"); exit(1); } /* * Now create a child process */ if ((childpid = fork()) < 0) { ERRNO_ERR0(LOG_ERR,"Cannot fork"); exit(1); } if (childpid == 0) { /* Child */ sf_close(mfd); /* disassociate from control terminal */ #ifdef USE_SETPGRP_NOARGS /* SysV */ setpgrp(); #elif defined(USE_SETPGRP) /* BSD */ setpgrp(0,getpid()); #else /* POSIX */ setsid(); #endif /* Open the slave pty */ if (sfd < 0) { /* not allocated by open_pty_master */ if ((sfd = open_pty_slave(ptyslave)) < 0) { ERRNO_ERR1(LOG_ERR,"Could not open pty slave '%s'", ptyslave); exit(1); } /* But sfd may be one of the stdio fd's now, and we should be unmodern and not use dup2... */ /* easiest to dup it up... */ while (sfd < 3) { sfd = dup(sfd); } } #if defined(HAVE_OPENPTY) && defined(TIOCSCTTY) else { /* sfd is from open_pty_master * openpty -> fork -> login_tty (forkpty) * * It would be preferable to implement a portable * forkpty instead of open_pty_master / open_pty_slave */ /* login_tty(sfd); <- FAIL */ ioctl(sfd, TIOCSCTTY, (char *)NULL); } #endif #ifndef NO_SYSLOG /* Before fiddling with file descriptors we make sure syslog is turned off or "closed". In the single case where we might want it again, we will open it again instead. Would not want syslog to go to some other fd... */ if (run_daemon) { closelog(); } #endif /* Close stdio */ sf_close(0); sf_close(1); sf_close(2); if (dup(sfd) != 0 || dup(sfd) != 1 || dup(sfd) != 2) { status("Cannot dup\n"); } sf_close(sfd); exec_shell(argv+off_argv); /* exec_shell expects argv[2] to be */ /* the command name, so we have to */ /* adjust. */ } else { /* Parent */ /* Ignore the SIGPIPE signal, write() will return errno=EPIPE */ struct sigaction sig_act; sigemptyset(&sig_act.sa_mask); sig_act.sa_flags = 0; sig_act.sa_handler = SIG_IGN; sigaction(SIGPIPE, &sig_act, (struct sigaction *)NULL); sigemptyset(&sig_act.sa_mask); sig_act.sa_flags = SA_NOCLDSTOP; sig_act.sa_handler = catch_sigchild; sigaction(SIGCHLD, &sig_act, (struct sigaction *)NULL); /* * read and write: enter the workloop */ pass_on(childpid); } return 0; } /* main() */