1 /* 2 * Copyright (c) 1980 Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms are permitted 6 * provided that the above copyright notice and this paragraph are 7 * duplicated in all such forms and that any documentation, 8 * advertising materials, and other materials related to such 9 * distribution and use acknowledge that the software was developed 10 * by the University of California, Berkeley. The name of the 11 * University may not be used to endorse or promote products derived 12 * from this software without specific prior written permission. 13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 16 */ 17 18 #ifndef lint 19 static char sccsid[] = "@(#)tty.c 5.7 (Berkeley) 06/29/88"; 20 #endif /* not lint */ 21 22 /* 23 * Mail -- a mail program 24 * 25 * Generally useful tty stuff. 26 */ 27 28 #include "rcv.h" 29 30 static int c_erase; /* Current erase char */ 31 static int c_kill; /* Current kill char */ 32 static int hadcont; /* Saw continue signal */ 33 static jmp_buf rewrite; /* Place to go when continued */ 34 #ifndef TIOCSTI 35 static int ttyset; /* We must now do erase/kill */ 36 #endif 37 38 /* 39 * Read all relevant header fields. 40 */ 41 42 grabh(hp, gflags) 43 struct header *hp; 44 { 45 struct sgttyb ttybuf; 46 #ifndef TIOCSTI 47 int (*saveint)(), (*savequit)(); 48 #endif 49 int (*savecont)(); 50 int errs; 51 52 savecont = signal(SIGCONT, SIG_DFL); 53 errs = 0; 54 #ifndef TIOCSTI 55 ttyset = 0; 56 #endif 57 if (gtty(fileno(stdin), &ttybuf) < 0) { 58 perror("gtty"); 59 return(-1); 60 } 61 c_erase = ttybuf.sg_erase; 62 c_kill = ttybuf.sg_kill; 63 #ifndef TIOCSTI 64 ttybuf.sg_erase = 0; 65 ttybuf.sg_kill = 0; 66 if ((saveint = signal(SIGINT, SIG_IGN)) == SIG_DFL) 67 signal(SIGINT, SIG_DFL); 68 if ((savequit = signal(SIGQUIT, SIG_IGN)) == SIG_DFL) 69 signal(SIGQUIT, SIG_DFL); 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 signal(SIGCONT, savecont); 103 #ifndef TIOCSTI 104 ttybuf.sg_erase = c_erase; 105 ttybuf.sg_kill = c_kill; 106 if (ttyset) 107 stty(fileno(stdin), &ttybuf); 108 signal(SIGINT, saveint); 109 signal(SIGQUIT, savequit); 110 #endif 111 return(errs); 112 } 113 114 /* 115 * Read up a header from standard input. 116 * The source string has the preliminary contents to 117 * be read. 118 * 119 */ 120 121 char * 122 readtty(pr, src) 123 char pr[], src[]; 124 { 125 char ch, canonb[BUFSIZ]; 126 int c; 127 register char *cp, *cp2; 128 int ttycont(); 129 130 fputs(pr, stdout); 131 fflush(stdout); 132 if (src != NOSTR && strlen(src) > BUFSIZ - 2) { 133 printf("too long to edit\n"); 134 return(src); 135 } 136 #ifndef TIOCSTI 137 if (src != NOSTR) 138 cp = copy(src, canonb); 139 else 140 cp = copy("", canonb); 141 fputs(canonb, stdout); 142 fflush(stdout); 143 #else 144 cp = src == NOSTR ? "" : src; 145 while (c = *cp++) { 146 if (c == c_erase || c == c_kill) { 147 ch = '\\'; 148 ioctl(0, TIOCSTI, &ch); 149 } 150 ch = c; 151 ioctl(0, TIOCSTI, &ch); 152 } 153 cp = canonb; 154 *cp = 0; 155 #endif 156 cp2 = cp; 157 while (cp2 < canonb + BUFSIZ) 158 *cp2++ = 0; 159 cp2 = cp; 160 if (setjmp(rewrite)) 161 goto redo; 162 signal(SIGCONT, ttycont); 163 clearerr(stdin); 164 while (cp2 < canonb + BUFSIZ) { 165 c = getc(stdin); 166 if (c == EOF || c == '\n') 167 break; 168 *cp2++ = c; 169 } 170 *cp2 = 0; 171 signal(SIGCONT, SIG_DFL); 172 if (c == EOF && ferror(stdin) && hadcont) { 173 redo: 174 hadcont = 0; 175 cp = strlen(canonb) > 0 ? canonb : NOSTR; 176 clearerr(stdin); 177 return(readtty(pr, cp)); 178 } 179 #ifndef TIOCSTI 180 if (cp == NOSTR || *cp == '\0') 181 return(src); 182 cp2 = cp; 183 if (!ttyset) 184 return(strlen(canonb) > 0 ? savestr(canonb) : NOSTR); 185 while (*cp != '\0') { 186 c = *cp++; 187 if (c == c_erase) { 188 if (cp2 == canonb) 189 continue; 190 if (cp2[-1] == '\\') { 191 cp2[-1] = c; 192 continue; 193 } 194 cp2--; 195 continue; 196 } 197 if (c == c_kill) { 198 if (cp2 == canonb) 199 continue; 200 if (cp2[-1] == '\\') { 201 cp2[-1] = c; 202 continue; 203 } 204 cp2 = canonb; 205 continue; 206 } 207 *cp2++ = c; 208 } 209 *cp2 = '\0'; 210 #endif 211 if (equal("", canonb)) 212 return(NOSTR); 213 return(savestr(canonb)); 214 } 215 216 /* 217 * Receipt continuation. 218 */ 219 /*ARGSUSED*/ 220 ttycont(s) 221 { 222 hadcont++; 223 longjmp(rewrite, 1); 224 } 225