/* Called from main */ void x_init(void) { /* set to -2 to force initial binding */ edchars.erase = edchars.kill = edchars.intr = edchars.quit = edchars.eof = -2; /* default value for deficient systems */ edchars.werase = 027; /* ^W */ if (setsig(&sigtraps[SIGWINCH], x_sigwinch, SS_RESTORE_ORIG|SS_SHTRAP)) sigtraps[SIGWINCH].flags |= TF_SHELL_USES; got_sigwinch = 1; /* force initial check */ check_sigwinch(); #ifdef EMACS x_init_emacs(); #endif /* EMACS */ }
/* * sig_init -- * Initialize signals. * * PUBLIC: int sig_init __P((GS *, SCR *)); */ int sig_init(GS *gp, SCR *sp) { CL_PRIVATE *clp; clp = GCLP(gp); if (sp == NULL) { (void)sigemptyset(&__sigblockset); if (sigaddset(&__sigblockset, SIGHUP) || setsig(SIGHUP, &clp->oact[INDX_HUP], h_hup) || sigaddset(&__sigblockset, SIGINT) || setsig(SIGINT, &clp->oact[INDX_INT], h_int) || sigaddset(&__sigblockset, SIGTERM) || setsig(SIGTERM, &clp->oact[INDX_TERM], h_term) #ifdef SIGWINCH || sigaddset(&__sigblockset, SIGWINCH) || setsig(SIGWINCH, &clp->oact[INDX_WINCH], h_winch) #endif ) { perr(gp->progname, NULL); return (1); } } else if (setsig(SIGHUP, NULL, h_hup) || setsig(SIGINT, NULL, h_int) || setsig(SIGTERM, NULL, h_term) #ifdef SIGWINCH || setsig(SIGWINCH, NULL, h_winch) #endif ) { msgq(sp, M_SYSERR, "signal-reset"); } return (0); }
/* Called from main */ void x_init() { /* set to -1 to force initial binding */ edchars.erase = edchars.kill = edchars.intr = edchars.quit = edchars.eof = -1; /* default value for deficient systems */ edchars.werase = 027; /* ^W */ #ifdef TIOCGWINSZ # ifdef SIGWINCH if (setsig(&sigtraps[SIGWINCH], x_sigwinch, SS_RESTORE_ORIG|SS_SHTRAP)) sigtraps[SIGWINCH].flags |= TF_SHELL_USES; # endif /* SIGWINCH */ got_sigwinch = 1; /* force initial check */ check_sigwinch(); #endif /* TIOCGWINSZ */ #ifdef EMACS x_init_emacs(); #endif /* EMACS */ /* Bizarreness to figure out how to disable * a struct termios.c_cc[] char */ #ifdef _POSIX_VDISABLE if (_POSIX_VDISABLE >= 0) vdisable_c = (char) _POSIX_VDISABLE; else /* `feature not available' */ vdisable_c = (char) 0377; #else # if defined(HAVE_PATHCONF) && defined(_PC_VDISABLE) vdisable_c = fpathconf(tty_fd, _PC_VDISABLE); # else vdisable_c = (char) 0377; /* default to old BSD value */ # endif #endif /* _POSIX_VDISABLE */ }
/* * sig_init -- * Initialize signals. * * PUBLIC: int sig_init(GS *, SCR *); */ int sig_init(GS *gp, SCR *sp) { CL_PRIVATE *clp; clp = GCLP(gp); if (sp == NULL) { if (setsig(SIGHUP, &clp->oact[INDX_HUP], h_hup) || setsig(SIGINT, &clp->oact[INDX_INT], h_int) || setsig(SIGTERM, &clp->oact[INDX_TERM], h_term) || setsig(SIGWINCH, &clp->oact[INDX_WINCH], h_winch) ) err(1, NULL); } else if (setsig(SIGHUP, NULL, h_hup) || setsig(SIGINT, NULL, h_int) || setsig(SIGTERM, NULL, h_term) || setsig(SIGWINCH, NULL, h_winch) ) { msgq(sp, M_SYSERR, "signal-reset"); } return (0); }
void xexec(char *argv[], int fd) { register int i; char *pr=argv[0]; #ifdef O_NONBLOCK i=fcntl(fd, F_GETFL); (void) fcntl(fd, F_SETFL, i&(~O_NONBLOCK)); #endif dup2(fd, 0); dup2(fd, 1); dup2(fd, 2); for (i=getdtablesize()-1; i>2; --i) (void) close(i); setsig(SIGPIPE, SIG_DFL); #if defined(HAVE_STRDUP) && defined(HAVE_STRRCHR) { char *p=strrchr(argv[0], '/'); if (p && (p=strdup(p+1))) argv[0]=p; } #endif execv(pr, argv); write(2, "exec error\n", 11); }
static VALUE bossan_run_loop(int argc, VALUE *argv, VALUE self) { int ret; VALUE args1, args2, args3; rb_scan_args(argc, argv, "21", &args1, &args2, &args3); if(listen_sock > 0){ rb_raise(rb_eException, "already set listen socket"); } if (argc == 3){ server_name = StringValuePtr(args1); server_port = NUM2INT(args2); long _port = NUM2INT(args2); if (_port <= 0 || _port >= 65536) { // out of range rb_raise(rb_eArgError, "port number outside valid range"); } server_port = (short)_port; ret = inet_listen(); rack_app = args3; } else { Check_Type(args1, T_STRING); ret = unix_listen(StringValuePtr(args1)); rack_app = args2; } if(ret < 0){ //error listen_sock = -1; } if(listen_sock <= 0){ rb_raise(rb_eTypeError, "not found listen socket"); } /* init picoev */ picoev_init(MAX_FDS); /* create loop */ main_loop = picoev_create_loop(60); loop_done = 1; setsig(SIGPIPE, sigpipe_cb); setsig(SIGINT, sigint_cb); setsig(SIGTERM, sigint_cb); picoev_add(main_loop, listen_sock, PICOEV_READ, ACCEPT_TIMEOUT_SECS, accept_callback, NULL); /* loop */ while (loop_done) { picoev_loop_once(main_loop, 10); } picoev_destroy_loop(main_loop); picoev_deinit(); printf("Bye.\n"); return Qnil; }
/* execute tree in child subprocess */ int exchild(struct op *t, int flags, volatile int *xerrok, int close_fd) /* used if XPCLOSE or XCCLOSE */ { static Proc *last_proc; /* for pipelines */ int i; sigset_t omask; Proc *p; Job *j; int rv = 0; int forksleep; int ischild; if (flags & XEXEC) /* Clear XFORK|XPCLOSE|XCCLOSE|XCOPROC|XPIPEO|XPIPEI|XXCOM|XBGND * (also done in another execute() below) */ return execute(t, flags & (XEXEC | XERROK), xerrok); /* no SIGCHLD's while messing with job and process lists */ sigprocmask(SIG_BLOCK, &sm_sigchld, &omask); p = new_proc(); p->next = (Proc *) 0; p->state = PRUNNING; p->status = 0; p->pid = 0; /* link process into jobs list */ if (flags&XPIPEI) { /* continuing with a pipe */ if (!last_job) internal_errorf(1, "exchild: XPIPEI and no last_job - pid %d", (int) procpid); j = last_job; last_proc->next = p; last_proc = p; } else { j = new_job(); /* fills in j->job */ /* we don't consider XXCOM's foreground since they don't get * tty process group and we don't save or restore tty modes. */ j->flags = (flags & XXCOM) ? JF_XXCOM : ((flags & XBGND) ? 0 : (JF_FG|JF_USETTYMODE)); timerclear(&j->usrtime); timerclear(&j->systime); j->state = PRUNNING; j->pgrp = 0; j->ppid = procpid; j->age = ++njobs; j->proc_list = p; j->coproc_id = 0; last_job = j; last_proc = p; put_job(j, PJ_PAST_STOPPED); } snptreef(p->command, sizeof(p->command), "%T", t); /* create child process */ forksleep = 1; while ((i = fork()) < 0 && errno == EAGAIN && forksleep < 32) { if (intrsig) /* allow user to ^C out... */ break; sleep(forksleep); forksleep <<= 1; } if (i < 0) { kill_job(j, SIGKILL); remove_job(j, "fork failed"); sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); errorf("cannot fork - try again"); } ischild = i == 0; if (ischild) p->pid = procpid = getpid(); else p->pid = i; #ifdef JOBS /* job control set up */ if (Flag(FMONITOR) && !(flags&XXCOM)) { int dotty = 0; if (j->pgrp == 0) { /* First process */ j->pgrp = p->pid; dotty = 1; } /* set pgrp in both parent and child to deal with race * condition */ setpgid(p->pid, j->pgrp); /* YYY: should this be if (ttypgrp_ok && ischild && !(flags&XBGND)) tcsetpgrp(tty_fd, j->pgrp); instead? (see also YYY below) */ if (ttypgrp_ok && dotty && !(flags & XBGND)) tcsetpgrp(tty_fd, j->pgrp); } #endif /* JOBS */ /* used to close pipe input fd */ if (close_fd >= 0 && (((flags & XPCLOSE) && !ischild) || ((flags & XCCLOSE) && ischild))) close(close_fd); if (ischild) { /* child */ /* Do this before restoring signal */ if (flags & XCOPROC) coproc_cleanup(false); sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); cleanup_parents_env(); #ifdef JOBS /* If FMONITOR or FTALKING is set, these signals are ignored, * if neither FMONITOR nor FTALKING are set, the signals have * their inherited values. */ if (Flag(FMONITOR) && !(flags & XXCOM)) { for (i = NELEM(tt_sigs); --i >= 0; ) setsig(&sigtraps[tt_sigs[i]], SIG_DFL, SS_RESTORE_DFL|SS_FORCE); } #endif /* JOBS */ if (Flag(FBGNICE) && (flags & XBGND)) nice(4); if ((flags & XBGND) && !Flag(FMONITOR)) { setsig(&sigtraps[SIGINT], SIG_IGN, SS_RESTORE_IGN|SS_FORCE); setsig(&sigtraps[SIGQUIT], SIG_IGN, SS_RESTORE_IGN|SS_FORCE); if (!(flags & (XPIPEI | XCOPROC))) { int fd = open("/dev/null", 0); if (fd != 0) { (void) ksh_dup2(fd, 0, true); close(fd); } } } remove_job(j, "child"); /* in case of `jobs` command */ nzombie = 0; #ifdef JOBS ttypgrp_ok = 0; Flag(FMONITOR) = 0; #endif /* JOBS */ Flag(FTALKING) = 0; tty_close(); cleartraps(); execute(t, (flags & XERROK) | XEXEC, NULL); /* no return */ internal_errorf(0, "exchild: execute() returned"); unwind(LLEAVE); /* NOTREACHED */ } /* shell (parent) stuff */ /* Ensure next child gets a (slightly) different $RANDOM sequence */ change_random(); if (!(flags & XPIPEO)) { /* last process in a job */ #ifdef JOBS /* YYY: Is this needed? (see also YYY above) if (Flag(FMONITOR) && !(flags&(XXCOM|XBGND))) tcsetpgrp(tty_fd, j->pgrp); */ #endif /* JOBS */ j_startjob(j); if (flags & XCOPROC) { j->coproc_id = coproc.id; coproc.njobs++; /* n jobs using co-process output */ coproc.job = (void *) j; /* j using co-process input */ } if (flags & XBGND) { j_set_async(j); if (Flag(FTALKING)) { shf_fprintf(shl_out, "[%d]", j->job); for (p = j->proc_list; p; p = p->next) shf_fprintf(shl_out, " %d", p->pid); shf_putchar('\n', shl_out); shf_flush(shl_out); } } else rv = j_waitj(j, JW_NONE, "jw:last proc"); } sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); return rv; }
/* turn job control on or off according to Flag(FMONITOR) */ void j_change(void) { int i; if (Flag(FMONITOR)) { int use_tty; if (Flag(FTALKING)) { /* Don't call tcgetattr() 'til we own the tty process group */ use_tty = 1; tty_init(false); } else use_tty = 0; /* no controlling tty, no SIGT* */ ttypgrp_ok = use_tty && tty_fd >= 0 && tty_devtty; if (ttypgrp_ok && (our_pgrp = getpgrp()) < 0) { warningf(false, "j_init: getpgrp() failed: %s", strerror(errno)); ttypgrp_ok = 0; } if (ttypgrp_ok) { setsig(&sigtraps[SIGTTIN], SIG_DFL, SS_RESTORE_ORIG|SS_FORCE); /* wait to be given tty (POSIX.1, B.2, job control) */ while (1) { pid_t ttypgrp; if ((ttypgrp = tcgetpgrp(tty_fd)) < 0) { warningf(false, "j_init: tcgetpgrp() failed: %s", strerror(errno)); ttypgrp_ok = 0; break; } if (ttypgrp == our_pgrp) break; kill(0, SIGTTIN); } } for (i = NELEM(tt_sigs); --i >= 0; ) setsig(&sigtraps[tt_sigs[i]], SIG_IGN, SS_RESTORE_DFL|SS_FORCE); if (ttypgrp_ok && our_pgrp != kshpid) { if (setpgid(0, kshpid) < 0) { warningf(false, "j_init: setpgid() failed: %s", strerror(errno)); ttypgrp_ok = 0; } else { if (tcsetpgrp(tty_fd, kshpid) < 0) { warningf(false, "j_init: tcsetpgrp() failed: %s", strerror(errno)); ttypgrp_ok = 0; } else restore_ttypgrp = our_pgrp; our_pgrp = kshpid; } } if (use_tty) { if (!ttypgrp_ok) warningf(false, "warning: won't have full job control"); } if (tty_fd >= 0) tcgetattr(tty_fd, &tty_state); } else { ttypgrp_ok = 0; if (Flag(FTALKING)) for (i = NELEM(tt_sigs); --i >= 0; ) setsig(&sigtraps[tt_sigs[i]], SIG_IGN, SS_RESTORE_IGN|SS_FORCE); else for (i = NELEM(tt_sigs); --i >= 0; ) { if (sigtraps[tt_sigs[i]].flags & (TF_ORIG_IGN | TF_ORIG_DFL)) setsig(&sigtraps[tt_sigs[i]], (sigtraps[tt_sigs[i]].flags & TF_ORIG_IGN) ? SIG_IGN : SIG_DFL, SS_RESTORE_ORIG|SS_FORCE); } if (!Flag(FTALKING)) tty_close(); } }
int exchild(struct op *t, int flags, int close_fd) /* used if XPCLOSE or XCCLOSE */ { static Proc *last_proc; /* for pipelines */ int i; sigset_t omask; Proc *p; Job *j; int rv = 0; int forksleep; int ischild; if (flags & XEXEC) /* Clear XFORK|XPCLOSE|XCCLOSE|XCOPROC|XPIPEO|XPIPEI|XXCOM|XBGND * (also done in another execute() below) */ return execute(t, flags & (XEXEC | XERROK)); p = new_proc(); p->next = (Proc *) 0; p->state = PRUNNING; p->status = 0; p->pid = 0; /* link process into jobs list */ if (flags&XPIPEI) { /* continuing with a pipe */ if (!last_job) internal_errorf(1, "exchild: XPIPEI and no last_job - pid %d", (int) procpid); j = last_job; last_proc->next = p; last_proc = p; } else { j = new_job(); /* fills in j->job */ /* we don't consider XXCOM's foreground since they don't get * tty process group and we don't save or restore tty modes. */ j->flags = (flags & XXCOM) ? JF_XXCOM : ((flags & XBGND) ? 0 : (JF_FG|JF_USETTYMODE)); j->usrtime = j->systime = 0; j->state = PRUNNING; j->pgrp = 0; j->ppid = procpid; j->age = ++njobs; j->proc_list = p; j->coproc_id = 0; last_job = j; last_proc = p; put_job(j, PJ_PAST_STOPPED); } snptreef(p->command, sizeof(p->command), "%T", t); /* create child process */ forksleep = 1; while ((i = fork()) < 0 && errno == EAGAIN && forksleep < 32) { if (intrsig) /* allow user to ^C out... */ break; sleep(forksleep); forksleep <<= 1; } if (i < 0) { kill_job(j, SIGKILL); remove_job(j, "fork failed"); sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); errorf("cannot fork - try again"); } ischild = i == 0; if (ischild) p->pid = procpid = getpid(); else p->pid = i; /* used to close pipe input fd */ if (close_fd >= 0 && (((flags & XPCLOSE) && !ischild) || ((flags & XCCLOSE) && ischild))) close(close_fd); if (ischild) { /* child */ /* Do this before restoring signal */ if (flags & XCOPROC) coproc_cleanup(false); sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); cleanup_parents_env(); if ((flags & XBGND)) { setsig(&sigtraps[SIGINT], SIG_IGN, SS_RESTORE_IGN|SS_FORCE); setsig(&sigtraps[SIGQUIT], SIG_IGN, SS_RESTORE_IGN|SS_FORCE); if (!(flags & (XPIPEI | XCOPROC))) { int fd = open("/dev/null", 0); if (fd != 0) { (void) ksh_dup2(fd, 0, true); close(fd); } } } remove_job(j, "child"); /* in case of `jobs` command */ nzombie = 0; Flag(FTALKING) = 0; tty_close(); cleartraps(); execute(t, (flags & XERROK) | XEXEC); /* no return */ internal_errorf(0, "exchild: execute() returned"); unwind(LLEAVE); /* NOTREACHED */ } /* shell (parent) stuff */ /* Ensure next child gets a (slightly) different $RANDOM sequence */ change_random(); if (!(flags & XPIPEO)) { /* last process in a job */ j_startjob(j); if (flags & XCOPROC) { j->coproc_id = coproc.id; coproc.njobs++; /* n jobs using co-process output */ coproc.job = (void *) j; /* j using co-process input */ } if (flags & XBGND) { j_set_async(j); if (Flag(FTALKING)) { shf_fprintf(shl_out, "[%d]", j->job); for (p = j->proc_list; p; p = p->next) shf_fprintf(shl_out, " %d", p->pid); shf_putchar('\n', shl_out); shf_flush(shl_out); } } else rv = j_waitj(j, JW_NONE, "jw:last proc"); } sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); return rv; }
/* * mail [ -ehpPqrtw ] [-x debuglevel] [ -f file ] [ -F user(s) ] * mail -T file persons * mail [ -tw ] [ -m messagetype ] persons * rmail [ -tw ] persons */ int main(int argc, char **argv) { register int i; char *cptr, *p; static char pn[] = "main"; extern char **environ; int env_var_idx, next_slot_idx; int tmpfd = -1; (void)&argc; (void)&argv; setlocale(LC_CTYPE, ""); mb_cur_max = MB_CUR_MAX; /* fix here for bug #1086130 - security hole */ /* skip over the LD_* env variable */ env_var_idx = 0; next_slot_idx = 0; while (environ[env_var_idx] != NULL) { environ[next_slot_idx] = environ[env_var_idx]; if (strncmp(environ[env_var_idx], "LD_", 3)) { next_slot_idx++; } env_var_idx++; } environ[next_slot_idx] = NULL; line = smalloc(linesize = LSIZE); *line = '\0'; #ifdef SIGCONT { struct sigaction nsig; nsig.sa_handler = SIG_DFL; sigemptyset(&nsig.sa_mask); nsig.sa_flags = SA_RESTART; sigaction(SIGCONT, &nsig, (struct sigaction *)0); } #endif /* * Strip off path name of this command for use in messages */ if ((program = strrchr(argv[0], '/')) != NULL) { program++; } else { program = argv[0]; } /* Close all file descriptors except stdin, stdout & stderr */ for (i = 3; close(i) == 0; i++); /* * Get group id for mail, exit if none exists */ if ((grpptr = getgrnam("mail")) == NULL) { errmsg(E_GROUP, ""); exit(1); } else { mailgrp = grpptr->gr_gid; } /* * Save the *id for later use. */ my_uid = getuid(); my_gid = getgid(); my_euid = geteuid(); my_egid = getegid(); /* * What command (rmail or mail)? */ if (strcmp(program, "rmail") == SAME) { ismail = FALSE; } /* * Parse the command line and adjust argc and argv * to compensate for any options */ i = parse(argc, argv); argv += (i - 1); argc -= (i - 1); /* block a potential security hole */ if (flgT && (my_euid != 0)) { setgid(my_gid); Tout(pn, "Setgid unset\n"); } if (debug == 0) { /* If not set as an invocation option, check for system-wide */ /* global flag */ char *xp = xgetenv("DEBUG"); if (xp != (char *)NULL) { debug = atoi(xp); if (debug < 0) { /* Keep trace file even if successful */ keepdbgfile = -1; debug = -debug; } } } if (debug > 0) { strcpy(dbgfname, "/tmp/MLDBGXXXXXX"); if ((tmpfd = mkstemp(dbgfname)) == -1) { fprintf(stderr, "%s: can't open debugging file '%s'\n", program, dbgfname); exit(13); } if ((dbgfp = fdopen(tmpfd, "w")) == (FILE *)NULL) { fprintf(stderr, "%s: can't open debugging file '%s'\n", program, dbgfname); close(tmpfd); exit(13); } setbuf(dbgfp, NULL); fprintf(dbgfp, "main(): debugging level == %d\n", debug); fprintf(dbgfp, "main(): trace file ='%s': kept %s\n", dbgfname, ((keepdbgfile < 0) ? "on success or failure." : "only on failure.")); } if (!ismail && (goerr > 0 || !i)) { Dout(pn, 11, "!ismail, goerr=%d, i=%d\n", goerr, i); if (goerr > 0) { errmsg(E_SYNTAX, "Usage: rmail [-wt] person(s)"); } if (!i) { errmsg(E_SYNTAX, "At least one user must be specified"); } Dout(pn, 11, "exiting!\n"); done(0); } umsave = umask(7); uname(&utsn); if ((p = xgetenv("CLUSTER")) != (char *)NULL) { /* * We are not who we appear... */ thissys = p; } else { thissys = utsn.nodename; } Dout(pn, 11, "thissys = '%s', uname = '%s'\n", thissys, utsn.nodename); failsafe = xgetenv("FAILSAFE"); if (failsafe) Dout(pn, 11, "failsafe processing enabled to %s\n", failsafe); /* * Use environment variables */ home = getenv("HOME"); if (!home || !*home) { home = "."; } pwd = getpwuid(my_uid); if (pwd) cpy(&my_name, &my_namesize, pwd->pw_name); else cpy(&my_name, &my_namesize, ""); /* If root, use LOGNAME if set */ if (my_uid == 0) { /* If root, use LOGNAME if set */ if (((cptr = getenv("LOGNAME")) != NULL) && (strlen(cptr) != 0)) { cpy(&my_name, &my_namesize, cptr); } } Dout(pn, 11, "my_name = '%s'\n", my_name); /* * Catch signals for cleanup */ if (setjmp(sjbuf)) { done(0); } setsig(SIGINT, delete); setsig(SIGQUIT, delete); setsig(SIGTRAP, delete); #ifdef SIGIOT setsig(SIGIOT, delete); #endif #ifdef SIGEMT setsig(SIGEMT, delete); #endif setsig(SIGBUS, delete); setsig(SIGSEGV, delete); setsig(SIGPIPE, delete); setsig(SIGALRM, delete); setsig(SIGHUP, sig_done); setsig(SIGTERM, sig_done); cksaved(my_name); /* * Rmail is always invoked to send mail */ Dout(pn, 11, "ismail=%d, argc=%d\n", ismail, argc); if (ismail && (argc == 1)) { sending = FALSE; printmail(); } else { sending = TRUE; sendmail(argc, argv); } done(0); /*NOTREACHED*/ return 0; }
static int main_init(int argc, const char *argv[], Source **sp, struct block **lp) { int argi, i; Source *s = NULL; struct block *l; unsigned char restricted_shell, errexit, utf_flag; char *cp; const char *ccp, **wp; struct tbl *vp; struct stat s_stdin; #if !defined(_PATH_DEFPATH) && defined(_CS_PATH) ssize_t k; #endif #if defined(MKSH_EBCDIC) || defined(MKSH_FAUX_EBCDIC) ebcdic_init(); #endif set_ifs(TC_IFSWS); #ifdef __OS2__ os2_init(&argc, &argv); #endif /* do things like getpgrp() et al. */ chvt_reinit(); /* make sure argv[] is sane, for weird OSes */ if (!*argv) { argv = empty_argv; argc = 1; } kshname = argv[0]; /* initialise permanent Area */ ainit(&aperm); /* max. name length: -2147483648 = 11 (+ NUL) */ vtemp = alloc(offsetof(struct tbl, name[0]) + 12, APERM); /* set up base environment */ env.type = E_NONE; ainit(&env.area); /* set up global l->vars and l->funs */ newblock(); /* Do this first so output routines (eg, errorf, shellf) can work */ initio(); /* determine the basename (without '-' or path) of the executable */ ccp = kshname; goto begin_parsing_kshname; while ((i = ccp[argi++])) { if (mksh_cdirsep(i)) { ccp += argi; begin_parsing_kshname: argi = 0; if (*ccp == '-') ++ccp; } } if (!*ccp) ccp = empty_argv[0]; /* * Turn on nohup by default. (AT&T ksh does not have a nohup * option - it always sends the hup). */ Flag(FNOHUP) = 1; /* * Turn on brace expansion by default. AT&T kshs that have * alternation always have it on. */ Flag(FBRACEEXPAND) = 1; /* * Turn on "set -x" inheritance by default. */ Flag(FXTRACEREC) = 1; /* define built-in commands and see if we were called as one */ ktinit(APERM, &builtins, /* currently up to 54 builtins: 75% of 128 = 2^7 */ 7); for (i = 0; mkshbuiltins[i].name != NULL; i++) if (!strcmp(ccp, builtin(mkshbuiltins[i].name, mkshbuiltins[i].func))) Flag(FAS_BUILTIN) = 1; if (!Flag(FAS_BUILTIN)) { /* check for -T option early */ argi = parse_args(argv, OF_FIRSTTIME, NULL); if (argi < 0) return (1); #if defined(MKSH_BINSHPOSIX) || defined(MKSH_BINSHREDUCED) /* are we called as -sh or /bin/sh or so? */ if (!strcmp(ccp, "sh" MKSH_EXE_EXT)) { /* either also turns off braceexpand */ #ifdef MKSH_BINSHPOSIX /* enable better POSIX conformance */ change_flag(FPOSIX, OF_FIRSTTIME, true); #endif #ifdef MKSH_BINSHREDUCED /* enable kludge/compat mode */ change_flag(FSH, OF_FIRSTTIME, true); #endif } #endif } initvar(); inittraps(); coproc_init(); /* set up variable and command dictionaries */ ktinit(APERM, &taliases, 0); ktinit(APERM, &aliases, 0); #ifndef MKSH_NOPWNAM ktinit(APERM, &homedirs, 0); #endif /* define shell keywords */ initkeywords(); init_histvec(); /* initialise tty size before importing environment */ change_winsz(); #ifdef _PATH_DEFPATH def_path = _PATH_DEFPATH; #else #ifdef _CS_PATH if ((k = confstr(_CS_PATH, NULL, 0)) > 0 && confstr(_CS_PATH, cp = alloc(k + 1, APERM), k + 1) == k + 1) def_path = cp; else #endif /* * this is uniform across all OSes unless it * breaks somewhere hard; don't try to optimise, * e.g. add stuff for Interix or remove /usr * for HURD, because e.g. Debian GNU/HURD is * "keeping a regular /usr"; this is supposed * to be a sane 'basic' default PATH */ def_path = MKSH_UNIXROOT "/bin" MKSH_PATHSEPS MKSH_UNIXROOT "/usr/bin" MKSH_PATHSEPS MKSH_UNIXROOT "/sbin" MKSH_PATHSEPS MKSH_UNIXROOT "/usr/sbin"; #endif /* * Set PATH to def_path (will set the path global variable). * (import of environment below will probably change this setting). */ vp = global(TPATH); /* setstr can't fail here */ setstr(vp, def_path, KSH_RETURN_ERROR); #ifndef MKSH_NO_CMDLINE_EDITING /* * Set edit mode to emacs by default, may be overridden * by the environment or the user. Also, we want tab completion * on in vi by default. */ change_flag(FEMACS, OF_SPECIAL, true); #if !MKSH_S_NOVI Flag(FVITABCOMPLETE) = 1; #endif #endif /* import environment */ init_environ(); /* override default PATH regardless of environment */ #ifdef MKSH_DEFPATH_OVERRIDE vp = global(TPATH); setstr(vp, MKSH_DEFPATH_OVERRIDE, KSH_RETURN_ERROR); #endif /* for security */ typeset(TinitIFS, 0, 0, 0, 0); /* assign default shell variable values */ typeset("PATHSEP=" MKSH_PATHSEPS, 0, 0, 0, 0); substitute(initsubs, 0); /* Figure out the current working directory and set $PWD */ vp = global(TPWD); cp = str_val(vp); /* Try to use existing $PWD if it is valid */ set_current_wd((mksh_abspath(cp) && test_eval(NULL, TO_FILEQ, cp, Tdot, true)) ? cp : NULL); if (current_wd[0]) simplify_path(current_wd); /* Only set pwd if we know where we are or if it had a bogus value */ if (current_wd[0] || *cp) /* setstr can't fail here */ setstr(vp, current_wd, KSH_RETURN_ERROR); for (wp = initcoms; *wp != NULL; wp++) { c_builtin(wp); while (*wp != NULL) wp++; } setint_n(global("OPTIND"), 1, 10); kshuid = getuid(); kshgid = getgid(); kshegid = getegid(); safe_prompt = ksheuid ? "$ " : "# "; vp = global("PS1"); /* Set PS1 if unset or we are root and prompt doesn't contain a # */ if (!(vp->flag & ISSET) || (!ksheuid && !strchr(str_val(vp), '#'))) /* setstr can't fail here */ setstr(vp, safe_prompt, KSH_RETURN_ERROR); setint_n((vp = global("BASHPID")), 0, 10); vp->flag |= INT_U; setint_n((vp = global("PGRP")), (mksh_uari_t)kshpgrp, 10); vp->flag |= INT_U; setint_n((vp = global("PPID")), (mksh_uari_t)kshppid, 10); vp->flag |= INT_U; setint_n((vp = global("USER_ID")), (mksh_uari_t)ksheuid, 10); vp->flag |= INT_U; setint_n((vp = global("KSHUID")), (mksh_uari_t)kshuid, 10); vp->flag |= INT_U; setint_n((vp = global("KSHEGID")), (mksh_uari_t)kshegid, 10); vp->flag |= INT_U; setint_n((vp = global("KSHGID")), (mksh_uari_t)kshgid, 10); vp->flag |= INT_U; setint_n((vp = global("RANDOM")), rndsetup(), 10); vp->flag |= INT_U; setint_n((vp_pipest = global("PIPESTATUS")), 0, 10); /* Set this before parsing arguments */ Flag(FPRIVILEGED) = (kshuid != ksheuid || kshgid != kshegid) ? 2 : 0; /* this to note if monitor is set on command line (see below) */ #ifndef MKSH_UNEMPLOYED Flag(FMONITOR) = 127; #endif /* this to note if utf-8 mode is set on command line (see below) */ UTFMODE = 2; if (!Flag(FAS_BUILTIN)) { argi = parse_args(argv, OF_CMDLINE, NULL); if (argi < 0) return (1); } /* process this later only, default to off (hysterical raisins) */ utf_flag = UTFMODE; UTFMODE = 0; if (Flag(FAS_BUILTIN)) { /* auto-detect from environment variables, always */ utf_flag = 3; } else if (Flag(FCOMMAND)) { s = pushs(SSTRINGCMDLINE, ATEMP); if (!(s->start = s->str = argv[argi++])) errorf(Tf_optfoo, "", "", 'c', Treq_arg); while (*s->str) { if (ctype(*s->str, C_QUOTE)) break; s->str++; } if (!*s->str) s->flags |= SF_MAYEXEC; s->str = s->start; #ifdef MKSH_MIDNIGHTBSD01ASH_COMPAT /* compatibility to MidnightBSD 0.1 /bin/sh (kludge) */ if (Flag(FSH) && argv[argi] && !strcmp(argv[argi], "--")) ++argi; #endif if (argv[argi]) kshname = argv[argi++]; } else if (argi < argc && !Flag(FSTDIN)) { s = pushs(SFILE, ATEMP); #ifdef __OS2__ /* * A bug in OS/2 extproc (like shebang) handling makes * it not pass the full pathname of a script, so we need * to search for it. This changes the behaviour of a * simple "mksh foo", but can't be helped. */ s->file = argv[argi++]; if (search_access(s->file, X_OK) != 0) s->file = search_path(s->file, path, X_OK, NULL); if (!s->file || !*s->file) s->file = argv[argi - 1]; #else s->file = argv[argi++]; #endif s->u.shf = shf_open(s->file, O_RDONLY, 0, SHF_MAPHI | SHF_CLEXEC); if (s->u.shf == NULL) { shl_stdout_ok = false; warningf(true, Tf_sD_s, s->file, cstrerror(errno)); /* mandated by SUSv4 */ exstat = 127; unwind(LERROR); } kshname = s->file; } else { Flag(FSTDIN) = 1; s = pushs(SSTDIN, ATEMP); s->file = "<stdin>"; s->u.shf = shf_fdopen(0, SHF_RD | can_seek(0), NULL); if (isatty(0) && isatty(2)) { Flag(FTALKING) = Flag(FTALKING_I) = 1; /* The following only if isatty(0) */ s->flags |= SF_TTY; s->u.shf->flags |= SHF_INTERRUPT; s->file = NULL; } } /* this bizarreness is mandated by POSIX */ if (fstat(0, &s_stdin) >= 0 && S_ISCHR(s_stdin.st_mode) && Flag(FTALKING)) reset_nonblock(0); /* initialise job control */ j_init(); /* do this after j_init() which calls tty_init_state() */ if (Flag(FTALKING)) { if (utf_flag == 2) { #ifndef MKSH_ASSUME_UTF8 /* auto-detect from locale or environment */ utf_flag = 4; #else /* this may not be an #elif */ #if MKSH_ASSUME_UTF8 utf_flag = 1; #else /* always disable UTF-8 (for interactive) */ utf_flag = 0; #endif #endif } #ifndef MKSH_NO_CMDLINE_EDITING x_init(); #endif } #ifdef SIGWINCH sigtraps[SIGWINCH].flags |= TF_SHELL_USES; setsig(&sigtraps[SIGWINCH], x_sigwinch, SS_RESTORE_ORIG|SS_FORCE|SS_SHTRAP); #endif l = e->loc; if (Flag(FAS_BUILTIN)) { l->argc = argc; l->argv = argv; l->argv[0] = ccp; } else { l->argc = argc - argi; /* * allocate a new array because otherwise, when we modify * it in-place, ps(1) output changes; the meaning of argc * here is slightly different as it excludes kshname, and * we add a trailing NULL sentinel as well */ l->argv = alloc2(l->argc + 2, sizeof(void *), APERM); l->argv[0] = kshname; memcpy(&l->argv[1], &argv[argi], l->argc * sizeof(void *)); l->argv[l->argc + 1] = NULL; getopts_reset(1); } /* divine the initial state of the utf8-mode Flag */ ccp = null; switch (utf_flag) { /* auto-detect from locale or environment */ case 4: #if HAVE_SETLOCALE_CTYPE ccp = setlocale(LC_CTYPE, ""); #if HAVE_LANGINFO_CODESET if (!isuc(ccp)) ccp = nl_langinfo(CODESET); #endif if (!isuc(ccp)) ccp = null; #endif /* FALLTHROUGH */ /* auto-detect from environment */ case 3: /* these were imported from environ earlier */ if (ccp == null) ccp = str_val(global("LC_ALL")); if (ccp == null) ccp = str_val(global("LC_CTYPE")); if (ccp == null) ccp = str_val(global("LANG")); UTFMODE = isuc(ccp); break; /* not set on command line, not FTALKING */ case 2: /* unknown values */ default: utf_flag = 0; /* FALLTHROUGH */ /* known values */ case 1: case 0: UTFMODE = utf_flag; break; } /* Disable during .profile/ENV reading */ restricted_shell = Flag(FRESTRICTED); Flag(FRESTRICTED) = 0; errexit = Flag(FERREXIT); Flag(FERREXIT) = 0; /* * Do this before profile/$ENV so that if it causes problems in them, * user will know why things broke. */ if (!current_wd[0] && Flag(FTALKING)) warningf(false, "can't determine current directory"); if (Flag(FLOGIN)) include(MKSH_SYSTEM_PROFILE, 0, NULL, true); if (!Flag(FPRIVILEGED)) { if (Flag(FLOGIN)) include(substitute("$HOME/.profile", 0), 0, NULL, true); if (Flag(FTALKING)) { cp = substitute("${ENV:-" MKSHRC_PATH "}", DOTILDE); if (cp[0] != '\0') include(cp, 0, NULL, true); } } else { include(MKSH_SUID_PROFILE, 0, NULL, true); /* turn off -p if not set explicitly */ if (Flag(FPRIVILEGED) != 1) change_flag(FPRIVILEGED, OF_INTERNAL, false); } if (restricted_shell) { c_builtin(restr_com); /* After typeset command... */ Flag(FRESTRICTED) = 1; } Flag(FERREXIT) = errexit; if (Flag(FTALKING) && s) hist_init(s); else /* set after ENV */ Flag(FTRACKALL) = 1; alarm_init(); *sp = s; *lp = l; return (0); }
int main(int argc, char **argv) { int c, background, unit; int pmin, pmax, rmin, rmax; char base[PATH_MAX], path[PATH_MAX]; unsigned int mode, dup, mmc, vol; unsigned int hold, autovol, bufsz, round, rate; const char *str; struct aparams par; struct dev *d; struct port *p; struct listen *l; atexit(log_flush); /* * global options defaults */ vol = 118; dup = 1; mmc = 0; hold = 0; autovol = 1; bufsz = 0; round = 0; rate = DEFAULT_RATE; unit = 0; background = 1; pmin = 0; pmax = 1; rmin = 0; rmax = 1; aparams_init(&par); mode = MODE_PLAY | MODE_REC; setsig(); filelist_init(); while ((c = getopt(argc, argv, "a:b:c:C:de:f:j:L:m:Mq:r:s:t:U:v:w:x:z:")) != -1) { switch (c) { case 'd': log_level++; background = 0; break; case 'U': if (listen_list) errx(1, "-U must come before -L"); unit = strtonum(optarg, 0, 15, &str); if (str) errx(1, "%s: unit number is %s", optarg, str); break; case 'L': listen_new_tcp(optarg, AUCAT_PORT + unit); break; case 'm': mode = opt_mode(); break; case 'j': dup = opt_onoff(); break; case 't': mmc = opt_mmc(); break; case 'c': opt_ch(&pmin, &pmax); break; case 'C': opt_ch(&rmin, &rmax); break; case 'e': opt_enc(&par); break; case 'r': rate = strtonum(optarg, RATE_MIN, RATE_MAX, &str); if (str) errx(1, "%s: rate is %s", optarg, str); break; case 'v': vol = strtonum(optarg, 0, MIDI_MAXCTL, &str); if (str) errx(1, "%s: volume is %s", optarg, str); break; case 's': if ((d = dev_list) == NULL) { d = mkdev(DEFAULT_DEV, &par, 0, bufsz, round, rate, hold, autovol); } mkopt(optarg, d, pmin, pmax, rmin, rmax, mode, vol, mmc, dup); break; case 'q': p = port_new(optarg, MODE_MIDIMASK, hold); if (!p) errx(1, "%s: can't open port", optarg); break; case 'a': hold = opt_onoff(); break; case 'w': autovol = opt_onoff(); break; case 'b': bufsz = strtonum(optarg, 1, RATE_MAX, &str); if (str) errx(1, "%s: buffer size is %s", optarg, str); break; case 'z': round = strtonum(optarg, 1, SHRT_MAX, &str); if (str) errx(1, "%s: block size is %s", optarg, str); break; case 'f': mkdev(optarg, &par, 0, bufsz, round, rate, hold, autovol); break; case 'M': /* XXX: for compatibility with aucat, remove this */ break; default: fputs(usagestr, stderr); return 1; } } argc -= optind; argv += optind; if (argc > 0) { fputs(usagestr, stderr); return 1; } if (dev_list == NULL) mkdev(DEFAULT_DEV, &par, 0, bufsz, round, rate, hold, autovol); for (d = dev_list; d != NULL; d = d->next) { if (opt_byname("default", d->num)) continue; mkopt("default", d, pmin, pmax, rmin, rmax, mode, vol, mmc, dup); } getbasepath(base, sizeof(base)); snprintf(path, PATH_MAX, "%s/%s%u", base, AUCAT_PATH, unit); listen_new_un(path); if (geteuid() == 0) privdrop(); midi_init(); for (p = port_list; p != NULL; p = p->next) { if (!port_init(p)) return 1; } for (d = dev_list; d != NULL; d = d->next) { if (!dev_init(d)) return 1; } for (l = listen_list; l != NULL; l = l->next) { if (!listen_init(l)) return 1; } if (background) { log_flush(); log_level = 0; if (daemon(0, 0) < 0) err(1, "daemon"); } /* * Loop, start audio. */ for (;;) { if (quit_flag) break; if (!file_poll()) break; } while (listen_list != NULL) listen_close(listen_list); while (sock_list != NULL) sock_close(sock_list); while (opt_list != NULL) opt_del(opt_list); for (d = dev_list; d != NULL; d = d->next) dev_done(d); for (p = port_list; p != NULL; p = p->next) port_done(p); midi_done(); while (file_poll()) ; /* nothing */ while (dev_list) dev_del(dev_list); while (port_list) port_del(port_list); filelist_done(); rmdir(base); unsetsig(); return 0; }
int main(int argc, char *argv[]) { FILE *poldfile, *pnewfile; char *oline, *nline, *diffline; char *olp, *nlp, *dp; int otcnt, ntcnt; pid_t i; int pfd[2]; FILE *poldtemp, *pnewtemp, *pipeinp; int status; prognam = basename(argv[0]); /* * Set flags for 'fatal' so that it will clean up, * produce a message, and terminate. */ fflags = FTLMSG | FTLCLN | FTLEXIT; setsig(); if (argc < 3 || argc > 5) fatal("arg count"); if (strcmp(argv[1], "-") == 0 && strcmp(argv[2], "-") == 0) fatal("both files standard input"); if (strcmp(argv[1], "-") == 0) poldfile = stdin; else if ((poldfile = fopen(argv[1], "r")) == NULL) { snprintf(Error, sizeof (Error), "Can not open '%s'", argv[1]); fatal(Error); } if (strcmp(argv[2], "-") == 0) pnewfile = stdin; else if ((pnewfile = fopen(argv[2], "r")) == NULL) { snprintf(Error, sizeof (Error), "Can not open '%s'", argv[2]); fatal(Error); } seglim = 3500; if (argc > 3) { if (argv[3][0] == '-' && argv[3][1] == 's') fflags &= ~FTLMSG; else { if ((seglim = atoi(argv[3])) == 0) fatal("non-numeric limit"); if (argc == 5 && argv[4][0] == '-' && argv[4][1] == 's') fflags &= ~FTLMSG; } } linenum = 0; /* Allocate the buffers and initialize their lengths */ obufsiz = BUFSIZ; nbufsiz = BUFSIZ; dbufsiz = BUFSIZ; oline = smalloc(obufsiz); nline = smalloc(nbufsiz); diffline = smalloc(dbufsiz); /* * The following while-loop will prevent any lines * common to the beginning of both files from being * sent to 'diff'. Since the running time of 'diff' is * non-linear, this will help improve performance. * If, during this process, both files reach EOF, then * the files are equal and the program will terminate. * If either file reaches EOF before the other, the * program will generate the appropriate 'diff' output * itself, since this can be easily determined and will * avoid executing 'diff' completely. */ for (;;) { olp = readline(&oline, &obufsiz, &obuflen, poldfile); nlp = readline(&nline, &nbufsiz, &nbuflen, pnewfile); if (!olp && !nlp) /* EOF found on both: files equal */ return (0); if (!olp) { /* * The entire old file is a prefix of the * new file. Generate the appropriate "append" * 'diff'-like output, which is of the form: * nan, n * where 'n' represents a line-number. */ addgen(&nline, &nbufsiz, &nbuflen, pnewfile); } if (!nlp) { /* * The entire new file is a prefix of the * old file. Generate the appropriate "delete" * 'diff'-like output, which is of the form: * n, ndn * where 'n' represents a line-number. */ delgen(&oline, &obufsiz, &obuflen, poldfile); } if (obuflen == nbuflen && memcmp(olp, nlp, obuflen) == 0) linenum++; else break; } /* * Here, first 'linenum' lines are equal. * The following while-loop segments both files into * seglim segments, forks and executes 'diff' on the * segments, and processes the resulting output of * 'diff', which is read from a pipe. */ for (;;) { /* If both files are at EOF, everything is done. */ if (!olp && !nlp) /* finished */ return (0); if (!olp) { /* * Generate appropriate "append" * output without executing 'diff'. */ addgen(&nline, &nbufsiz, &nbuflen, pnewfile); } if (!nlp) { /* * Generate appropriate "delete" * output without executing 'diff'. */ delgen(&oline, &obufsiz, &obuflen, poldfile); } /* * Create a temporary file to hold a segment * from the old file, and write it. */ poldtemp = maket(otmp); otcnt = 0; while (olp && otcnt < seglim) { fwrite(oline, sizeof *oline, obuflen, poldtemp); if (ferror(poldtemp) != 0) { fflags |= FTLMSG; fatal("Can not write to temporary file"); } olp = readline(&oline, &obufsiz, &obuflen, poldfile); otcnt++; } fclose(poldtemp); /* * Create a temporary file to hold a segment * from the new file, and write it. */ pnewtemp = maket(ntmp); ntcnt = 0; while (nlp && ntcnt < seglim) { fwrite(nline, sizeof *nline, nbuflen, pnewtemp); if (ferror(pnewtemp) != 0) { fflags |= FTLMSG; fatal("Can not write to temporary file"); } nlp = readline(&nline, &nbufsiz, &nbuflen, pnewfile); ntcnt++; } fclose(pnewtemp); /* Create pipes and fork. */ if ((pipe(pfd)) == -1) fatal("Can not create pipe"); if ((i = fork()) < 0) { close(pfd[0]); close(pfd[1]); fatal("Can not fork, try again"); } else if (i == 0) { /* child process */ close(pfd[0]); close(1); dup(pfd[1]); close(pfd[1]); putenv("LC_ALL=C"); /* Execute 'diff' on the segment files. */ execlp(diff, diff, "-a", otmp, ntmp, NULL); /* * Exit code here must be > 1. * Parent process treats exit code of 1 from the child * as non-error because the child process "diff" exits * with a status of 1 when a difference is encountered. * The error here is a true error--the parent process * needs to detect it and exit with a non-zero status. */ close(1); snprintf(Error, sizeof (Error), "Can not execute '%s'", diff); fatal_num = 2; fatal(Error); } else { /* parent process */ close(pfd[1]); pipeinp = fdopen(pfd[0], "r"); /* Process 'diff' output. */ while ((dp = readline(&diffline, &dbufsiz, &dbuflen, pipeinp))) { if (isdigit(*dp)) fixnum(diffline); else fwrite(diffline, sizeof *diffline, dbuflen, stdout); } fclose(pipeinp); /* EOF on pipe. */ while (wait(&status) != i); if (status && (!WIFEXITED(status) || WEXITSTATUS(status) != 1)) { snprintf(Error, sizeof (Error), "'%s' failed", diff); fatal(Error); } } linenum += seglim; /* Remove temporary files. */ unlink(otmp); unlink(ntmp); } }
/* Send mail - High level sending routine */ void sendmail(int argc, char **argv) { char **args; char *tp, *zp; char *buf = NULL; size_t bufsize = 0; char last1c; FILE *input; struct stat sbuf; int aret; int i, n; int oldn = 1; int ttyf = 0; int pushrest = 0; int hdrtyp = 0; int ctf = FALSE; int binflg = 0; long count = 0L; struct tm *bp; struct hdrs *hptr; static char pn[] = "sendmail"; reciplist list; buf = smalloc(bufsize = 2048); Dout(pn, 0, "entered\n"); new_reciplist(&list); for (i = 1; i < argc; ++i) { if (argv[i][0] == '-') { if (argv[i][1] == '\0') { errmsg(E_SYNTAX,"Hyphens MAY NOT be followed by spaces"); } if (i > 1) { errmsg(E_SYNTAX,"Options MUST PRECEDE persons"); } done(0); } /* Ensure no NULL names in list */ if (argv[i][0] == '\0' || argv[i][strlen(argv[i])-1] == '!') { errmsg(E_SYNTAX,"Null names are not allowed"); done(0); } add_recip(&list, argv[i], FALSE); /* Don't check for duplication */ } mktmp(); /* Format time */ time(&iop); bp = localtime(&iop); tp = asctime(bp); zp = tzname[bp->tm_isdst]; sprintf(datestring, "%.16s %.4s %.5s", tp, zp, tp+20); trimnl (datestring); /* asctime: Fri Sep 30 00:00:00 1986\n */ /* 0123456789012345678901234 */ /* RFCtime: Fri, 28 Jul 89 10:30 EDT */ sprintf(RFC822datestring, "%.3s, %.2s %.3s %.4s %.5s %.3s", tp, tp+8, tp+4, tp+20, tp+11, zp); /* Write out the from line header for the letter */ if (fromflag && deliverflag && from_user[0] != '\0') { snprintf(buf, bufsize, "%s%s %s\n", header[H_FROM].tag, from_user, datestring); } else { snprintf(buf, bufsize, "%s%s %s\n", header[H_FROM].tag, my_name, datestring); } if (!wtmpf(buf, strlen(buf))) { done(0); } savehdrs(buf, H_FROM); /* Copy to list in mail entry? */ if (flgt == 1 && argc > 1) { aret = argc; args = argv; while (--aret > 0) { snprintf(buf, bufsize, "%s %s\n", header[H_TO].tag, *++args); if (!wtmpf(buf, strlen(buf))) { done(0); } savehdrs(buf, H_TO); } } flgf = 1; /* reset when first read of message body succeeds */ /* Read mail message, allowing for lines of infinite length. This is tricky, have to watch for newlines. */ saveint = setsig(SIGINT, savdead); last1c = ' '; /* anything other than newline */ ttyf = isatty (fileno(stdin)); pushrest = 0; /* * scan header & save relevant info. */ cpy(&fromU, &fromUsize, my_name); cpy(&fromS, &fromSsize, ""); input = stdin; if (fstat(fileno(input), &sbuf) < 0) { #ifdef EOVERFLOW if (errno == EOVERFLOW) { perror("stdin"); exit(1); } #endif } while ((n = getline (&line, &linesize, stdin)) > 0) { last1c = line[n-1]; if (pushrest) { if (!wtmpf(line,n)) { done(0); } pushrest = (last1c != '\n'); continue; } pushrest = (last1c != '\n'); if ((hdrtyp = isheader (line, &ctf)) == FALSE) { break; } flgf = 0; switch (hdrtyp) { case H_RVERS: /* Are we dealing with a delivery report? */ /* dflag = 9 ==> do not return on failure */ dflag = 9; Dout(pn, 0, "dflag = 9\n"); break; case H_FROM: if (!wtmpf(">", 1)) { done(0); } /* note dropthru */ hdrtyp = H_FROM1; case H_FROM1: if (substr(line, "forwarded by") > -1) { break; } pickFrom (line); if (Rpath[0] != '\0') concat(&Rpath, &Rpathsize, "!"); concat(&Rpath, &Rpathsize, fromS); n = 0; /* don't copy remote from's into mesg. */ break; case H_CTYPE: /* suppress it: only generated if needed */ n = 0; /* suppress */ break; case H_TCOPY: /* Write out placeholder for later */ snprintf(buf, bufsize, "%s \n", header[H_TCOPY].tag); if (!wtmpf(buf, strlen(buf))) { done(0); } n = 0; /* suppress */ break; case H_MTYPE: if (flgm) { /* suppress if message-type argument */ n = 0; } break; case H_CONT: if (oldn == 0) { /* suppress continuation line also */ n = 0; } break; } oldn = n; /* remember if this line was suppressed */ if (n && !wtmpf(line,n)) { done(0); } if (!n) savehdrs(line, hdrtyp); } if (Rpath != NULL && Rpath[0] != '\0') concat(&Rpath, &Rpathsize, "!"); concat(&Rpath, &Rpathsize, fromU); /* push out message type if so requested */ if (flgm) { /* message-type */ snprintf(buf, bufsize, "%s%s\n", header[H_MTYPE].tag, msgtype); if (!wtmpf(buf, strlen(buf))) { done(0); } } if (n > bufsize) { free(buf); buf = smalloc(bufsize = n); } memcpy (buf, line, n); if (n == 0 || (ttyf && !strncmp (buf, ".\n", 2)) ) { if (flgf) { /* no input */ return; } else { /* * no content: put content-type * only if explicitly present. * Write out 'place-holders' only. (see below....) */ if ((hptr = hdrlines[H_CTYPE].head) != (struct hdrs *)NULL) { snprintf(line, linesize, "%s \n", header[H_CTYPE].tag); if (!wtmpf(line, strlen(line))) { done(0); } } goto wrapsend; } } if (n == 1 && last1c == '\n') { /* blank line -- suppress */ n = getline (&buf, &bufsize, stdin); if (n == 0 || (ttyf && !strncmp (buf, ".\n", 2)) ) { /* * no content: put content-type * only if explicitly present. * Write out 'place-holder' only. (see below....) */ if ((hptr = hdrlines[H_CTYPE].head) != (struct hdrs *)NULL) { snprintf(line, linesize, "%s \n", header[H_CTYPE].tag); if (!wtmpf(line, strlen(line))) { done(0); } } goto wrapsend; } } if (debug > 0) { buf[n] = '\0'; Dout(pn, 0, "header scan complete, readahead %d = \"%s\"\n", n, buf); } /* * Write out H_CTYPE line. This is used only as * placeholders in the tmp file. When the 'real' message is sent, * the proper value will be put out by copylet(). */ snprintf(line, linesize, "%s \n", header[H_CTYPE].tag); if (!wtmpf(line, strlen(line))) { done(0); } if (hdrlines[H_CTYPE].head == (struct hdrs *)NULL) { savehdrs(line,H_CTYPE); } /* and a blank line */ if (!wtmpf("\n", 1)) { done(0); } Dout(pn, 0, "header out completed\n"); pushrest = 0; count = 0L; /* * Are we returning mail from a delivery failure of an old-style * (SVR3.1 or SVR3.0) rmail? If so, we won't return THIS on failure * [This line should occur as the FIRST non-blank non-header line] */ if (!strncmp("***** UNDELIVERABLE MAIL sent to",buf,32)) { dflag = 9; /* 9 says do not return on failure */ Dout(pn, 0, "found old-style UNDELIVERABLE line. dflag = 9\n"); } /* scan body of message */ while (n > 0) { if (ttyf && !strcmp (buf, ".\n")) break; if (!binflg) { binflg = !istext ((unsigned char *)buf, n); } if (!wtmpf(buf, n)) { done(0); } count += n; n = ttyf ? getline (&buf, &bufsize, stdin) : fread (buf, 1, bufsize, stdin); } setsig(SIGINT, saveint); wrapsend: /* * In order to use some of the subroutines that are used to * read mail, the let array must be set up */ nlet = 1; let[0].adr = 0; let[1].adr = ftell(tmpf); let[0].text = (binflg == 1 ? FALSE : TRUE); Dout(pn, 0, "body copy complete, count %ld\n", count); /* * Modify value of H_CTYPE if necessary. */ if ((hptr = hdrlines[H_CTYPE].head) != (struct hdrs *)NULL) { if (strlen(hptr->value) == 0) strcpy(hptr->value, binflg ? "binary" : "text"); } if (fclose(tmpf) == EOF) { tmpf = NULL; tmperr(); done(0); } tmpf = doopen(lettmp,"r+",E_TMP); /* Do not send mail on SIGINT */ if (dflag == 2) { done(0); } sendlist(&list, 0, 0); done(0); }
void sig_ignore(int signum) { /* we don't use SIG_IGN to make it possible that child catch singals */ setsig(signum, ignore_handler); }
void quitenv(struct shf *shf) { struct env *ep = e; char *cp; int fd; yyrecursive_pop(true); while (ep->oenv && ep->oenv->loc != ep->loc) popblock(); if (ep->savefd != NULL) { for (fd = 0; fd < NUFILE; fd++) /* if ep->savefd[fd] < 0, means fd was closed */ if (ep->savefd[fd]) restfd(fd, ep->savefd[fd]); if (ep->savefd[2]) /* Clear any write errors */ shf_reopen(2, SHF_WR, shl_out); } /* * Bottom of the stack. * Either main shell is exiting or cleanup_parents_env() was called. */ if (ep->oenv == NULL) { #ifdef DEBUG_LEAKS int i; #endif if (ep->type == E_NONE) { /* Main shell exiting? */ #if HAVE_PERSISTENT_HISTORY if (Flag(FTALKING)) hist_finish(); #endif j_exit(); if (ep->flags & EF_FAKE_SIGDIE) { int sig = (exstat & 0xFF) - 128; /* * ham up our death a bit (AT&T ksh * only seems to do this for SIGTERM) * Don't do it for SIGQUIT, since we'd * dump a core.. */ if ((sig == SIGINT || sig == SIGTERM) && (kshpgrp == kshpid)) { setsig(&sigtraps[sig], SIG_DFL, SS_RESTORE_CURR | SS_FORCE); kill(0, sig); } } } if (shf) shf_close(shf); reclaim(); #ifdef DEBUG_LEAKS #ifndef MKSH_NO_CMDLINE_EDITING x_done(); #endif #ifndef MKSH_NOPROSPECTOFWORK /* block at least SIGCHLD during/after afreeall */ sigprocmask(SIG_BLOCK, &sm_sigchld, NULL); #endif afreeall(APERM); for (fd = 3; fd < NUFILE; fd++) if ((i = fcntl(fd, F_GETFD, 0)) != -1 && (i & FD_CLOEXEC)) close(fd); close(2); close(1); close(0); #endif exit(exstat & 0xFF); } if (shf) shf_close(shf); reclaim(); e = e->oenv; /* free the struct env - tricky due to the ALLOC_ITEM inside */ cp = (void *)ep; afree(cp + sizeof(ALLOC_ITEM), ATEMP); }
int main(int argc, char **argv) { char *prog, *optstr, *usagestr; int c, background, unit, active; char base[PATH_MAX], path[PATH_MAX]; unsigned int mode, hdr, xrun, rate, join, mmc, vol; unsigned int hold, autovol, bufsz, round; const char *str; struct aparams ppar, rpar; struct dev *d, *dnext; struct listen *l; struct wav *w; /* * global options defaults */ hdr = HDR_AUTO; xrun = XRUN_IGNORE; vol = MIDI_MAXCTL; join = 1; mmc = 0; hold = 0; autovol = 1; bufsz = 0; round = 0; unit = 0; background = 0; aparams_init(&ppar, 0, 1, DEFAULT_RATE); aparams_init(&rpar, 0, 1, DEFAULT_RATE); mode = MODE_MIDIMASK | MODE_PLAY | MODE_REC; #ifdef DEBUG atexit(dbg_flush); #endif setsig(); filelist_init(); prog = strrchr(argv[0], '/'); if (prog == NULL) prog = argv[0]; else prog++; if (strcmp(prog, PROG_AUCAT) == 0) { optstr = "a:b:c:C:de:f:h:i:j:lL:m:Mno:q:r:s:t:U:v:w:x:z:"; usagestr = aucat_usage; } else if (strcmp(prog, PROG_SNDIOD) == 0) { optstr = "a:b:c:C:de:f:j:L:m:Mq:r:s:t:U:v:w:x:z:"; usagestr = sndiod_usage; background = 1; hold = 0; } else { fprintf(stderr, "%s: can't determine program to run\n", prog); return 1; } while ((c = getopt(argc, argv, optstr)) != -1) { switch (c) { case 'd': #ifdef DEBUG if (debug_level < 4) debug_level++; #endif background = 0; break; case 'U': if (listen_list) errx(1, "-U must come before -L"); unit = strtonum(optarg, 0, MIDI_MAXCTL, &str); if (str) errx(1, "%s: unit number is %s", optarg, str); break; case 'L': listen_new_tcp(optarg, AUCAT_PORT + unit); break; case 'm': mode = opt_mode(); break; case 'h': hdr = opt_hdr(); break; case 'x': xrun = opt_xrun(); break; case 'j': join = opt_onoff(); break; case 't': mmc = opt_mmc(); break; case 'c': opt_ch(&ppar); break; case 'C': opt_ch(&rpar); break; case 'e': opt_enc(&ppar); aparams_copyenc(&rpar, &ppar); break; case 'r': rate = strtonum(optarg, RATE_MIN, RATE_MAX, &str); if (str) errx(1, "%s: rate is %s", optarg, str); ppar.rate = rpar.rate = rate; break; case 'v': vol = strtonum(optarg, 0, MIDI_MAXCTL, &str); if (str) errx(1, "%s: volume is %s", optarg, str); break; case 'i': d = mkdev(NULL, 0, bufsz, round, 1, autovol); w = wav_new_in(&wav_ops, d, mode & (MODE_PLAY | MODE_MIDIOUT), optarg, hdr, &ppar, xrun, vol, mmc, join); if (w == NULL) errx(1, "%s: couldn't create stream", optarg); dev_adjpar(d, w->mode, NULL, &w->hpar); break; case 'o': d = mkdev(NULL, 0, bufsz, round, 1, autovol); w = wav_new_out(&wav_ops, d, mode & (MODE_RECMASK | MODE_MIDIIN), optarg, hdr, &rpar, xrun, mmc, join); if (w == NULL) errx(1, "%s: couldn't create stream", optarg); dev_adjpar(d, w->mode, &w->hpar, NULL); break; case 's': if ((d = dev_list) == NULL) { d = mkdev(DEFAULT_DEV, 0, bufsz, round, hold, autovol); } mkopt(optarg, d, &rpar, &ppar, mode, vol, mmc, join); /* XXX: set device rate, if never set */ break; case 'q': d = mkdev(NULL, mode, bufsz, round, 1, autovol); if (!devctl_add(d, optarg, MODE_MIDIMASK)) errx(1, "%s: can't open port", optarg); d->reqmode |= MODE_MIDIMASK; break; case 'a': hold = opt_onoff(); break; case 'w': autovol = opt_onoff(); break; case 'b': bufsz = strtonum(optarg, 1, RATE_MAX * 5, &str); if (str) errx(1, "%s: buffer size is %s", optarg, str); break; case 'z': round = strtonum(optarg, 1, SHRT_MAX, &str); if (str) errx(1, "%s: block size is %s", optarg, str); break; case 'f': mkdev(optarg, 0, bufsz, round, hold, autovol); break; case 'n': mkdev("loopback", MODE_LOOP, bufsz, round, 1, autovol); break; case 'M': mkdev("midithru", MODE_THRU, 0, 0, hold, 0); break; case 'l': background = 1; break; default: fputs(usagestr, stderr); exit(1); } } argc -= optind; argv += optind; if (argc > 0) { fputs(usagestr, stderr); exit(1); } if (wav_list) { if (opt_list || listen_list) errx(1, "-io not allowed in server mode"); if ((d = dev_list) && d->next) errx(1, "only one device allowed in non-server mode"); if ((d->reqmode & MODE_THRU) && d->ctl_list == NULL) { if (!devctl_add(d, "default", MODE_MIDIMASK)) errx(1, "%s: can't open port", optarg); d->reqmode |= MODE_MIDIMASK; } } else { if (dev_list == NULL) mkdev(DEFAULT_DEV, 0, bufsz, round, hold, autovol); for (d = dev_list; d != NULL; d = d->next) { if (opt_byname("default", d->num)) continue; mkopt("default", d, &rpar, &ppar, mode, vol, mmc, join); } } if (opt_list) { getbasepath(base, sizeof(base)); snprintf(path, PATH_MAX, "%s/%s%u", base, AUCAT_PATH, unit); listen_new_un(path); if (geteuid() == 0) privdrop(); } for (w = wav_list; w != NULL; w = w->next) { if (!wav_init(w)) exit(1); } for (d = dev_list; d != NULL; d = d->next) { if (!dev_init(d)) exit(1); if (d->autostart && (d->mode & MODE_AUDIOMASK)) dev_mmcstart(d); } for (l = listen_list; l != NULL; l = l->next) { if (!listen_init(l)) exit(1); } if (background) { #ifdef DEBUG debug_level = 0; dbg_flush(); #endif if (daemon(0, 0) < 0) err(1, "daemon"); } /* * Loop, start audio. */ for (;;) { if (quit_flag) break; active = 0; for (d = dev_list; d != NULL; d = dnext) { dnext = d->next; if (!dev_run(d)) goto fatal; if (d->refcnt > 0) active = 1; } if (dev_list == NULL) break; if (!opt_list && !active) break; if (!file_poll()) break; } fatal: while (listen_list != NULL) file_close(&listen_list->file); /* * give a chance to drain */ for (d = dev_list; d != NULL; d = d->next) dev_drain(d); while (file_poll()) ; /* nothing */ while (dev_list) dev_del(dev_list); filelist_done(); if (opt_list) { if (rmdir(base) < 0 && errno != ENOTEMPTY && errno != EPERM) warn("rmdir(\"%s\")", base); } unsetsig(); return 0; }
/* Called by c_print() to undo whatever block_pipe() did */ void restore_pipe(int restore_dfl) { if (restore_dfl) setsig(&sigtraps[SIGPIPE], SIG_DFL, SS_RESTORE_CURR); }
static unsigned ProgRun( int step ) { static int ptrace_sig = 0; static int ld_state = 0; user_regs_struct regs; int status; prog_go_ret *ret; void (*old)(int); int debug_continue; if( pid == 0 ) return( 0 ); ret = GetOutPtr( 0 ); if( at_end ) { ptrace_sig = 0; ret->conditions = COND_TERMINATE; goto end; } /* we only want child-generated SIGINTs now */ do { old = setsig( SIGINT, SIG_IGN ); if( step ) { Out( "PTRACE_SINGLESTEP\n" ); if( ptrace( PTRACE_SINGLESTEP, pid, NULL, (void *)ptrace_sig ) == -1 ) perror( "PTRACE_SINGLESTEP" ); } else { Out( "PTRACE_CONT\n" ); if( ptrace( PTRACE_CONT, pid, NULL, (void *)ptrace_sig ) == -1 ) perror( "PTRACE_CONT" ); } waitpid( pid, &status, 0 ); setsig( SIGINT, old ); #if defined( MD_x86 ) ptrace( PTRACE_GETREGS, pid, NULL, ®s ); #elif defined( MD_ppc ) regs.eip = ptrace( PTRACE_PEEKUSER, pid, REGSIZE * PT_NIP, NULL ); regs.esp = ptrace( PTRACE_PEEKUSER, pid, REGSIZE * PT_R1, NULL ); #elif defined( MD_mips ) regs.eip = ptrace( PTRACE_PEEKUSER, pid, (void *)PC, NULL ); regs.esp = ptrace( PTRACE_PEEKUSER, pid, (void *)29, NULL ); #endif Out( " eip " ); OutNum( regs.eip ); Out( "\n" ); debug_continue = FALSE; if( WIFSTOPPED( status ) ) { switch( ( ptrace_sig = WSTOPSIG( status ) ) ) { case SIGSEGV: case SIGILL: case SIGFPE: case SIGABRT: case SIGBUS: case SIGQUIT: case SIGSYS: last_sig = ptrace_sig; ret->conditions = COND_EXCEPTION; ptrace_sig = 0; break; case SIGINT: ret->conditions = COND_USER; ptrace_sig = 0; break; case SIGTRAP: ret->conditions = step ? COND_TRACE : COND_BREAK; Out( "sigtrap\n" ); ptrace_sig = 0; break; default: /* For signals that we do not wish to handle, we need * to continue the debuggee until we get a signal * that we need to handle */ Out( "Unknown signal " ); OutNum( ptrace_sig ); Out( "\n" ); debug_continue = TRUE; break; } } else if( WIFEXITED( status ) ) { Out( "WIFEXITED\n" ); at_end = TRUE; ret->conditions = COND_TERMINATE; ptrace_sig = 0; goto end; } } while( debug_continue ); if( ret->conditions == COND_BREAK ) { #if defined( MD_x86 ) if( regs.eip == rdebug.r_brk + sizeof( old_ld_bp ) ) { #elif defined( MD_ppc ) || defined( MD_mips ) if( regs.eip == rdebug.r_brk ) { #endif int psig = 0; void (*oldsig)(int); bp_t opcode = BRK_POINT; /* The dynamic linker breakpoint was hit, meaning that * libraries are being loaded or unloaded. This gets a bit * tricky because we must restore the original code that was * at the breakpoint and execute it, but we still want to * keep the breakpoint. */ WriteMem( pid, &old_ld_bp, rdebug.r_brk, sizeof( old_ld_bp ) ); ReadMem( pid, &rdebug, (addr48_off)dbg_rdebug, sizeof( rdebug ) ); Out( "ld breakpoint hit, state is " ); switch( rdebug.r_state ) { case RT_ADD: Out( "RT_ADD\n" ); ld_state = RT_ADD; AddOneLib( rdebug.r_map ); break; case RT_DELETE: Out( "RT_DELETE\n" ); ld_state = RT_DELETE; break; case RT_CONSISTENT: Out( "RT_CONSISTENT\n" ); if( ld_state == RT_DELETE ) DelOneLib( rdebug.r_map ); ld_state = RT_CONSISTENT; break; default: Out( "error!\n" ); break; } regs.orig_eax = -1; #if defined( MD_x86 ) regs.eip--; ptrace( PTRACE_SETREGS, pid, NULL, ®s ); #endif oldsig = setsig( SIGINT, SIG_IGN ); ptrace( PTRACE_SINGLESTEP, pid, NULL, (void *)psig ); waitpid( pid, &status, 0 ); setsig( SIGINT, oldsig ); WriteMem( pid, &opcode, rdebug.r_brk, sizeof( old_ld_bp ) ); ret->conditions = COND_LIBRARIES; } else { #if defined( MD_x86 ) Out( "decrease eip(sigtrap)\n" ); regs.orig_eax = -1; regs.eip--; ptrace( PTRACE_SETREGS, pid, NULL, ®s ); #endif } } orig_eax = regs.orig_eax; last_eip = regs.eip; ret->program_counter.offset = regs.eip; ret->program_counter.segment = regs.cs; ret->stack_pointer.offset = regs.esp; ret->stack_pointer.segment = regs.ss; ret->conditions |= COND_CONFIG; /* If debuggee has dynamic section, try getting the r_debug struct * every time the debuggee stops. The r_debug data may not be available * immediately after the debuggee process loads. */ if( !have_rdebug && (dbg_dyn != NULL) ) { if( Get_ld_info( pid, dbg_dyn, &rdebug, &dbg_rdebug ) ) { bp_t opcode; AddInitialLibs( rdebug.r_map ); have_rdebug = TRUE; ret->conditions |= COND_LIBRARIES; /* Set a breakpoint in dynamic linker. That way we can be * informed on dynamic library load/unload events. */ ReadMem( pid, &old_ld_bp, rdebug.r_brk, sizeof( old_ld_bp ) ); Out( "Setting ld breakpoint at " ); OutNum( rdebug.r_brk ); Out( " old opcode was " ); OutNum( old_ld_bp ); Out( "\n" ); opcode = BRK_POINT; WriteMem( pid, &opcode, rdebug.r_brk, sizeof( opcode ) ); } } end: CONV_LE_32( ret->stack_pointer.offset ); CONV_LE_16( ret->stack_pointer.segment ); CONV_LE_32( ret->program_counter.offset ); CONV_LE_16( ret->program_counter.segment ); CONV_LE_16( ret->conditions ); return( sizeof( *ret ) ); } unsigned ReqProg_step( void ) { return( ProgRun( TRUE ) ); } unsigned ReqProg_go( void ) { return( ProgRun( FALSE ) ); } unsigned ReqRedirect_stdin( void ) { redirect_stdin_ret *ret; ret = GetOutPtr( 0 ); ret->err = 1; return( sizeof( *ret ) ); }