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; } }
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)); }
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)); }
/* * 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); }
/* * 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); }
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); }
/* * 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; }
/* * 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; }