1 # 2 #include "rcv.h" 3 #include <sys/stat.h> 4 5 /* 6 * Mail -- a mail program 7 * 8 * User commands. 9 */ 10 11 static char *SccsId = "@(#)cmd1.c 2.9 10/21/82"; 12 13 /* 14 * Print the current active headings. 15 * Don't change dot if invoker didn't give an argument. 16 */ 17 18 static int screen; 19 20 headers(msgvec) 21 int *msgvec; 22 { 23 register int n, mesg, flag; 24 register struct message *mp; 25 int size; 26 27 size = screensize(); 28 n = msgvec[0]; 29 if (n != 0) 30 screen = (n-1)/size; 31 if (screen < 0) 32 screen = 0; 33 mp = &message[screen * size]; 34 if (mp >= &message[msgCount]) 35 mp = &message[msgCount - size]; 36 if (mp < &message[0]) 37 mp = &message[0]; 38 flag = 0; 39 mesg = mp - &message[0]; 40 if (dot != &message[n-1]) 41 dot = mp; 42 for (; mp < &message[msgCount]; mp++) { 43 mesg++; 44 if (mp->m_flag & MDELETED) 45 continue; 46 if (flag++ >= size) 47 break; 48 printhead(mesg); 49 sreset(); 50 } 51 if (flag == 0) { 52 printf("No more mail.\n"); 53 return(1); 54 } 55 return(0); 56 } 57 58 /* 59 * Scroll to the next/previous screen 60 */ 61 62 scroll(arg) 63 char arg[]; 64 { 65 register int s, size; 66 int cur[1]; 67 68 cur[0] = 0; 69 size = screensize(); 70 s = screen; 71 switch (*arg) { 72 case 0: 73 case '+': 74 s++; 75 if (s * size > msgCount) { 76 printf("On last screenful of messages\n"); 77 return(0); 78 } 79 screen = s; 80 break; 81 82 case '-': 83 if (--s < 0) { 84 printf("On first screenful of messages\n"); 85 return(0); 86 } 87 screen = s; 88 break; 89 90 default: 91 printf("Unrecognized scrolling command \"%s\"\n", arg); 92 return(1); 93 } 94 return(headers(cur)); 95 } 96 97 /* 98 * Compute what the screen size should be. 99 * We use the following algorithm: 100 * If user specifies with screen option, use that. 101 * If baud rate < 1200, use 5 102 * If baud rate = 1200, use 10 103 * If baud rate > 1200, use 20 104 */ 105 screensize() 106 { 107 register char *cp; 108 register int s; 109 110 if ((cp = value("screen")) != NOSTR) { 111 s = atoi(cp); 112 if (s > 0) 113 return(s); 114 } 115 if (baud < B1200) 116 s = 5; 117 else if (baud == B1200) 118 s = 10; 119 else 120 s = 20; 121 return(s); 122 } 123 124 /* 125 * Print out the headlines for each message 126 * in the passed message list. 127 */ 128 129 from(msgvec) 130 int *msgvec; 131 { 132 register int *ip; 133 134 for (ip = msgvec; *ip != NULL; ip++) { 135 printhead(*ip); 136 sreset(); 137 } 138 if (--ip >= msgvec) 139 dot = &message[*ip - 1]; 140 return(0); 141 } 142 143 /* 144 * Print out the header of a specific message. 145 * This is a slight improvement to the standard one. 146 */ 147 148 printhead(mesg) 149 { 150 struct message *mp; 151 FILE *ibuf; 152 char headline[LINESIZE], wcount[10], *subjline, dispc, curind; 153 char pbuf[BUFSIZ]; 154 int s; 155 struct headline hl; 156 register char *cp; 157 158 mp = &message[mesg-1]; 159 ibuf = setinput(mp); 160 readline(ibuf, headline); 161 subjline = hfield("subject", mp); 162 if (subjline == NOSTR) 163 subjline = hfield("subj", mp); 164 165 /* 166 * Bletch! 167 */ 168 169 if (subjline != NOSTR && strlen(subjline) > 28) 170 subjline[29] = '\0'; 171 curind = dot == mp ? '>' : ' '; 172 dispc = ' '; 173 if (mp->m_flag & MSAVED) 174 dispc = '*'; 175 if (mp->m_flag & MPRESERVE) 176 dispc = 'P'; 177 if ((mp->m_flag & (MREAD|MNEW)) == MNEW) 178 dispc = 'N'; 179 if ((mp->m_flag & (MREAD|MNEW)) == 0) 180 dispc = 'U'; 181 if (mp->m_flag & MBOX) 182 dispc = 'M'; 183 parse(headline, &hl, pbuf); 184 sprintf(wcount, " %d/%ld", mp->m_lines, mp->m_size); 185 s = strlen(wcount); 186 cp = wcount + s; 187 while (s < 7) 188 s++, *cp++ = ' '; 189 *cp = '\0'; 190 if (subjline != NOSTR) 191 printf("%c%c%3d %-8s %16.16s %s \"%s\"\n", curind, dispc, mesg, 192 nameof(mp, 0), hl.l_date, wcount, subjline); 193 else 194 printf("%c%c%3d %-8s %16.16s %s\n", curind, dispc, mesg, 195 nameof(mp, 0), hl.l_date, wcount); 196 } 197 198 /* 199 * Print out the value of dot. 200 */ 201 202 pdot() 203 { 204 printf("%d\n", dot - &message[0] + 1); 205 return(0); 206 } 207 208 /* 209 * Print out all the possible commands. 210 */ 211 212 pcmdlist() 213 { 214 register struct cmd *cp; 215 register int cc; 216 extern struct cmd cmdtab[]; 217 218 printf("Commands are:\n"); 219 for (cc = 0, cp = cmdtab; cp->c_name != NULL; cp++) { 220 cc += strlen(cp->c_name) + 2; 221 if (cc > 72) { 222 printf("\n"); 223 cc = strlen(cp->c_name) + 2; 224 } 225 if ((cp+1)->c_name != NOSTR) 226 printf("%s, ", cp->c_name); 227 else 228 printf("%s\n", cp->c_name); 229 } 230 return(0); 231 } 232 233 /* 234 * Type out messages, honor ignored fields. 235 */ 236 type(msgvec) 237 int *msgvec; 238 { 239 240 return(type1(msgvec, 1)); 241 } 242 243 /* 244 * Type out messages, even printing ignored fields. 245 */ 246 Type(msgvec) 247 int *msgvec; 248 { 249 250 return(type1(msgvec, 0)); 251 } 252 253 /* 254 * Type out the messages requested. 255 */ 256 jmp_buf pipestop; 257 258 type1(msgvec, doign) 259 int *msgvec; 260 { 261 register *ip; 262 register struct message *mp; 263 register int mesg; 264 register char *cp; 265 int c, nlines; 266 int brokpipe(); 267 FILE *ibuf, *obuf; 268 269 obuf = stdout; 270 if (setjmp(pipestop)) { 271 if (obuf != stdout) { 272 pipef = NULL; 273 pclose(obuf); 274 } 275 sigset(SIGPIPE, SIG_DFL); 276 return(0); 277 } 278 if (intty && outtty && (cp = value("crt")) != NOSTR) { 279 for (ip = msgvec, nlines = 0; *ip && ip-msgvec < msgCount; ip++) 280 nlines += message[*ip - 1].m_lines; 281 if (nlines > atoi(cp)) { 282 obuf = popen(MORE, "w"); 283 if (obuf == NULL) { 284 perror(MORE); 285 obuf = stdout; 286 } 287 else { 288 pipef = obuf; 289 sigset(SIGPIPE, brokpipe); 290 } 291 } 292 } 293 for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) { 294 mesg = *ip; 295 touch(mesg); 296 mp = &message[mesg-1]; 297 dot = mp; 298 print(mp, obuf, doign); 299 } 300 if (obuf != stdout) { 301 pipef = NULL; 302 pclose(obuf); 303 } 304 sigset(SIGPIPE, SIG_DFL); 305 return(0); 306 } 307 308 /* 309 * Respond to a broken pipe signal -- 310 * probably caused by using quitting more. 311 */ 312 313 brokpipe() 314 { 315 # ifdef VMUNIX 316 sigrelse(SIGPIPE); 317 # else 318 signal(SIGPIPE, brokpipe); 319 # endif 320 longjmp(pipestop, 1); 321 } 322 323 /* 324 * Print the indicated message on standard output. 325 */ 326 327 print(mp, obuf, doign) 328 register struct message *mp; 329 FILE *obuf; 330 { 331 332 if (value("quiet") == NOSTR) 333 fprintf(obuf, "Message %2d:\n", mp - &message[0] + 1); 334 touch(mp - &message[0] + 1); 335 send(mp, obuf, doign); 336 } 337 338 /* 339 * Print the top so many lines of each desired message. 340 * The number of lines is taken from the variable "toplines" 341 * and defaults to 5. 342 */ 343 344 top(msgvec) 345 int *msgvec; 346 { 347 register int *ip; 348 register struct message *mp; 349 register int mesg; 350 int c, topl, lines, lineb; 351 char *valtop, linebuf[LINESIZE]; 352 FILE *ibuf; 353 354 topl = 5; 355 valtop = value("toplines"); 356 if (valtop != NOSTR) { 357 topl = atoi(valtop); 358 if (topl < 0 || topl > 10000) 359 topl = 5; 360 } 361 lineb = 1; 362 for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) { 363 mesg = *ip; 364 touch(mesg); 365 mp = &message[mesg-1]; 366 dot = mp; 367 if (value("quiet") == NOSTR) 368 printf("Message %2d:\n", mesg); 369 ibuf = setinput(mp); 370 c = mp->m_lines; 371 if (!lineb) 372 printf("\n"); 373 for (lines = 0; lines < c && lines <= topl; lines++) { 374 if (readline(ibuf, linebuf) <= 0) 375 break; 376 puts(linebuf); 377 lineb = blankline(linebuf); 378 } 379 } 380 return(0); 381 } 382 383 /* 384 * Touch all the given messages so that they will 385 * get mboxed. 386 */ 387 388 stouch(msgvec) 389 int msgvec[]; 390 { 391 register int *ip; 392 393 for (ip = msgvec; *ip != 0; ip++) { 394 dot = &message[*ip-1]; 395 dot->m_flag |= MTOUCH; 396 dot->m_flag &= ~MPRESERVE; 397 } 398 return(0); 399 } 400 401 /* 402 * Make sure all passed messages get mboxed. 403 */ 404 405 mboxit(msgvec) 406 int msgvec[]; 407 { 408 register int *ip; 409 410 for (ip = msgvec; *ip != 0; ip++) { 411 dot = &message[*ip-1]; 412 dot->m_flag |= MTOUCH|MBOX; 413 dot->m_flag &= ~MPRESERVE; 414 } 415 return(0); 416 } 417 418 /* 419 * List the folders the user currently has. 420 */ 421 folders() 422 { 423 char dirname[BUFSIZ], cmd[BUFSIZ]; 424 int pid, s, e; 425 426 if (getfold(dirname) < 0) { 427 printf("No value set for \"folder\"\n"); 428 return(-1); 429 } 430 switch ((pid = fork())) { 431 case 0: 432 sigchild(); 433 execlp("ls", "ls", dirname, 0); 434 clrbuf(stdout); 435 exit(1); 436 437 case -1: 438 perror("fork"); 439 return(-1); 440 441 default: 442 while ((e = wait(&s)) != -1 && e != pid) 443 ; 444 } 445 return(0); 446 } 447