Пример #1
0
/* 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 */
}
Пример #2
0
/*
 * 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);
}
Пример #3
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 */
}
Пример #4
0
/*
 * 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);
}
Пример #5
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);
}
Пример #6
0
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;
}
Пример #7
0
/* 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;
}
Пример #8
0
/* 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();
	}
}
Пример #9
0
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;
}
Пример #10
0
/*
 *	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;
}
Пример #11
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);
}
Пример #12
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;
}
Пример #13
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);
	}
}
Пример #14
0
/*
	 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);
}
Пример #15
0
void
sig_ignore(int signum)
{
	/* we don't use SIG_IGN to make it possible that child catch singals */
	setsig(signum, ignore_handler);
}
Пример #16
0
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);
}
Пример #17
0
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;
}
Пример #18
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);
}
Пример #19
0
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, &regs );
#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, &regs );
#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, &regs );
#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 ) );
}