Beispiel #1
0
static void
smopts_core(const char *sname, char **argv)
{
	struct smopts_s *sp;
	struct name *np;
	struct name *t;
	int h;
	char **ap;

	if ((sp = findsmopts(sname, 1)) != NULL) {
		char *cp;
		cp = detract(sp->s_smopts, GSMOPTS);
		(void)printf("%s already defined as: %s\n", sname, cp);
		return;
	}
	h = hashcase(sname);
	sp = ecalloc(1, sizeof(*sp));
	sp->s_name = vcopy(sname);
	if (smoptstbl[h])
		sp->s_link = smoptstbl[h];
	smoptstbl[h] = sp;

	np = NULL;
	for (ap = argv + 1; *ap != NULL; ap++) {
		t = ncalloc(*ap, GSMOPTS);
		if (sp->s_smopts == NULL)
			sp->s_smopts = t;
		else
			np->n_flink = t;
		t->n_blink = np;
		np = t;
	}
}
Beispiel #2
0
static void
printsmopts(const char *name)
{
	struct smopts_s *sp;

	if ((sp = findsmopts(name, 1)) == NULL) {
		(void)printf("%s:\n", name);
		return;
	}
	(void)printf("%s:\t%s\n", sp->s_name, detract(sp->s_smopts, GSMOPTS));
}
Beispiel #3
0
void
grabedit(struct header* hp, unsigned long type)
{
	register char*			s;
	register const struct lab*	lp;
	int				r;
	sig_t				saveint;
	sig_t				savequit;
	char				buf[LINESIZE];

	fflush(stdout);
	if ((saveint = signal(SIGINT, SIG_IGN)) == SIG_DFL)
		signal(SIGINT, SIG_DFL);
	if ((savequit = signal(SIGQUIT, SIG_IGN)) == SIG_DFL)
		signal(SIGQUIT, SIG_DFL);
	r = 0;
	for (lp = state.hdrtab; lp->name; lp++)
		if (type & lp->type) {
			if (!(s = detract(hp, lp->type)))
				s = "";
			if (strlen(s) >= sizeof(buf)) {
				note(0, "%sfield too long to edit", lp->name);
				continue;
			}
			strcpy(buf, s);
			if ((r = ttyedit(0, 1, lp->name, buf, sizeof(buf))) < 0)
				break;
			headclear(hp, lp->type);
			extract(hp, lp->type, buf);
		}
	if (saveint != SIG_DFL)
		signal(SIGINT, saveint);
	if (savequit != SIG_DFL)
		signal(SIGQUIT, savequit);
	if (r < -1)
		kill(0, -(r + 1));
}
Beispiel #4
0
/*
 * Read all relevant header fields.
 */
int
grabh(struct header *hp, int gflags)
{
	struct termios ttybuf;
#ifndef TIOCSTI
	struct sigaction savequit;
#else
# ifdef	TIOCEXT
	int extproc;
	int flag;
# endif /* TIOCEXT */
#endif
	struct sigaction savetstp;
	struct sigaction savettou;
	struct sigaction savettin;
	struct sigaction act;
	char *s;
	int error;

	sigemptyset(&act.sa_mask);
	act.sa_flags = SA_RESTART;
	act.sa_handler = SIG_DFL;
	(void)sigaction(SIGTSTP, &act, &savetstp);
	(void)sigaction(SIGTTOU, &act, &savettou);
	(void)sigaction(SIGTTIN, &act, &savettin);
	error = 1;
#ifndef TIOCSTI
	ttyset = 0;
#endif
	if (tcgetattr(fileno(stdin), &ttybuf) < 0) {
		warn("tcgetattr");
		return(-1);
	}
	c_erase = ttybuf.c_cc[VERASE];
	c_kill = ttybuf.c_cc[VKILL];
#ifndef TIOCSTI
	ttybuf.c_cc[VERASE] = 0;
	ttybuf.c_cc[VKILL] = 0;
	act.sa_handler = SIG_IGN;
	if (sigaction(SIGQUIT, &act, &savequit) == 0 &&
	    savequit.sa_handler == SIG_DFL)
		(void)sigaction(SIGQUIT, &savequit, NULL);
#else
# ifdef	TIOCEXT
	extproc = ((ttybuf.c_lflag & EXTPROC) ? 1 : 0);
	if (extproc) {
		flag = 0;
		if (ioctl(fileno(stdin), TIOCEXT, &flag) < 0)
			warn("TIOCEXT: off");
	}
# endif /* TIOCEXT */
#endif
	if (gflags & GTO) {
#ifndef TIOCSTI
		if (!ttyset && hp->h_to != NULL)
			ttyset++, tcsetattr(fileno(stdin), TCSADRAIN, &ttybuf);
#endif
		s = readtty("To: ", detract(hp->h_to, 0));
		if (s == NULL)
			goto out;
		hp->h_to = extract(s, GTO);
	}
	if (gflags & GSUBJECT) {
#ifndef TIOCSTI
		if (!ttyset && hp->h_subject != NULL)
			ttyset++, tcsetattr(fileno(stdin), TCSADRAIN, &ttybuf);
#endif
		s = readtty("Subject: ", hp->h_subject);
		if (s == NULL)
			goto out;
		hp->h_subject = s;
	}
	if (gflags & GCC) {
#ifndef TIOCSTI
		if (!ttyset && hp->h_cc != NULL)
			ttyset++, tcsetattr(fileno(stdin), TCSADRAIN, &ttybuf);
#endif
		s = readtty("Cc: ", detract(hp->h_cc, 0));
		if (s == NULL)
			goto out;
		hp->h_cc = extract(s, GCC);
	}
	if (gflags & GBCC) {
#ifndef TIOCSTI
		if (!ttyset && hp->h_bcc != NULL)
			ttyset++, tcsetattr(fileno(stdin), TCSADRAIN, &ttybuf);
#endif
		s = readtty("Bcc: ", detract(hp->h_bcc, 0));
		if (s == NULL)
			goto out;
		hp->h_bcc = extract(s, GBCC);
	}
	error = 0;
out:
	(void)sigaction(SIGTSTP, &savetstp, NULL);
	(void)sigaction(SIGTTOU, &savettou, NULL);
	(void)sigaction(SIGTTIN, &savettin, NULL);
#ifndef TIOCSTI
	ttybuf.c_cc[VERASE] = c_erase;
	ttybuf.c_cc[VKILL] = c_kill;
	if (ttyset)
		tcsetattr(fileno(stdin), TCSADRAIN, &ttybuf);
	(void)sigaction(SIGQUIT, &savequit, NULL);
#else
# ifdef	TIOCEXT
	if (extproc) {
		flag = 1;
		if (ioctl(fileno(stdin), TIOCEXT, &flag) < 0)
			warn("TIOCEXT: on");
	}
# endif /* TIOCEXT */
#endif
	return(error);
}
Beispiel #5
0
/*
 * Mail a message on standard input to the people indicated
 * in the passed header.  (Internal interface).
 */
void
mail1(struct header *hp, int printheaders)
{
	char *cp;
	char *nbuf;
	int pid;
	char **namelist;
	struct name *to, *nsto;
	FILE *mtf;

	/*
	 * Collect user's mail from standard input.
	 * Get the result as mtf.
	 */
	if ((mtf = collect(hp, printheaders)) == NULL)
		return;
	if (value("interactive") != NULL) {
		if (value("askcc") != NULL || value("askbcc") != NULL) {
			if (value("askcc") != NULL)
				grabh(hp, GCC);
			if (value("askbcc") != NULL)
				grabh(hp, GBCC);
		} else {
			printf("EOT\n");
			(void)fflush(stdout);
		}
	}
	if (fsize(mtf) == 0) {
		if (value("dontsendempty") != NULL)
			goto out;
		if (hp->h_subject == NULL)
			printf("No message, no subject; hope that's ok\n");
		else
			printf("Null message body; hope that's ok\n");
	}
	/*
	 * Now, take the user names from the combined
	 * to and cc lists and do all the alias
	 * processing.
	 */
	senderr = 0;
	to = usermap(cat(hp->h_bcc, cat(hp->h_to, hp->h_cc)));
	if (to == NULL) {
		printf("No recipients specified\n");
		senderr++;
	}
	/*
	 * Look through the recipient list for names with /'s
	 * in them which we write to as files directly.
	 */
	to = outof(to, mtf, hp);
	if (senderr)
		savedeadletter(mtf);
	to = elide(to);
	if (count(to) == 0)
		goto out;
	if (value("recordrecip") != NULL) {
		/*
		 * Before fixing the header, save old To:.
		 * We do this because elide above has sorted To: list, and
		 * we would like to save message in a file named by the first
		 * recipient the user has entered, not the one being the first
		 * after sorting happened.
		 */
		if ((nsto = malloc(sizeof(struct name))) == NULL)
			err(1, "Out of memory");
		bcopy(hp->h_to, nsto, sizeof(struct name));
	}
	fixhead(hp, to);
	if ((mtf = infix(hp, mtf)) == NULL) {
		fprintf(stderr, ". . . message lost, sorry.\n");
		return;
	}
	namelist = unpack(cat(hp->h_smopts, to));
	if (debug) {
		char **t;

		printf("Sendmail arguments:");
		for (t = namelist; *t != NULL; t++)
			printf(" \"%s\"", *t);
		printf("\n");
		goto out;
	}
	if (value("recordrecip") != NULL) {
		/*
		 * Extract first recipient username from saved To: and use it
		 * as a filename.
		 */
		if ((nbuf = malloc(strlen(detract(nsto, 0)) + 1)) == NULL)
			err(1, "Out of memory");
		if ((cp = yanklogin(detract(nsto, 0), nbuf)) != NULL)
			(void)savemail(expand(nbuf), mtf);
		free(nbuf);
		free(nsto);
	} else if ((cp = value("record")) != NULL)
		(void)savemail(expand(cp), mtf);
	/*
	 * Fork, set up the temporary mail file as standard
	 * input for "mail", and exec with the user list we generated
	 * far above.
	 */
	pid = fork();
	if (pid == -1) {
		warn("fork");
		savedeadletter(mtf);
		goto out;
	}
	if (pid == 0) {
		sigset_t nset;
		(void)sigemptyset(&nset);
		(void)sigaddset(&nset, SIGHUP);
		(void)sigaddset(&nset, SIGINT);
		(void)sigaddset(&nset, SIGQUIT);
		(void)sigaddset(&nset, SIGTSTP);
		(void)sigaddset(&nset, SIGTTIN);
		(void)sigaddset(&nset, SIGTTOU);
		prepare_child(&nset, fileno(mtf), -1);
		if ((cp = value("sendmail")) != NULL)
			cp = expand(cp);
		else
			cp = _PATH_SENDMAIL;
		execv(cp, namelist);
		warn("%s", cp);
		_exit(1);
	}
	if (value("verbose") != NULL)
		(void)wait_child(pid);
	else
		free_child(pid);
out:
	(void)Fclose(mtf);
}
Beispiel #6
0
int
grabh(struct header *hp, int gflags)
{
	struct termios ttybuf;
	sig_t saveint;
	sig_t savetstp;
	sig_t savettou;
	sig_t savettin;
	int errs;
#ifndef TIOCSTI
	sig_t savequit;
#else
# ifdef TIOCEXT
	int extproc, flag;
# endif /* TIOCEXT */
#endif /* TIOCSTI */

	savetstp = signal(SIGTSTP, SIG_DFL);
	savettou = signal(SIGTTOU, SIG_DFL);
	savettin = signal(SIGTTIN, SIG_DFL);
	errs = 0;
#ifndef TIOCSTI
	ttyset = 0;
#endif
	if (tcgetattr(fileno(stdin), &ttybuf) < 0) {
		warn("tcgetattr(stdin)");
		return (-1);
	}
	c_erase = ttybuf.c_cc[VERASE];
	c_kill = ttybuf.c_cc[VKILL];
#ifndef TIOCSTI
	ttybuf.c_cc[VERASE] = _POSIX_VDISABLE;
	ttybuf.c_cc[VKILL] = _POSIX_VDISABLE;
	if ((saveint = signal(SIGINT, SIG_IGN)) == SIG_DFL)
		(void)signal(SIGINT, SIG_DFL);
	if ((savequit = signal(SIGQUIT, SIG_IGN)) == SIG_DFL)
		(void)signal(SIGQUIT, SIG_DFL);
#else
# ifdef		TIOCEXT
	extproc = ((ttybuf.c_lflag & EXTPROC) ? 1 : 0);
	if (extproc) {
		flag = 0;
		if (ioctl(fileno(stdin), TIOCEXT, &flag) < 0)
			warn("TIOCEXT: off");
	}
# endif	/* TIOCEXT */
	if (setjmp(intjmp))
		goto out;
	saveint = signal(SIGINT, ttyint);
#endif
	if (gflags & GTO) {
#ifndef TIOCSTI
		if (!ttyset && hp->h_to != NULL)
			ttyset++, tcsetattr(fileno(stdin), TCSADRAIN, &ttybuf);
#endif
		hp->h_to =
			extract(readtty("To: ", detract(hp->h_to, 0)), GTO);
	}
	if (gflags & GSUBJECT) {
#ifndef TIOCSTI
		if (!ttyset && hp->h_subject != NULL)
			ttyset++, tcsetattr(fileno(stdin), TCSADRAIN, &ttybuf);
#endif
		hp->h_subject = readtty("Subject: ", hp->h_subject);
	}
	if (gflags & GCC) {
#ifndef TIOCSTI
		if (!ttyset && hp->h_cc != NULL)
			ttyset++, tcsetattr(fileno(stdin), TCSADRAIN, &ttybuf);
#endif
		hp->h_cc =
			extract(readtty("Cc: ", detract(hp->h_cc, 0)), GCC);
	}
	if (gflags & GBCC) {
#ifndef TIOCSTI
		if (!ttyset && hp->h_bcc != NULL)
			ttyset++, tcsetattr(fileno(stdin), TCSADRAIN, &ttybuf);
#endif
		hp->h_bcc =
			extract(readtty("Bcc: ", detract(hp->h_bcc, 0)), GBCC);
	}
out:
	(void)signal(SIGTSTP, savetstp);
	(void)signal(SIGTTOU, savettou);
	(void)signal(SIGTTIN, savettin);
#ifndef TIOCSTI
	ttybuf.c_cc[VERASE] = c_erase;
	ttybuf.c_cc[VKILL] = c_kill;
	if (ttyset)
		tcsetattr(fileno(stdin), TCSADRAIN, &ttybuf);
	(void)signal(SIGQUIT, savequit);
#else
# ifdef		TIOCEXT
	if (extproc) {
		flag = 1;
		if (ioctl(fileno(stdin), TIOCEXT, &flag) < 0)
			warn("TIOCEXT: on");
	}
# endif	/* TIOCEXT */
#endif
	(void)signal(SIGINT, saveint);
	return (errs);
}
Beispiel #7
0
/*
 * Mail a message on standard input to the people indicated
 * in the passed header.  (Internal interface).
 */
void 
mail1(struct header *hp, int use_to, char *orig_to)
{
	pid_t p, pid;
	int i, s, gotcha;
	char **namelist, *deliver;
	struct name *to, *np;
	FILE *mtf, *fp;
	int remote = rflag != NOSTR || rmail;
	char **t;
	char *deadletter;
	char recfile[PATHSIZE];

	/*
	 * Collect user's mail from standard input.
	 * Get the result as mtf.
	 */

	pid = (pid_t)-1;
	if ((mtf = collect(hp)) == NULL)
		return;
	hp->h_seq = 1;
	if (hp->h_subject == NOSTR)
		hp->h_subject = sflag;
	if (fsize(mtf) == 0 && hp->h_subject == NOSTR) {
		printf(gettext("No message !?!\n"));
		goto out;
	}
	if (intty) {
		printf(gettext("EOT\n"));
		flush();
	}

	/*
	 * If we need to use the To: line to determine the record
	 * file, save a copy of it before it's sorted below.
	 */

	if (use_to && orig_to == NOSTR && hp->h_to != NOSTR)
		orig_to = strcpy((char *)salloc(strlen(hp->h_to)+1), hp->h_to);
	else if (orig_to == NOSTR)
		orig_to = "";

	/*
	 * Now, take the user names from the combined
	 * to and cc lists and do all the alias
	 * processing.
	 */

	senderr = 0;
	to = cat(extract(hp->h_bcc, GBCC),
	     cat(extract(hp->h_to, GTO),
	     extract(hp->h_cc, GCC)));
	to = translate(outpre(elide(usermap(to))));
	if (!senderr)
		mapf(to, myname);
	mechk(to);
	for (gotcha = 0, np = to; np != NIL; np = np->n_flink)
		if ((np->n_type & GDEL) == 0)
			gotcha++;
	hp->h_to = detract(to, GTO);
	hp->h_cc = detract(to, GCC);
	hp->h_bcc = detract(to, GBCC);
	if ((mtf = infix(hp, mtf)) == NULL) {
		fprintf(stderr, gettext(". . . message lost, sorry.\n"));
		return;
	}
	rewind(mtf);
	if (askme && isatty(0)) {
		char ans[64];
		puthead(hp, stdout, GTO|GCC|GBCC, 0);
		printf(gettext("Send? "));
		printf("[yes] ");
		if (fgets(ans, sizeof(ans), stdin) && ans[0] &&
				(tolower(ans[0]) != 'y' && ans[0] != '\n'))
			goto dead;
	}
	if (senderr)
		goto dead;
	/*
	 * Look through the recipient list for names with /'s
	 * in them which we write to as files directly.
	 */
	i = outof(to, mtf);
	rewind(mtf);
	if (!gotcha && !i) {
		printf(gettext("No recipients specified\n"));
		goto dead;
	}
	if (senderr)
		goto dead;

	getrecf(orig_to, recfile, use_to, sizeof (recfile));
	if (recfile != NOSTR && *recfile)
		savemail(safeexpand(recfile), hp, mtf);
	if (!gotcha)
		goto out;
	namelist = unpack(to);
	if (debug) {
		fprintf(stderr, "Recipients of message:\n");
		for (t = namelist; *t != NOSTR; t++)
			fprintf(stderr, " \"%s\"", *t);
		fprintf(stderr, "\n");
		return;
	}

	/*
	 * Wait, to absorb a potential zombie, then
	 * fork, set up the temporary mail file as standard
	 * input for "mail" and exec with the user list we generated
	 * far above. Return the process id to caller in case he
	 * wants to await the completion of mail.
	 */

#ifdef VMUNIX
	while (wait3((int *)0, WNOHANG, (struct rusage *)0) > 0)
		;
#else
#ifdef preSVr4
	wait((int *)0);
#else
	while (waitpid((pid_t)-1, (int *)0, WNOHANG) > 0)
		;
#endif
#endif
	rewind(mtf);
	pid = fork();
	if (pid == (pid_t)-1) {
		perror("fork");
dead:
		deadletter = Getf("DEAD");
		if (fp = fopen(deadletter,
		    value("appenddeadletter") == NOSTR ? "w" : "a")) {
			chmod(deadletter, DEADPERM);
			puthead(hp, fp, GMASK|GCLEN, fsize(mtf) - textpos);
			fseek(mtf, textpos, 0);
			lcwrite(deadletter, mtf, fp,
			    value("appenddeadletter") != NOSTR);
			fclose(fp);
		} else
			perror(deadletter);
		goto out;
	}
	if (pid == 0) {
		sigchild();
#ifdef SIGTSTP
		if (remote == 0) {
			sigset(SIGTSTP, SIG_IGN);
			sigset(SIGTTIN, SIG_IGN);
			sigset(SIGTTOU, SIG_IGN);
		}
#endif
		sigset(SIGHUP, SIG_IGN);
		sigset(SIGINT, SIG_IGN);
		sigset(SIGQUIT, SIG_IGN);
		s = fileno(mtf);
		(void) fdwalk(closefd_walk, &s);
		close(0);
		dup(s);
		close(s);
#ifdef CC
		submit(getpid());
#endif /* CC */
		if ((deliver = value("sendmail")) == NOSTR)
#ifdef SENDMAIL
			deliver = SENDMAIL;
#else
			deliver = MAIL;
#endif
		execvp(safeexpand(deliver), namelist);
		perror(deliver);
		exit(1);
	}

	if (value("sendwait")!=NOSTR)
		remote++;
out:
	if (remote) {
		while ((p = wait(&s)) != pid && p != (pid_t)-1)
			;
		if (s != 0)
			senderr++;
		pid = 0;
	}
	fclose(mtf);
	return;
}
Beispiel #8
0
/*
 * Read all relevant header fields.
 * Returns 0 on success; 1 if there was an error or signal.
 */
PUBLIC int
grabh(struct header *hp, int gflags)
{
	sig_t volatile old_sigint;
	int retval;
#ifndef USE_EDITLINE
	struct termios ttybuf;
# if defined(TIOCSTI) && defined(TIOCEXT)
	int extproc;
# endif

	if (save_erase_and_kill(&ttybuf))
		return -1;

# if defined(TIOCSTI) && defined(TIOCEXT)
	extproc = ((ttybuf.c_lflag & EXTPROC) ? 1 : 0);
	if (extproc) {
		int flag;

		flag = 0;
		if (ioctl(fileno(stdin), TIOCEXT, &flag) == -1)
			warn("TIOCEXT: off");
	}
# endif
#endif /* USE_EDITLINE */

	sig_check();
	old_sigint = sig_signal(SIGINT, tty_sigint);

	/* return here if we detect a SIGINT */
	if ((retval = setjmp(tty_jmpbuf)) != 0) {
		(void)putc('\n', stdout);
		goto out;
	}

	/*
	 * Do this irrespective of whether the initial string is empty.
	 * Otherwise, the editing is inconsistent.
	 */
	disable_erase_and_kill(&ttybuf);

	if (gflags & GTO) {
		hp->h_to =
		    extract(readtty("To: ", detract(hp->h_to, 0)), GTO);
	}
	if (gflags & GSUBJECT) {
		hp->h_subject = readtty("Subject: ", hp->h_subject);
	}
	if (gflags & GCC) {
		hp->h_cc =
		    extract(readtty("Cc: ", detract(hp->h_cc, 0)), GCC);
	}
	if (gflags & GBCC) {
		hp->h_bcc =
		    extract(readtty("Bcc: ", detract(hp->h_bcc, 0)), GBCC);
	}
	if (gflags & GSMOPTS) {
		hp->h_smopts =
		    shextract(readtty("Smopts: ", detract(hp->h_smopts, 0)),
			GSMOPTS);
	}
#ifdef MIME_SUPPORT
	if (gflags & GSMOPTS) {	/* XXX - Use a new flag for this? */
		if (hp->h_attach) {
			struct attachment *ap;
			int i;

			i = 0;
			for (ap = hp->h_attach; ap; ap = ap->a_flink)
				i++;
			(void)printf("Attachment%s: %d\n", i > 1 ? "s" : "", i);
		}
	}
#endif
 out:
	restore_erase_and_kill(&ttybuf);

#ifndef USE_EDITLINE
# if defined(TIOCSTI) && defined(TIOCEXT)
	if (extproc) {
		int flag;
		flag = 1;
		if (ioctl(fileno(stdin), TIOCEXT, &flag) == -1)
			warn("TIOCEXT: on");
	}
# endif
#endif
	(void)sig_signal(SIGINT, old_sigint);
	sig_check();
	return retval;
}