1: /*
   2:  * Copyright (c) 1980 Regents of the University of California.
   3:  * All rights reserved.  The Berkeley software License Agreement
   4:  * specifies the terms and conditions for redistribution.
   5:  */
   6: 
   7: #ifndef lint
   8: static char *sccsid = "@(#)cmd2.c	5.3 (Berkeley) 9/10/85";
   9: #endif not lint
  10: 
  11: #include "rcv.h"
  12: #include <sys/stat.h>
  13: 
  14: /*
  15:  * Mail -- a mail program
  16:  *
  17:  * More user commands.
  18:  */
  19: 
  20: /*
  21:  * If any arguments were given, go to the next applicable argument
  22:  * following dot, otherwise, go to the next applicable message.
  23:  * If given as first command with no arguments, print first message.
  24:  */
  25: 
  26: next(msgvec)
  27:     int *msgvec;
  28: {
  29:     register struct message *mp;
  30:     register int *ip, *ip2;
  31:     int list[2], mdot;
  32: 
  33:     if (*msgvec != NULL) {
  34: 
  35:         /*
  36: 		 * If some messages were supplied, find the
  37: 		 * first applicable one following dot using
  38: 		 * wrap around.
  39: 		 */
  40: 
  41:         mdot = dot - &message[0] + 1;
  42: 
  43:         /*
  44: 		 * Find the first message in the supplied
  45: 		 * message list which follows dot.
  46: 		 */
  47: 
  48:         for (ip = msgvec; *ip != NULL; ip++)
  49:             if (*ip > mdot)
  50:                 break;
  51:         if (*ip == NULL)
  52:             ip = msgvec;
  53:         ip2 = ip;
  54:         do {
  55:             mp = &message[*ip2 - 1];
  56:             if ((mp->m_flag & MDELETED) == 0) {
  57:                 dot = mp;
  58:                 goto hitit;
  59:             }
  60:             if (*ip2 != NULL)
  61:                 ip2++;
  62:             if (*ip2 == NULL)
  63:                 ip2 = msgvec;
  64:         } while (ip2 != ip);
  65:         printf("No messages applicable\n");
  66:         return(1);
  67:     }
  68: 
  69:     /*
  70: 	 * If this is the first command, select message 1.
  71: 	 * Note that this must exist for us to get here at all.
  72: 	 */
  73: 
  74:     if (!sawcom)
  75:         goto hitit;
  76: 
  77:     /*
  78: 	 * Just find the next good message after dot, no
  79: 	 * wraparound.
  80: 	 */
  81: 
  82:     for (mp = dot+1; mp < &message[msgCount]; mp++)
  83:         if ((mp->m_flag & (MDELETED|MSAVED)) == 0)
  84:             break;
  85:     if (mp >= &message[msgCount]) {
  86:         printf("At EOF\n");
  87:         return(0);
  88:     }
  89:     dot = mp;
  90: hitit:
  91:     /*
  92: 	 * Print dot.
  93: 	 */
  94: 
  95:     list[0] = dot - &message[0] + 1;
  96:     list[1] = NULL;
  97:     return(type(list));
  98: }
  99: 
 100: /*
 101:  * Save a message in a file.  Mark the message as saved
 102:  * so we can discard when the user quits.
 103:  */
 104: save(str)
 105:     char str[];
 106: {
 107: 
 108:     return(save1(str, 1));
 109: }
 110: 
 111: /*
 112:  * Copy a message to a file without affected its saved-ness
 113:  */
 114: copycmd(str)
 115:     char str[];
 116: {
 117: 
 118:     return(save1(str, 0));
 119: }
 120: 
 121: /*
 122:  * Save/copy the indicated messages at the end of the passed file name.
 123:  * If mark is true, mark the message "saved."
 124:  */
 125: save1(str, mark)
 126:     char str[];
 127: {
 128:     register int *ip, mesg;
 129:     register struct message *mp;
 130:     char *file, *disp, *cmd;
 131:     int f, *msgvec, lc, t;
 132:     long cc;
 133:     FILE *obuf;
 134:     struct stat statb;
 135: 
 136:     cmd = mark ? "save" : "copy";
 137:     msgvec = (int *) salloc((msgCount + 2) * sizeof *msgvec);
 138:     if ((file = snarf(str, &f)) == NOSTR)
 139:         return(1);
 140:     if (!f) {
 141:         *msgvec = first(0, MMNORM);
 142:         if (*msgvec == NULL) {
 143:             printf("No messages to %s.\n", cmd);
 144:             return(1);
 145:         }
 146:         msgvec[1] = NULL;
 147:     }
 148:     if (f && getmsglist(str, msgvec, 0) < 0)
 149:         return(1);
 150:     if ((file = expand(file)) == NOSTR)
 151:         return(1);
 152:     printf("\"%s\" ", file);
 153:     fflush(stdout);
 154:     if (stat(file, &statb) >= 0)
 155:         disp = "[Appended]";
 156:     else
 157:         disp = "[New file]";
 158:     if ((obuf = fopen(file, "a")) == NULL) {
 159:         perror(NOSTR);
 160:         return(1);
 161:     }
 162:     cc = 0L;
 163:     lc = 0;
 164:     for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) {
 165:         mesg = *ip;
 166:         touch(mesg);
 167:         mp = &message[mesg-1];
 168:         if ((t = send(mp, obuf, 0)) < 0) {
 169:             perror(file);
 170:             fclose(obuf);
 171:             return(1);
 172:         }
 173:         lc += t;
 174:         cc += mp->m_size;
 175:         if (mark)
 176:             mp->m_flag |= MSAVED;
 177:     }
 178:     fflush(obuf);
 179:     if (ferror(obuf))
 180:         perror(file);
 181:     fclose(obuf);
 182:     printf("%s %d/%ld\n", disp, lc, cc);
 183:     return(0);
 184: }
 185: 
 186: /*
 187:  * Write the indicated messages at the end of the passed
 188:  * file name, minus header and trailing blank line.
 189:  */
 190: 
 191: swrite(str)
 192:     char str[];
 193: {
 194:     register int *ip, mesg;
 195:     register struct message *mp;
 196:     register char *file, *disp;
 197:     char linebuf[BUFSIZ];
 198:     int f, *msgvec, lc, cc, t;
 199:     FILE *obuf, *mesf;
 200:     struct stat statb;
 201: 
 202:     msgvec = (int *) salloc((msgCount + 2) * sizeof *msgvec);
 203:     if ((file = snarf(str, &f)) == NOSTR)
 204:         return(1);
 205:     if ((file = expand(file)) == NOSTR)
 206:         return(1);
 207:     if (!f) {
 208:         *msgvec = first(0, MMNORM);
 209:         if (*msgvec == NULL) {
 210:             printf("No messages to write.\n");
 211:             return(1);
 212:         }
 213:         msgvec[1] = NULL;
 214:     }
 215:     if (f && getmsglist(str, msgvec, 0) < 0)
 216:         return(1);
 217:     printf("\"%s\" ", file);
 218:     fflush(stdout);
 219:     if (stat(file, &statb) >= 0)
 220:         disp = "[Appended]";
 221:     else
 222:         disp = "[New file]";
 223:     if ((obuf = fopen(file, "a")) == NULL) {
 224:         perror(NOSTR);
 225:         return(1);
 226:     }
 227:     cc = lc = 0;
 228:     for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) {
 229:         mesg = *ip;
 230:         touch(mesg);
 231:         mp = &message[mesg-1];
 232:         mesf = setinput(mp);
 233:         t = mp->m_lines - 1;
 234:         while (t-- > 0) {
 235:             readline(mesf, linebuf);
 236:             if (blankline(linebuf))
 237:                 break;
 238:         }
 239:         while (t-- > 0) {
 240:             fgets(linebuf, BUFSIZ, mesf);
 241:             fputs(linebuf, obuf);
 242:             cc += strlen(linebuf);
 243:         }
 244:         lc += mp->m_lines - 2;
 245:         mp->m_flag |= MSAVED;
 246:     }
 247:     fflush(obuf);
 248:     if (ferror(obuf))
 249:         perror(file);
 250:     fclose(obuf);
 251:     printf("%s %d/%d\n", disp, lc, cc);
 252:     return(0);
 253: }
 254: 
 255: /*
 256:  * Snarf the file from the end of the command line and
 257:  * return a pointer to it.  If there is no file attached,
 258:  * just return NOSTR.  Put a null in front of the file
 259:  * name so that the message list processing won't see it,
 260:  * unless the file name is the only thing on the line, in
 261:  * which case, return 0 in the reference flag variable.
 262:  */
 263: 
 264: char *
 265: snarf(linebuf, flag)
 266:     char linebuf[];
 267:     int *flag;
 268: {
 269:     register char *cp;
 270: 
 271:     *flag = 1;
 272:     cp = strlen(linebuf) + linebuf - 1;
 273: 
 274:     /*
 275: 	 * Strip away trailing blanks.
 276: 	 */
 277: 
 278:     while (*cp == ' ' && cp > linebuf)
 279:         cp--;
 280:     *++cp = 0;
 281: 
 282:     /*
 283: 	 * Now search for the beginning of the file name.
 284: 	 */
 285: 
 286:     while (cp > linebuf && !any(*cp, "\t "))
 287:         cp--;
 288:     if (*cp == '\0') {
 289:         printf("No file specified.\n");
 290:         return(NOSTR);
 291:     }
 292:     if (any(*cp, " \t"))
 293:         *cp++ = 0;
 294:     else
 295:         *flag = 0;
 296:     return(cp);
 297: }
 298: 
 299: /*
 300:  * Delete messages.
 301:  */
 302: 
 303: delete(msgvec)
 304:     int msgvec[];
 305: {
 306:     return(delm(msgvec));
 307: }
 308: 
 309: /*
 310:  * Delete messages, then type the new dot.
 311:  */
 312: 
 313: deltype(msgvec)
 314:     int msgvec[];
 315: {
 316:     int list[2];
 317:     int lastdot;
 318: 
 319:     lastdot = dot - &message[0] + 1;
 320:     if (delm(msgvec) >= 0) {
 321:         list[0] = dot - &message[0];
 322:         list[0]++;
 323:         if (list[0] > lastdot) {
 324:             touch(list[0]);
 325:             list[1] = NULL;
 326:             return(type(list));
 327:         }
 328:         printf("At EOF\n");
 329:         return(0);
 330:     }
 331:     else {
 332:         printf("No more messages\n");
 333:         return(0);
 334:     }
 335: }
 336: 
 337: /*
 338:  * Delete the indicated messages.
 339:  * Set dot to some nice place afterwards.
 340:  * Internal interface.
 341:  */
 342: 
 343: delm(msgvec)
 344:     int *msgvec;
 345: {
 346:     register struct message *mp;
 347:     register *ip, mesg;
 348:     int last;
 349: 
 350:     last = NULL;
 351:     for (ip = msgvec; *ip != NULL; ip++) {
 352:         mesg = *ip;
 353:         touch(mesg);
 354:         mp = &message[mesg-1];
 355:         mp->m_flag |= MDELETED|MTOUCH;
 356:         mp->m_flag &= ~(MPRESERVE|MSAVED|MBOX);
 357:         last = mesg;
 358:     }
 359:     if (last != NULL) {
 360:         dot = &message[last-1];
 361:         last = first(0, MDELETED);
 362:         if (last != NULL) {
 363:             dot = &message[last-1];
 364:             return(0);
 365:         }
 366:         else {
 367:             dot = &message[0];
 368:             return(-1);
 369:         }
 370:     }
 371: 
 372:     /*
 373: 	 * Following can't happen -- it keeps lint happy
 374: 	 */
 375: 
 376:     return(-1);
 377: }
 378: 
 379: /*
 380:  * Undelete the indicated messages.
 381:  */
 382: 
 383: undelete(msgvec)
 384:     int *msgvec;
 385: {
 386:     register struct message *mp;
 387:     register *ip, mesg;
 388: 
 389:     for (ip = msgvec; ip-msgvec < msgCount; ip++) {
 390:         mesg = *ip;
 391:         if (mesg == 0)
 392:             return;
 393:         touch(mesg);
 394:         mp = &message[mesg-1];
 395:         dot = mp;
 396:         mp->m_flag &= ~MDELETED;
 397:     }
 398: }
 399: 
 400: /*
 401:  * Interactively dump core on "core"
 402:  */
 403: 
 404: core()
 405: {
 406:     register int pid;
 407:     int status;
 408: 
 409:     if ((pid = vfork()) == -1) {
 410:         perror("fork");
 411:         return(1);
 412:     }
 413:     if (pid == 0) {
 414:         sigchild();
 415:         abort();
 416:         _exit(1);
 417:     }
 418:     printf("Okie dokie");
 419:     fflush(stdout);
 420:     while (wait(&status) != pid)
 421:         ;
 422:     if (status & 0200)
 423:         printf(" -- Core dumped\n");
 424:     else
 425:         printf("\n");
 426: }
 427: 
 428: /*
 429:  * Clobber as many bytes of stack as the user requests.
 430:  */
 431: clobber(argv)
 432:     char **argv;
 433: {
 434:     register int times;
 435: 
 436:     if (argv[0] == 0)
 437:         times = 1;
 438:     else
 439:         times = (atoi(argv[0]) + 511) / 512;
 440:     clob1(times);
 441: }
 442: 
 443: /*
 444:  * Clobber the stack.
 445:  */
 446: clob1(n)
 447: {
 448:     char buf[512];
 449:     register char *cp;
 450: 
 451:     if (n <= 0)
 452:         return;
 453:     for (cp = buf; cp < &buf[512]; *cp++ = 0xFF)
 454:         ;
 455:     clob1(n - 1);
 456: }
 457: 
 458: /*
 459:  * Add the given header fields to the retained list.
 460:  * If no arguments, print the current list of retained fields.
 461:  */
 462: retfield(list)
 463:     char *list[];
 464: {
 465:     char field[BUFSIZ];
 466:     register int h;
 467:     register struct ignore *igp;
 468:     char **ap;
 469: 
 470:     if (argcount(list) == 0)
 471:         return(retshow());
 472:     for (ap = list; *ap != 0; ap++) {
 473:         istrcpy(field, *ap);
 474: 
 475:         if (member(field, retain))
 476:             continue;
 477: 
 478:         h = hash(field);
 479:         igp = (struct ignore *) calloc(1, sizeof (struct ignore));
 480:         igp->i_field = calloc(strlen(field) + 1, sizeof (char));
 481:         strcpy(igp->i_field, field);
 482:         igp->i_link = retain[h];
 483:         retain[h] = igp;
 484:         nretained++;
 485:     }
 486:     return(0);
 487: }
 488: 
 489: /*
 490:  * Print out all currently retained fields.
 491:  */
 492: retshow()
 493: {
 494:     register int h, count;
 495:     struct ignore *igp;
 496:     char **ap, **ring;
 497:     int igcomp();
 498: 
 499:     count = 0;
 500:     for (h = 0; h < HSHSIZE; h++)
 501:         for (igp = retain[h]; igp != 0; igp = igp->i_link)
 502:             count++;
 503:     if (count == 0) {
 504:         printf("No fields currently being retained.\n");
 505:         return(0);
 506:     }
 507:     ring = (char **) salloc((count + 1) * sizeof (char *));
 508:     ap = ring;
 509:     for (h = 0; h < HSHSIZE; h++)
 510:         for (igp = retain[h]; igp != 0; igp = igp->i_link)
 511:             *ap++ = igp->i_field;
 512:     *ap = 0;
 513:     qsort(ring, count, sizeof (char *), igcomp);
 514:     for (ap = ring; *ap != 0; ap++)
 515:         printf("%s\n", *ap);
 516:     return(0);
 517: }
 518: 
 519: /*
 520:  * Add the given header fields to the ignored list.
 521:  * If no arguments, print the current list of ignored fields.
 522:  */
 523: igfield(list)
 524:     char *list[];
 525: {
 526:     char field[BUFSIZ];
 527:     register int h;
 528:     register struct ignore *igp;
 529:     char **ap;
 530: 
 531:     if (argcount(list) == 0)
 532:         return(igshow());
 533:     for (ap = list; *ap != 0; ap++) {
 534:         if (isign(*ap))
 535:             continue;
 536:         istrcpy(field, *ap);
 537:         h = hash(field);
 538:         igp = (struct ignore *) calloc(1, sizeof (struct ignore));
 539:         igp->i_field = calloc(strlen(field) + 1, sizeof (char));
 540:         strcpy(igp->i_field, field);
 541:         igp->i_link = ignore[h];
 542:         ignore[h] = igp;
 543:     }
 544:     return(0);
 545: }
 546: 
 547: /*
 548:  * Print out all currently ignored fields.
 549:  */
 550: igshow()
 551: {
 552:     register int h, count;
 553:     struct ignore *igp;
 554:     char **ap, **ring;
 555:     int igcomp();
 556: 
 557:     count = 0;
 558:     for (h = 0; h < HSHSIZE; h++)
 559:         for (igp = ignore[h]; igp != 0; igp = igp->i_link)
 560:             count++;
 561:     if (count == 0) {
 562:         printf("No fields currently being ignored.\n");
 563:         return(0);
 564:     }
 565:     ring = (char **) salloc((count + 1) * sizeof (char *));
 566:     ap = ring;
 567:     for (h = 0; h < HSHSIZE; h++)
 568:         for (igp = ignore[h]; igp != 0; igp = igp->i_link)
 569:             *ap++ = igp->i_field;
 570:     *ap = 0;
 571:     qsort(ring, count, sizeof (char *), igcomp);
 572:     for (ap = ring; *ap != 0; ap++)
 573:         printf("%s\n", *ap);
 574:     return(0);
 575: }
 576: 
 577: /*
 578:  * Compare two names for sorting ignored field list.
 579:  */
 580: igcomp(l, r)
 581:     char **l, **r;
 582: {
 583: 
 584:     return(strcmp(*l, *r));
 585: }

Defined functions

clob1 defined in line 446; used 2 times
clobber defined in line 431; used 2 times
copycmd defined in line 114; used 2 times
core defined in line 404; used 4 times
delete defined in line 303; used 2 times
delm defined in line 343; used 2 times
deltype defined in line 313; used 3 times
igcomp defined in line 580; used 4 times
igfield defined in line 523; used 3 times
igshow defined in line 550; used 1 times
next defined in line 26; used 2 times
retfield defined in line 462; used 2 times
retshow defined in line 492; used 1 times
save defined in line 104; used 2 times
save1 defined in line 125; used 2 times
snarf defined in line 264; used 3 times
swrite defined in line 191; used 2 times
undelete defined in line 383; used 2 times

Defined variables

sccsid defined in line 8; never used
Last modified: 1985-09-18
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1585
Valid CSS Valid XHTML 1.0 Strict