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