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