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.2 (Berkeley) 04/20/95"; 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 termios ttybuf; 39 sig_t saveint; 40 #ifndef TIOCSTI 41 sig_t savequit; 42 #else 43 int extproc, flag; 44 #endif 45 sig_t savetstp; 46 sig_t savettou; 47 sig_t savettin; 48 int errs; 49 void ttyint(); 50 51 savetstp = signal(SIGTSTP, SIG_DFL); 52 savettou = signal(SIGTTOU, SIG_DFL); 53 savettin = signal(SIGTTIN, SIG_DFL); 54 errs = 0; 55 #ifndef TIOCSTI 56 ttyset = 0; 57 #endif 58 if (ioctl(fileno(stdin), TIOCGETA, &ttybuf) < 0) { 59 perror("TIOCGETA"); 60 return(-1); 61 } 62 c_erase = ttybuf.c_cc[VERASE]; 63 c_kill = ttybuf.c_cc[VKILL]; 64 #ifndef TIOCSTI 65 ttybuf.c_cc[VERASE] = 0; 66 ttybuf.c_cc[VKILL] = 0; 67 if ((saveint = signal(SIGINT, SIG_IGN)) == SIG_DFL) 68 signal(SIGINT, SIG_DFL); 69 if ((savequit = signal(SIGQUIT, SIG_IGN)) == SIG_DFL) 70 signal(SIGQUIT, SIG_DFL); 71 #else 72 # ifdef TIOCEXT 73 extproc = ((ttybuf.c_lflag & EXTPROC) ? 1 : 0); 74 if (extproc) { 75 flag = 0; 76 if (ioctl(fileno(stdin), TIOCEXT, &flag) < 0) 77 perror("TIOCEXT: off"); 78 } 79 # endif /* TIOCEXT */ 80 if (setjmp(intjmp)) 81 goto out; 82 saveint = signal(SIGINT, ttyint); 83 #endif 84 if (gflags & GTO) { 85 #ifndef TIOCSTI 86 if (!ttyset && hp->h_to != NIL) 87 ttyset++, tcsetattr(fileno(stdin), &ttybuf); 88 #endif 89 hp->h_to = 90 extract(readtty("To: ", detract(hp->h_to, 0)), GTO); 91 } 92 if (gflags & GSUBJECT) { 93 #ifndef TIOCSTI 94 if (!ttyset && hp->h_subject != NOSTR) 95 ttyset++, tcsetattr(fileno(stdin), &ttybuf); 96 #endif 97 hp->h_subject = readtty("Subject: ", hp->h_subject); 98 } 99 if (gflags & GCC) { 100 #ifndef TIOCSTI 101 if (!ttyset && hp->h_cc != NIL) 102 ttyset++, tcsetattr(fileno(stdin), &ttybuf); 103 #endif 104 hp->h_cc = 105 extract(readtty("Cc: ", detract(hp->h_cc, 0)), GCC); 106 } 107 if (gflags & GBCC) { 108 #ifndef TIOCSTI 109 if (!ttyset && hp->h_bcc != NIL) 110 ttyset++, tcsetattr(fileno(stdin), &ttybuf); 111 #endif 112 hp->h_bcc = 113 extract(readtty("Bcc: ", detract(hp->h_bcc, 0)), GBCC); 114 } 115 out: 116 signal(SIGTSTP, savetstp); 117 signal(SIGTTOU, savettou); 118 signal(SIGTTIN, savettin); 119 #ifndef TIOCSTI 120 ttybuf.c_cc[VERASE] = c_erase; 121 ttybuf.c_cc[VKILL] = c_kill; 122 if (ttyset) 123 tcsetattr(fileno(stdin), &ttybuf); 124 signal(SIGQUIT, savequit); 125 #else 126 # ifdef TIOCEXT 127 if (extproc) { 128 flag = 1; 129 if (ioctl(fileno(stdin), TIOCEXT, &flag) < 0) 130 perror("TIOCEXT: on"); 131 } 132 # endif /* TIOCEXT */ 133 #endif 134 signal(SIGINT, saveint); 135 return(errs); 136 } 137 138 /* 139 * Read up a header from standard input. 140 * The source string has the preliminary contents to 141 * be read. 142 * 143 */ 144 145 char * 146 readtty(pr, src) 147 char pr[], src[]; 148 { 149 char ch, canonb[BUFSIZ]; 150 int c; 151 register char *cp, *cp2; 152 void ttystop(); 153 154 fputs(pr, stdout); 155 fflush(stdout); 156 if (src != NOSTR && strlen(src) > BUFSIZ - 2) { 157 printf("too long to edit\n"); 158 return(src); 159 } 160 #ifndef TIOCSTI 161 if (src != NOSTR) 162 cp = copy(src, canonb); 163 else 164 cp = copy("", canonb); 165 fputs(canonb, stdout); 166 fflush(stdout); 167 #else 168 cp = src == NOSTR ? "" : src; 169 while (c = *cp++) { 170 if (c == c_erase || c == c_kill) { 171 ch = '\\'; 172 ioctl(0, TIOCSTI, &ch); 173 } 174 ch = c; 175 ioctl(0, TIOCSTI, &ch); 176 } 177 cp = canonb; 178 *cp = 0; 179 #endif 180 cp2 = cp; 181 while (cp2 < canonb + BUFSIZ) 182 *cp2++ = 0; 183 cp2 = cp; 184 if (setjmp(rewrite)) 185 goto redo; 186 signal(SIGTSTP, ttystop); 187 signal(SIGTTOU, ttystop); 188 signal(SIGTTIN, ttystop); 189 clearerr(stdin); 190 while (cp2 < canonb + BUFSIZ) { 191 c = getc(stdin); 192 if (c == EOF || c == '\n') 193 break; 194 *cp2++ = c; 195 } 196 *cp2 = 0; 197 signal(SIGTSTP, SIG_DFL); 198 signal(SIGTTOU, SIG_DFL); 199 signal(SIGTTIN, SIG_DFL); 200 if (c == EOF && ferror(stdin)) { 201 redo: 202 cp = strlen(canonb) > 0 ? canonb : NOSTR; 203 clearerr(stdin); 204 return(readtty(pr, cp)); 205 } 206 #ifndef TIOCSTI 207 if (cp == NOSTR || *cp == '\0') 208 return(src); 209 cp2 = cp; 210 if (!ttyset) 211 return(strlen(canonb) > 0 ? savestr(canonb) : NOSTR); 212 while (*cp != '\0') { 213 c = *cp++; 214 if (c == c_erase) { 215 if (cp2 == canonb) 216 continue; 217 if (cp2[-1] == '\\') { 218 cp2[-1] = c; 219 continue; 220 } 221 cp2--; 222 continue; 223 } 224 if (c == c_kill) { 225 if (cp2 == canonb) 226 continue; 227 if (cp2[-1] == '\\') { 228 cp2[-1] = c; 229 continue; 230 } 231 cp2 = canonb; 232 continue; 233 } 234 *cp2++ = c; 235 } 236 *cp2 = '\0'; 237 #endif 238 if (equal("", canonb)) 239 return(NOSTR); 240 return(savestr(canonb)); 241 } 242 243 /* 244 * Receipt continuation. 245 */ 246 void 247 ttystop(s) 248 int s; 249 { 250 sig_t old_action = signal(s, SIG_DFL); 251 252 sigsetmask(sigblock(0) & ~sigmask(s)); 253 kill(0, s); 254 sigblock(sigmask(s)); 255 signal(s, old_action); 256 longjmp(rewrite, 1); 257 } 258 259 /*ARGSUSED*/ 260 void 261 ttyint(s) 262 int s; 263 { 264 longjmp(intjmp, 1); 265 } 266