1 /* 2 * Copyright (c) 1980 Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #ifndef lint 9 static char sccsid[] = "@(#)tty.c 5.12 (Berkeley) 04/01/91"; 10 #endif /* not lint */ 11 12 /* 13 * Mail -- a mail program 14 * 15 * Generally useful tty stuff. 16 */ 17 18 #include "rcv.h" 19 20 static int c_erase; /* Current erase char */ 21 static int c_kill; /* Current kill char */ 22 static jmp_buf rewrite; /* Place to go when continued */ 23 static jmp_buf intjmp; /* Place to go when interrupted */ 24 #ifndef TIOCSTI 25 static int ttyset; /* We must now do erase/kill */ 26 #endif 27 28 /* 29 * Read all relevant header fields. 30 */ 31 32 grabh(hp, gflags) 33 struct header *hp; 34 { 35 struct sgttyb ttybuf; 36 sig_t saveint; 37 #ifndef TIOCSTI 38 sig_t savequit; 39 #endif 40 sig_t savetstp; 41 sig_t savettou; 42 sig_t savettin; 43 int errs; 44 void ttyint(); 45 46 savetstp = signal(SIGTSTP, SIG_DFL); 47 savettou = signal(SIGTTOU, SIG_DFL); 48 savettin = signal(SIGTTIN, SIG_DFL); 49 errs = 0; 50 #ifndef TIOCSTI 51 ttyset = 0; 52 #endif 53 if (ioctl(fileno(stdin), TIOCGETP, &ttybuf) < 0) { 54 perror("gtty"); 55 return(-1); 56 } 57 c_erase = ttybuf.sg_erase; 58 c_kill = ttybuf.sg_kill; 59 #ifndef TIOCSTI 60 ttybuf.sg_erase = 0; 61 ttybuf.sg_kill = 0; 62 if ((saveint = signal(SIGINT, SIG_IGN)) == SIG_DFL) 63 signal(SIGINT, SIG_DFL); 64 if ((savequit = signal(SIGQUIT, SIG_IGN)) == SIG_DFL) 65 signal(SIGQUIT, SIG_DFL); 66 #else 67 if (setjmp(intjmp)) 68 goto out; 69 saveint = signal(SIGINT, ttyint); 70 #endif 71 if (gflags & GTO) { 72 #ifndef TIOCSTI 73 if (!ttyset && hp->h_to != NIL) 74 ttyset++, stty(fileno(stdin), &ttybuf); 75 #endif 76 hp->h_to = 77 extract(readtty("To: ", detract(hp->h_to, 0)), GTO); 78 } 79 if (gflags & GSUBJECT) { 80 #ifndef TIOCSTI 81 if (!ttyset && hp->h_subject != NOSTR) 82 ttyset++, stty(fileno(stdin), &ttybuf); 83 #endif 84 hp->h_subject = readtty("Subject: ", hp->h_subject); 85 } 86 if (gflags & GCC) { 87 #ifndef TIOCSTI 88 if (!ttyset && hp->h_cc != NIL) 89 ttyset++, stty(fileno(stdin), &ttybuf); 90 #endif 91 hp->h_cc = 92 extract(readtty("Cc: ", detract(hp->h_cc, 0)), GCC); 93 } 94 if (gflags & GBCC) { 95 #ifndef TIOCSTI 96 if (!ttyset && hp->h_bcc != NIL) 97 ttyset++, stty(fileno(stdin), &ttybuf); 98 #endif 99 hp->h_bcc = 100 extract(readtty("Bcc: ", detract(hp->h_bcc, 0)), GBCC); 101 } 102 out: 103 signal(SIGTSTP, savetstp); 104 signal(SIGTTOU, savettou); 105 signal(SIGTTIN, savettin); 106 #ifndef TIOCSTI 107 ttybuf.sg_erase = c_erase; 108 ttybuf.sg_kill = c_kill; 109 if (ttyset) 110 stty(fileno(stdin), &ttybuf); 111 signal(SIGQUIT, savequit); 112 #endif 113 signal(SIGINT, saveint); 114 return(errs); 115 } 116 117 /* 118 * Read up a header from standard input. 119 * The source string has the preliminary contents to 120 * be read. 121 * 122 */ 123 124 char * 125 readtty(pr, src) 126 char pr[], src[]; 127 { 128 char ch, canonb[BUFSIZ]; 129 int c; 130 register char *cp, *cp2; 131 void ttystop(); 132 133 fputs(pr, stdout); 134 fflush(stdout); 135 if (src != NOSTR && strlen(src) > BUFSIZ - 2) { 136 printf("too long to edit\n"); 137 return(src); 138 } 139 #ifndef TIOCSTI 140 if (src != NOSTR) 141 cp = copy(src, canonb); 142 else 143 cp = copy("", canonb); 144 fputs(canonb, stdout); 145 fflush(stdout); 146 #else 147 cp = src == NOSTR ? "" : src; 148 while (c = *cp++) { 149 if (c == c_erase || c == c_kill) { 150 ch = '\\'; 151 ioctl(0, TIOCSTI, &ch); 152 } 153 ch = c; 154 ioctl(0, TIOCSTI, &ch); 155 } 156 cp = canonb; 157 *cp = 0; 158 #endif 159 cp2 = cp; 160 while (cp2 < canonb + BUFSIZ) 161 *cp2++ = 0; 162 cp2 = cp; 163 if (setjmp(rewrite)) 164 goto redo; 165 signal(SIGTSTP, ttystop); 166 signal(SIGTTOU, ttystop); 167 signal(SIGTTIN, ttystop); 168 clearerr(stdin); 169 while (cp2 < canonb + BUFSIZ) { 170 c = getc(stdin); 171 if (c == EOF || c == '\n') 172 break; 173 *cp2++ = c; 174 } 175 *cp2 = 0; 176 signal(SIGTSTP, SIG_DFL); 177 signal(SIGTTOU, SIG_DFL); 178 signal(SIGTTIN, SIG_DFL); 179 if (c == EOF && ferror(stdin)) { 180 redo: 181 cp = strlen(canonb) > 0 ? canonb : NOSTR; 182 clearerr(stdin); 183 return(readtty(pr, cp)); 184 } 185 #ifndef TIOCSTI 186 if (cp == NOSTR || *cp == '\0') 187 return(src); 188 cp2 = cp; 189 if (!ttyset) 190 return(strlen(canonb) > 0 ? savestr(canonb) : NOSTR); 191 while (*cp != '\0') { 192 c = *cp++; 193 if (c == c_erase) { 194 if (cp2 == canonb) 195 continue; 196 if (cp2[-1] == '\\') { 197 cp2[-1] = c; 198 continue; 199 } 200 cp2--; 201 continue; 202 } 203 if (c == c_kill) { 204 if (cp2 == canonb) 205 continue; 206 if (cp2[-1] == '\\') { 207 cp2[-1] = c; 208 continue; 209 } 210 cp2 = canonb; 211 continue; 212 } 213 *cp2++ = c; 214 } 215 *cp2 = '\0'; 216 #endif 217 if (equal("", canonb)) 218 return(NOSTR); 219 return(savestr(canonb)); 220 } 221 222 /* 223 * Receipt continuation. 224 */ 225 void 226 ttystop(s) 227 { 228 sig_t old_action = signal(s, SIG_DFL); 229 230 sigsetmask(sigblock(0) & ~sigmask(s)); 231 kill(0, s); 232 sigblock(sigmask(s)); 233 signal(s, old_action); 234 longjmp(rewrite, 1); 235 } 236 237 /*ARGSUSED*/ 238 void 239 ttyint(s) 240 { 241 longjmp(intjmp, 1); 242 } 243