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