122469Sdist /*
262083Sbostic * Copyright (c) 1980, 1993
362083Sbostic * The Regents of the University of California. All rights reserved.
433499Sbostic *
542741Sbostic * %sccs.include.redist.c%
622469Sdist */
722469Sdist
834905Sbostic #ifndef lint
9*68818Sdab static char sccsid[] = "@(#)tty.c 8.2 (Berkeley) 04/20/95";
1034905Sbostic #endif /* not lint */
111247Skas
121247Skas /*
131247Skas * Mail -- a mail program
141247Skas *
151247Skas * Generally useful tty stuff.
161247Skas */
171247Skas
181247Skas #include "rcv.h"
1954505Sbostic #include "extern.h"
201247Skas
211247Skas static int c_erase; /* Current erase char */
221247Skas static int c_kill; /* Current kill char */
233422Skurt static jmp_buf rewrite; /* Place to go when continued */
2437482Sedward static jmp_buf intjmp; /* Place to go when interrupted */
251247Skas #ifndef TIOCSTI
261247Skas static int ttyset; /* We must now do erase/kill */
271247Skas #endif
281247Skas
291247Skas /*
301247Skas * Read all relevant header fields.
311247Skas */
321247Skas
3354505Sbostic int
grabh(hp,gflags)341247Skas grabh(hp, gflags)
351247Skas struct header *hp;
3654505Sbostic int gflags;
371247Skas {
38*68818Sdab struct termios ttybuf;
3939612Sedward sig_t saveint;
401247Skas #ifndef TIOCSTI
4139612Sedward sig_t savequit;
42*68818Sdab #else
43*68818Sdab int extproc, flag;
441247Skas #endif
4539612Sedward sig_t savetstp;
4639612Sedward sig_t savettou;
4739612Sedward sig_t savettin;
481247Skas int errs;
4947707Sbostic void ttyint();
501247Skas
5137482Sedward savetstp = signal(SIGTSTP, SIG_DFL);
5237482Sedward savettou = signal(SIGTTOU, SIG_DFL);
5337482Sedward savettin = signal(SIGTTIN, SIG_DFL);
541247Skas errs = 0;
551247Skas #ifndef TIOCSTI
561247Skas ttyset = 0;
571247Skas #endif
58*68818Sdab if (ioctl(fileno(stdin), TIOCGETA, &ttybuf) < 0) {
59*68818Sdab perror("TIOCGETA");
601247Skas return(-1);
611247Skas }
62*68818Sdab c_erase = ttybuf.c_cc[VERASE];
63*68818Sdab c_kill = ttybuf.c_cc[VKILL];
641247Skas #ifndef TIOCSTI
65*68818Sdab ttybuf.c_cc[VERASE] = 0;
66*68818Sdab ttybuf.c_cc[VKILL] = 0;
6731142Sedward if ((saveint = signal(SIGINT, SIG_IGN)) == SIG_DFL)
6831142Sedward signal(SIGINT, SIG_DFL);
6931142Sedward if ((savequit = signal(SIGQUIT, SIG_IGN)) == SIG_DFL)
7031142Sedward signal(SIGQUIT, SIG_DFL);
7137482Sedward #else
72*68818Sdab # ifdef TIOCEXT
73*68818Sdab extproc = ((ttybuf.c_lflag & EXTPROC) ? 1 : 0);
74*68818Sdab if (extproc) {
75*68818Sdab flag = 0;
76*68818Sdab if (ioctl(fileno(stdin), TIOCEXT, &flag) < 0)
77*68818Sdab perror("TIOCEXT: off");
78*68818Sdab }
79*68818Sdab # endif /* TIOCEXT */
8037482Sedward if (setjmp(intjmp))
8137482Sedward goto out;
8237482Sedward saveint = signal(SIGINT, ttyint);
831247Skas #endif
841247Skas if (gflags & GTO) {
851247Skas #ifndef TIOCSTI
8634800Sedward if (!ttyset && hp->h_to != NIL)
87*68818Sdab ttyset++, tcsetattr(fileno(stdin), &ttybuf);
881247Skas #endif
8934800Sedward hp->h_to =
9034800Sedward extract(readtty("To: ", detract(hp->h_to, 0)), GTO);
911247Skas }
921247Skas if (gflags & GSUBJECT) {
931247Skas #ifndef TIOCSTI
941247Skas if (!ttyset && hp->h_subject != NOSTR)
95*68818Sdab ttyset++, tcsetattr(fileno(stdin), &ttybuf);
961247Skas #endif
971247Skas hp->h_subject = readtty("Subject: ", hp->h_subject);
981247Skas }
991247Skas if (gflags & GCC) {
1001247Skas #ifndef TIOCSTI
10134800Sedward if (!ttyset && hp->h_cc != NIL)
102*68818Sdab ttyset++, tcsetattr(fileno(stdin), &ttybuf);
1031247Skas #endif
10434800Sedward hp->h_cc =
10534800Sedward extract(readtty("Cc: ", detract(hp->h_cc, 0)), GCC);
1061247Skas }
1071247Skas if (gflags & GBCC) {
1081247Skas #ifndef TIOCSTI
10934800Sedward if (!ttyset && hp->h_bcc != NIL)
110*68818Sdab ttyset++, tcsetattr(fileno(stdin), &ttybuf);
1111247Skas #endif
11234800Sedward hp->h_bcc =
11334800Sedward extract(readtty("Bcc: ", detract(hp->h_bcc, 0)), GBCC);
1141247Skas }
11537482Sedward out:
11637482Sedward signal(SIGTSTP, savetstp);
11737482Sedward signal(SIGTTOU, savettou);
11837482Sedward signal(SIGTTIN, savettin);
1191247Skas #ifndef TIOCSTI
120*68818Sdab ttybuf.c_cc[VERASE] = c_erase;
121*68818Sdab ttybuf.c_cc[VKILL] = c_kill;
1221247Skas if (ttyset)
123*68818Sdab tcsetattr(fileno(stdin), &ttybuf);
12431142Sedward signal(SIGQUIT, savequit);
125*68818Sdab #else
126*68818Sdab # ifdef TIOCEXT
127*68818Sdab if (extproc) {
128*68818Sdab flag = 1;
129*68818Sdab if (ioctl(fileno(stdin), TIOCEXT, &flag) < 0)
130*68818Sdab perror("TIOCEXT: on");
131*68818Sdab }
132*68818Sdab # endif /* TIOCEXT */
1331247Skas #endif
13437482Sedward signal(SIGINT, saveint);
1351247Skas return(errs);
1361247Skas }
1371247Skas
1381247Skas /*
1391247Skas * Read up a header from standard input.
1401247Skas * The source string has the preliminary contents to
1411247Skas * be read.
1421247Skas *
1431247Skas */
1441247Skas
1451247Skas char *
readtty(pr,src)1461247Skas readtty(pr, src)
1471247Skas char pr[], src[];
1481247Skas {
14910828Ssam char ch, canonb[BUFSIZ];
15031142Sedward int c;
1511247Skas register char *cp, *cp2;
15247707Sbostic void ttystop();
1531247Skas
1543422Skurt fputs(pr, stdout);
1553422Skurt fflush(stdout);
1561247Skas if (src != NOSTR && strlen(src) > BUFSIZ - 2) {
1571247Skas printf("too long to edit\n");
1581247Skas return(src);
1591247Skas }
1601247Skas #ifndef TIOCSTI
1611247Skas if (src != NOSTR)
1621247Skas cp = copy(src, canonb);
1631247Skas else
1641247Skas cp = copy("", canonb);
1651247Skas fputs(canonb, stdout);
1661247Skas fflush(stdout);
1671247Skas #else
1683422Skurt cp = src == NOSTR ? "" : src;
1693422Skurt while (c = *cp++) {
1701247Skas if (c == c_erase || c == c_kill) {
1711247Skas ch = '\\';
1721247Skas ioctl(0, TIOCSTI, &ch);
1731247Skas }
17410828Ssam ch = c;
17510828Ssam ioctl(0, TIOCSTI, &ch);
1761247Skas }
1771247Skas cp = canonb;
1782845Skas *cp = 0;
1791247Skas #endif
1803422Skurt cp2 = cp;
1813422Skurt while (cp2 < canonb + BUFSIZ)
1823422Skurt *cp2++ = 0;
1833422Skurt cp2 = cp;
1843422Skurt if (setjmp(rewrite))
1853422Skurt goto redo;
18637482Sedward signal(SIGTSTP, ttystop);
18737482Sedward signal(SIGTTOU, ttystop);
18837482Sedward signal(SIGTTIN, ttystop);
18914141Ssam clearerr(stdin);
1903422Skurt while (cp2 < canonb + BUFSIZ) {
1913422Skurt c = getc(stdin);
1923422Skurt if (c == EOF || c == '\n')
1933422Skurt break;
1943422Skurt *cp2++ = c;
1953422Skurt }
1963422Skurt *cp2 = 0;
19737482Sedward signal(SIGTSTP, SIG_DFL);
19837482Sedward signal(SIGTTOU, SIG_DFL);
19937482Sedward signal(SIGTTIN, SIG_DFL);
20037482Sedward if (c == EOF && ferror(stdin)) {
2013422Skurt redo:
2023422Skurt cp = strlen(canonb) > 0 ? canonb : NOSTR;
2033422Skurt clearerr(stdin);
2043422Skurt return(readtty(pr, cp));
2053422Skurt }
2061247Skas #ifndef TIOCSTI
2076223Skurt if (cp == NOSTR || *cp == '\0')
2081247Skas return(src);
2096223Skurt cp2 = cp;
2101247Skas if (!ttyset)
2111247Skas return(strlen(canonb) > 0 ? savestr(canonb) : NOSTR);
2121247Skas while (*cp != '\0') {
2131247Skas c = *cp++;
2141247Skas if (c == c_erase) {
2151247Skas if (cp2 == canonb)
2161247Skas continue;
2171247Skas if (cp2[-1] == '\\') {
2181247Skas cp2[-1] = c;
2191247Skas continue;
2201247Skas }
2211247Skas cp2--;
2221247Skas continue;
2231247Skas }
2241247Skas if (c == c_kill) {
2251247Skas if (cp2 == canonb)
2261247Skas continue;
2271247Skas if (cp2[-1] == '\\') {
2281247Skas cp2[-1] = c;
2291247Skas continue;
2301247Skas }
2311247Skas cp2 = canonb;
2321247Skas continue;
2331247Skas }
2341247Skas *cp2++ = c;
2351247Skas }
2361247Skas *cp2 = '\0';
2371247Skas #endif
2381247Skas if (equal("", canonb))
2391247Skas return(NOSTR);
2401247Skas return(savestr(canonb));
2411247Skas }
2423422Skurt
2433422Skurt /*
2443422Skurt * Receipt continuation.
2453422Skurt */
24647707Sbostic void
ttystop(s)24737482Sedward ttystop(s)
24854505Sbostic int s;
2493422Skurt {
25039612Sedward sig_t old_action = signal(s, SIG_DFL);
25137482Sedward
25237482Sedward sigsetmask(sigblock(0) & ~sigmask(s));
25337482Sedward kill(0, s);
25437482Sedward sigblock(sigmask(s));
25537482Sedward signal(s, old_action);
2563422Skurt longjmp(rewrite, 1);
2573422Skurt }
25837482Sedward
25937482Sedward /*ARGSUSED*/
26047707Sbostic void
ttyint(s)26137482Sedward ttyint(s)
26254505Sbostic int s;
26337482Sedward {
26437482Sedward longjmp(intjmp, 1);
26537482Sedward }
266