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