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