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