|
|
1.1 ! root 1: #ident "@(#)lex.c 1.5 'attmail mail(1) command'" ! 2: #ident "@(#)mailx:lex.c 1.21.3.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:lex.c 1.21.1.1" ! 11: ! 12: #include "rcv.h" ! 13: ! 14: /* ! 15: * mailx -- a modified version of a University of California at Berkeley ! 16: * mail program ! 17: * ! 18: * Lexical processing of commands. ! 19: */ ! 20: ! 21: #ifdef SIGCONT ! 22: static void contin(); ! 23: #endif ! 24: static int isprefix(); ! 25: static struct cmd *lex(); ! 26: static int Passeren(); ! 27: static void setmsize(); ! 28: ! 29: /* ! 30: * Set up editing on the given file name. ! 31: * If isedit is true, we are considered to be editing the file, ! 32: * otherwise we are reading our mail which has signficance for ! 33: * mbox and so forth. ! 34: */ ! 35: ! 36: setfile(name, isedit) ! 37: char *name; ! 38: int isedit; ! 39: { ! 40: FILE *ibuf; ! 41: int i; ! 42: static int shudclob; ! 43: static char efile[PATHSIZE]; ! 44: char fortest[128]; ! 45: struct stat stbuf; ! 46: ! 47: if ((ibuf = fopen(name, "r")) == NULL) { ! 48: if (exitflg) ! 49: exit(1); /* no mail, return error */ ! 50: if (isedit) ! 51: perror(name); ! 52: else if (!Hflag) { ! 53: if (strrchr(name,'/') == NOSTR) ! 54: fprintf(stderr, "No mail.\n"); ! 55: else ! 56: fprintf(stderr, "No mail for %s\n", strrchr(name,'/')+1); ! 57: } ! 58: return(-1); ! 59: } ! 60: fstat(fileno(ibuf), &stbuf); ! 61: if (stbuf.st_size == 0L) { ! 62: if (exitflg) ! 63: exit(1); /* no mail, return error */ ! 64: if (isedit) ! 65: fprintf(stderr, "%s: empty file\n", name); ! 66: else if (!Hflag) { ! 67: if (strrchr(name,'/') == NOSTR) ! 68: fprintf(stderr, "No mail.\n"); ! 69: else ! 70: fprintf(stderr, "No mail for %s\n", strrchr(name,'/')+1); ! 71: } ! 72: fclose(ibuf); ! 73: return(-1); ! 74: } ! 75: ! 76: fgets(fortest, sizeof fortest, ibuf); ! 77: fseek(ibuf, 0L, 0); ! 78: if (strncmp(fortest, "Forward to ", 11) == 0) { ! 79: if (exitflg) ! 80: exit(1); /* no mail, return error */ ! 81: fprintf(stderr, "Your mail is being forwarded to %s", fortest+11); ! 82: fclose(ibuf); ! 83: return (-1); ! 84: } ! 85: if (exitflg) ! 86: exit(0); /* there is mail, return success */ ! 87: ! 88: /* ! 89: * Looks like all will be well. Must hold signals ! 90: * while we are reading the new file, else we will ruin ! 91: * the message[] data structure. ! 92: * Copy the messages into /tmp and set pointers. ! 93: */ ! 94: ! 95: if (shudclob) { ! 96: holdsigs(); ! 97: if (edit) ! 98: edstop(); ! 99: else { ! 100: quit(); ! 101: Verhogen(); ! 102: } ! 103: relsesigs(); ! 104: } ! 105: ! 106: readonly = 0; ! 107: if (!isedit) ! 108: readonly = Passeren()==-1; ! 109: lock(name); /* adb */ ! 110: fstat(fileno(ibuf), &stbuf); ! 111: utimep->actime = stbuf.st_atime; ! 112: utimep->modtime = stbuf.st_mtime; ! 113: ! 114: holdsigs(); ! 115: if (!readonly) ! 116: if ((i = open(name, 1)) < 0) /* adb */ ! 117: readonly++; ! 118: else ! 119: close(i); ! 120: if (shudclob) { ! 121: fclose(itf); ! 122: fclose(otf); ! 123: free(message); ! 124: space=0; ! 125: } ! 126: shudclob = 1; ! 127: edit = isedit; ! 128: strncpy(efile, name, PATHSIZE); ! 129: editfile = efile; ! 130: if (name != mailname) ! 131: strcpy(mailname, name); ! 132: mailsize = fsize(ibuf); ! 133: if ((otf = fopen(tempMesg, "w")) == NULL) { ! 134: perror(tempMesg); ! 135: if (!edit) ! 136: Verhogen(); ! 137: exit(1); ! 138: } ! 139: if ((itf = fopen(tempMesg, "r")) == NULL) { ! 140: perror(tempMesg); ! 141: if (!edit) ! 142: Verhogen(); ! 143: exit(1); ! 144: } ! 145: removefile(tempMesg); ! 146: setptr(ibuf); ! 147: setmsize(msgCount); ! 148: unlock(); /* adb */ ! 149: fclose(ibuf); ! 150: relsesigs(); ! 151: sawcom = 0; ! 152: return(0); ! 153: } ! 154: ! 155: /* semaphore stuff is changed in V9/V10. adb */ ! 156: /* global to semaphores */ ! 157: static char semaphore[128]; ! 158: ! 159: /* ! 160: * return -1 if file is already being read, 0 otherwise ! 161: */ ! 162: static ! 163: Passeren() ! 164: { ! 165: char file[128]; ! 166: struct stat sbuf; ! 167: FILE *fp; ! 168: int pid; ! 169: extern char *getenv(); ! 170: char *home = getenv("HOME"); ! 171: ! 172: if (home == NULL) ! 173: return 0; ! 174: (void)strcpy(file, home); ! 175: (void)strcat(file, "/.Maillock"); ! 176: if (stat(file, &sbuf) >= 0) { ! 177: ! 178: /* lock file exists */ ! 179: fp = fopen(file, "r"); ! 180: if (fp != NULL) { ! 181: fscanf(fp, "%d", &pid); ! 182: fclose(fp); ! 183: } ! 184: if (fp == NULL || kill(pid, 0)==0) { ! 185: fprintf(stderr,"WARNING: You are already reading mail.\n"); ! 186: fprintf(stderr, "\tThis instance of mail is read only.\n"); ! 187: return -1; ! 188: } ! 189: } ! 190: ! 191: /* create a semaphore file */ ! 192: strcpy(semaphore, file); ! 193: Verhogen(); ! 194: fp = fopen(semaphore, "w"); ! 195: if (fp == NULL) ! 196: return 0; /* nothing else we can do */ ! 197: fprintf(fp, "%d somewhere", getpid()); ! 198: fclose(fp); ! 199: return 0; ! 200: } ! 201: ! 202: void ! 203: Verhogen() ! 204: { ! 205: unlink(semaphore); ! 206: } ! 207: ! 208: /* ! 209: * Interpret user commands one by one. If standard input is not a tty, ! 210: * print no prompt. ! 211: */ ! 212: ! 213: static int *msgvec; ! 214: static int shudprompt; ! 215: ! 216: void ! 217: commands() ! 218: { ! 219: int eofloop; ! 220: register int n; ! 221: char linebuf[LINESIZE]; ! 222: struct stat minfo; ! 223: FILE *ibuf; ! 224: FILE *lockopen(); /* adb */ ! 225: ! 226: #ifdef SIGCONT ! 227: # ifdef preSVr4 ! 228: sigset(SIGCONT, SIG_DFL); ! 229: # else ! 230: { ! 231: struct sigaction nsig; ! 232: nsig.sa_handler = SIG_DFL; ! 233: sigemptyset(&nsig.sa_mask); ! 234: nsig.sa_flags = SA_RESTART; ! 235: (void) sigaction(SIGCONT, &nsig, (struct sigaction*)0); ! 236: } ! 237: # endif ! 238: #endif ! 239: if (rcvmode && !sourcing) { ! 240: if (sigset(SIGINT, SIG_IGN) != (void (*)())SIG_IGN) /* adb */ ! 241: sigset(SIGINT, stop); ! 242: if (sigset(SIGHUP, SIG_IGN) != (void (*)())SIG_IGN) /* adb */ ! 243: sigset(SIGHUP, hangup); ! 244: } ! 245: for (;;) { ! 246: setjmp(srbuf); ! 247: ! 248: /* ! 249: * Print the prompt, if needed. Clear out ! 250: * string space, and flush the output. ! 251: */ ! 252: ! 253: if (!rcvmode && !sourcing) ! 254: return; ! 255: eofloop = 0; ! 256: top: ! 257: if ((shudprompt = (intty && !sourcing)) != 0) { ! 258: if (prompt==NOSTR) ! 259: prompt = "? "; ! 260: #ifdef SIGCONT ! 261: # ifdef preSVr4 ! 262: sigset(SIGCONT, contin); ! 263: # else ! 264: { ! 265: struct sigaction nsig; ! 266: nsig.sa_handler = contin; ! 267: sigemptyset(&nsig.sa_mask); ! 268: nsig.sa_flags = SA_RESTART; ! 269: (void) sigaction(SIGCONT, &nsig, (struct sigaction*)0); ! 270: } ! 271: # endif ! 272: #endif ! 273: if (stat(mailname, &minfo) >=0 && minfo.st_size > mailsize) { ! 274: int OmsgCount, i; ! 275: OmsgCount = msgCount; ! 276: fseek(otf, 0L, 2); ! 277: holdsigs(); ! 278: if ( (ibuf = lockopen(mailname, "r", 0666, -1, -1)) == NULL ) { /* adb */ ! 279: fprintf(stderr,"Can't reopen %s\n",mailname); ! 280: exit(1); ! 281: /* NOTREACHED */ ! 282: } ! 283: fseek(ibuf, mailsize, 0); ! 284: setptr(ibuf); ! 285: setmsize(msgCount); ! 286: stat(mailname, &minfo); ! 287: mailsize = minfo.st_size; ! 288: lockclose(ibuf); /* adb */ ! 289: /* unlockmail(); adb */ ! 290: if (msgCount-OmsgCount > 0) { ! 291: printf("New mail has arrived.\n"); ! 292: printf("Loaded %d new message%s\n", ! 293: msgCount-OmsgCount, ! 294: plural(msgCount-OmsgCount)); ! 295: if (value("header") != NOSTR) ! 296: for (i = OmsgCount+1; ! 297: i <= msgCount; i++) { ! 298: printhead(i); ! 299: sreset(); ! 300: } ! 301: } ! 302: relsesigs(); ! 303: } ! 304: printf("%s", prompt); ! 305: } ! 306: flush(); ! 307: sreset(); ! 308: ! 309: /* ! 310: * Read a line of commands from the current input ! 311: * and handle end of file specially. ! 312: */ ! 313: ! 314: n = 0; ! 315: for (;;) { ! 316: if (readline(input, &linebuf[n]) <= 0) { ! 317: if (n != 0) ! 318: break; ! 319: if (loading) ! 320: return; ! 321: if (sourcing) { ! 322: unstack(); ! 323: goto more; ! 324: } ! 325: if (value("ignoreeof") != NOSTR && shudprompt) { ! 326: if (++eofloop < 25) { ! 327: printf("Use \"quit\" to quit.\n"); ! 328: goto top; ! 329: } ! 330: } ! 331: if (edit) ! 332: edstop(); ! 333: return; ! 334: } ! 335: if ((n = strlen(linebuf)) == 0) ! 336: break; ! 337: n--; ! 338: if (linebuf[n] != '\\') ! 339: break; ! 340: linebuf[n++] = ' '; ! 341: } ! 342: #ifdef SIGCONT ! 343: # ifdef preSVr4 ! 344: sigset(SIGCONT, SIG_DFL); ! 345: # else ! 346: { ! 347: struct sigaction nsig; ! 348: nsig.sa_handler = SIG_DFL; ! 349: sigemptyset(&nsig.sa_mask); ! 350: nsig.sa_flags = SA_RESTART; ! 351: (void) sigaction(SIGCONT, &nsig, (struct sigaction*)0); ! 352: } ! 353: # endif ! 354: #endif ! 355: if (execute(linebuf, 0)) ! 356: return; ! 357: more: ; ! 358: } ! 359: } ! 360: ! 361: /* ! 362: * Execute a single command. If the command executed ! 363: * is "quit," then return non-zero so that the caller ! 364: * will know to return back to main, if he cares. ! 365: * Contxt is non-zero if called while composing mail. ! 366: */ ! 367: ! 368: execute(linebuf, contxt) ! 369: char linebuf[]; ! 370: { ! 371: char word[LINESIZE]; ! 372: char *arglist[MAXARGC]; ! 373: struct cmd *com; ! 374: register char *cp, *cp2; ! 375: register int c, e; ! 376: int muvec[2]; ! 377: ! 378: /* ! 379: * Strip the white space away from the beginning ! 380: * of the command, then scan out a word, which ! 381: * consists of anything except digits and white space. ! 382: * ! 383: * Handle |, ! and # differently to get the correct ! 384: * lexical conventions. ! 385: */ ! 386: ! 387: cp = linebuf; ! 388: while (any(*cp, " \t")) ! 389: cp++; ! 390: cp2 = word; ! 391: if (any(*cp, "!|#")) ! 392: *cp2++ = *cp++; ! 393: else ! 394: while (*cp && !any(*cp, " \t0123456789$^.:/-+*'\"")) ! 395: *cp2++ = *cp++; ! 396: *cp2 = '\0'; ! 397: ! 398: /* ! 399: * Look up the command; if not found, complain. ! 400: * Normally, a blank command would map to the ! 401: * first command in the table; while sourcing, ! 402: * however, we ignore blank lines to eliminate ! 403: * confusion. ! 404: */ ! 405: ! 406: if (sourcing && equal(word, "")) ! 407: return(0); ! 408: com = lex(word); ! 409: if (com == NONE) { ! 410: printf("Unknown command: \"%s\"\n", word); ! 411: if (loading) { ! 412: cond = CANY; ! 413: return(1); ! 414: } ! 415: if (sourcing) { ! 416: cond = CANY; ! 417: unstack(); ! 418: } ! 419: return(0); ! 420: } ! 421: ! 422: /* ! 423: * See if we should execute the command -- if a conditional ! 424: * we always execute it, otherwise, check the state of cond. ! 425: */ ! 426: ! 427: if ((com->c_argtype & F) == 0) ! 428: if (cond == CRCV && !rcvmode || cond == CSEND && rcvmode) ! 429: return(0); ! 430: ! 431: /* ! 432: * Special case so that quit causes a return to ! 433: * main, who will call the quit code directly. ! 434: * If we are in a source file, just unstack. ! 435: */ ! 436: ! 437: if (com->c_func == edstop && sourcing) { ! 438: if (loading) ! 439: return(1); ! 440: unstack(); ! 441: return(0); ! 442: } ! 443: if (!edit && com->c_func == edstop) { ! 444: sigset(SIGINT, SIG_IGN); ! 445: return(1); ! 446: } ! 447: ! 448: /* ! 449: * Process the arguments to the command, depending ! 450: * on the type he expects. Default to an error. ! 451: * If we are sourcing an interactive command, it's ! 452: * an error. ! 453: */ ! 454: ! 455: if (!rcvmode && (com->c_argtype & M) == 0) { ! 456: printf("May not execute \"%s\" while sending\n", ! 457: com->c_name); ! 458: if (loading) ! 459: return(1); ! 460: if (sourcing) ! 461: unstack(); ! 462: return(0); ! 463: } ! 464: if (sourcing && com->c_argtype & I) { ! 465: printf("May not execute \"%s\" while sourcing\n", ! 466: com->c_name); ! 467: if (loading) ! 468: return(1); ! 469: unstack(); ! 470: return(0); ! 471: } ! 472: if (readonly && com->c_argtype & W) { ! 473: printf("May not execute \"%s\" -- message file is read only\n", ! 474: com->c_name); ! 475: if (loading) ! 476: return(1); ! 477: if (sourcing) ! 478: unstack(); ! 479: return(0); ! 480: } ! 481: if (contxt && com->c_argtype & R) { ! 482: printf("Cannot recursively invoke \"%s\"\n", com->c_name); ! 483: return(0); ! 484: } ! 485: e = 1; ! 486: switch (com->c_argtype & ~(F|P|I|M|T|W|R)) { ! 487: case MSGLIST: ! 488: /* ! 489: * A message list defaulting to nearest forward ! 490: * legal message. ! 491: */ ! 492: if (msgvec == 0) { ! 493: printf("Illegal use of \"message list\"\n"); ! 494: return(-1); ! 495: } ! 496: if ((c = getmsglist(cp, msgvec, com->c_msgflag)) < 0) ! 497: break; ! 498: if (c == 0) ! 499: if (msgCount == 0) ! 500: *msgvec = NULL; ! 501: else { ! 502: *msgvec = first(com->c_msgflag, ! 503: com->c_msgmask); ! 504: msgvec[1] = NULL; ! 505: } ! 506: if (*msgvec == NULL) { ! 507: printf("No applicable messages\n"); ! 508: break; ! 509: } ! 510: e = (*com->c_func)(msgvec); ! 511: break; ! 512: ! 513: case NDMLIST: ! 514: /* ! 515: * A message list with no defaults, but no error ! 516: * if none exist. ! 517: */ ! 518: if (msgvec == 0) { ! 519: printf("Illegal use of \"message list\"\n"); ! 520: return(-1); ! 521: } ! 522: if (getmsglist(cp, msgvec, com->c_msgflag) < 0) ! 523: break; ! 524: e = (*com->c_func)(msgvec); ! 525: break; ! 526: ! 527: case STRLIST: ! 528: /* ! 529: * Just the straight string, with ! 530: * leading blanks removed. ! 531: */ ! 532: while (any(*cp, " \t")) ! 533: cp++; ! 534: e = (*com->c_func)(cp); ! 535: break; ! 536: ! 537: case RAWLIST: ! 538: /* ! 539: * A vector of strings, in shell style. ! 540: */ ! 541: if ((c = getrawlist(cp, arglist)) < 0) ! 542: break; ! 543: if (c < com->c_minargs) { ! 544: printf("%s requires at least %d arg(s)\n", ! 545: com->c_name, com->c_minargs); ! 546: break; ! 547: } ! 548: if (c > com->c_maxargs) { ! 549: printf("%s takes no more than %d arg(s)\n", ! 550: com->c_name, com->c_maxargs); ! 551: break; ! 552: } ! 553: e = (*com->c_func)(arglist); ! 554: break; ! 555: ! 556: case NOLIST: ! 557: /* ! 558: * Just the constant zero, for exiting, ! 559: * eg. ! 560: */ ! 561: e = (*com->c_func)(0); ! 562: break; ! 563: ! 564: default: ! 565: panic("Unknown argtype"); ! 566: } ! 567: ! 568: /* ! 569: * Exit the current source file on ! 570: * error. ! 571: */ ! 572: ! 573: if (e && loading) ! 574: return(1); ! 575: if (e && sourcing) ! 576: unstack(); ! 577: if (com->c_func == edstop) ! 578: return(1); ! 579: if (value("autoprint") != NOSTR && com->c_argtype & P) ! 580: if ((dot->m_flag & MDELETED) == 0) { ! 581: muvec[0] = dot - &message[0] + 1; ! 582: muvec[1] = 0; ! 583: type(muvec); ! 584: } ! 585: if (!sourcing && (com->c_argtype & T) == 0) ! 586: sawcom = 1; ! 587: return(0); ! 588: } ! 589: ! 590: #ifdef SIGCONT ! 591: /* ! 592: * When we wake up after ^Z, reprint the prompt. ! 593: */ ! 594: static void ! 595: contin() ! 596: { ! 597: if (shudprompt) ! 598: printf("%s", prompt); ! 599: fflush(stdout); ! 600: } ! 601: #endif ! 602: ! 603: /* ! 604: * Branch here on hangup signal and simulate quit. ! 605: */ ! 606: void ! 607: hangup() ! 608: { ! 609: ! 610: holdsigs(); ! 611: sigignore(SIGHUP); ! 612: if (edit) { ! 613: if (setjmp(srbuf)) ! 614: exit(0); ! 615: edstop(); ! 616: } else { ! 617: Verhogen(); ! 618: if (value("exit") != NOSTR) ! 619: exit(1); ! 620: else ! 621: quit(); ! 622: } ! 623: exit(0); ! 624: } ! 625: ! 626: /* ! 627: * Set the size of the message vector used to construct argument ! 628: * lists to message list functions. ! 629: */ ! 630: ! 631: static void ! 632: setmsize(sz) ! 633: { ! 634: ! 635: if (msgvec != (int *) 0) ! 636: free(msgvec); ! 637: if (sz < 1) ! 638: sz = 1; /* need at least one cell for terminating 0 */ ! 639: msgvec = (int *) calloc((unsigned) (sz + 1), sizeof *msgvec); ! 640: } ! 641: ! 642: /* ! 643: * Find the correct command in the command table corresponding ! 644: * to the passed command "word" ! 645: */ ! 646: ! 647: static struct cmd * ! 648: lex(word) ! 649: char word[]; ! 650: { ! 651: register struct cmd *cp; ! 652: ! 653: for (cp = &cmdtab[0]; cp->c_name != NOSTR; cp++) ! 654: if (isprefix(word, cp->c_name)) ! 655: return(cp); ! 656: return(NONE); ! 657: } ! 658: ! 659: /* ! 660: * Determine if as1 is a valid prefix of as2. ! 661: */ ! 662: static int ! 663: isprefix(as1, as2) ! 664: char *as1, *as2; ! 665: { ! 666: register char *s1, *s2; ! 667: ! 668: s1 = as1; ! 669: s2 = as2; ! 670: while (*s1++ == *s2) ! 671: if (*s2++ == '\0') ! 672: return(1); ! 673: return(*--s1 == '\0'); ! 674: } ! 675: ! 676: /* ! 677: * The following gets called on receipt of a rubout. This is ! 678: * to abort printout of a command, mainly. ! 679: * Dispatching here when command() is inactive crashes rcv. ! 680: * Close all open files except 0, 1, 2, and the temporary. ! 681: * The special call to getuserid() is needed so it won't get ! 682: * annoyed about losing its open file. ! 683: * Also, unstack all source files. ! 684: */ ! 685: ! 686: static int inithdr; /* am printing startup headers */ ! 687: ! 688: void ! 689: stop(s) ! 690: { ! 691: register NODE *head; ! 692: ! 693: noreset = 0; ! 694: if (!inithdr) ! 695: sawcom++; ! 696: inithdr = 0; ! 697: while (sourcing) ! 698: unstack(); ! 699: getuserid((char *) 0); ! 700: if ( !maxfiles ) ! 701: if ( (maxfiles=ulimit(4, 0)) < 0 ) ! 702: maxfiles = _NFILE; ! 703: for (head = fplist; head != (NODE *)NULL; head = head->next) { ! 704: if (head->fp == stdin || head->fp == stdout) ! 705: continue; ! 706: if (head->fp == itf || head->fp == otf) ! 707: continue; ! 708: if (head->fp == stderr) ! 709: continue; ! 710: if (head->fp == pipef) { ! 711: npclose(pipef); ! 712: pipef = NULL; ! 713: continue; ! 714: } ! 715: fclose(head->fp); ! 716: } ! 717: if (image >= 0) { ! 718: close(image); ! 719: image = -1; ! 720: } ! 721: clrbuf(stdout); ! 722: if (s) { ! 723: printf("Interrupt\n"); ! 724: sigrelse(s); ! 725: } ! 726: longjmp(srbuf, 1); ! 727: } ! 728: ! 729: /* ! 730: * Announce the presence of the current mailx version, ! 731: * give the message count, and print a header listing. ! 732: */ ! 733: ! 734: static char *greeting = "%s Type ? for help.\n"; ! 735: ! 736: void ! 737: announce() ! 738: { ! 739: int vec[2], mdot; ! 740: ! 741: if (!Hflag && value("quiet")==NOSTR) ! 742: printf(greeting, version); ! 743: mdot = newfileinfo(); ! 744: vec[0] = mdot; ! 745: vec[1] = 0; ! 746: dot = &message[mdot - 1]; ! 747: if (msgCount > 0 && !noheader) { ! 748: inithdr++; ! 749: headers(vec); ! 750: inithdr = 0; ! 751: } ! 752: } ! 753: ! 754: /* ! 755: * Announce information about the file we are editing. ! 756: * Return a likely place to set dot. ! 757: */ ! 758: newfileinfo() ! 759: { ! 760: register struct message *mp; ! 761: register int u, n, mdot, d, s; ! 762: char fname[BUFSIZ], zname[BUFSIZ], *ename; ! 763: ! 764: if (Hflag) ! 765: return(1); ! 766: for (mp = &message[0]; mp < &message[msgCount]; mp++) ! 767: if (mp->m_flag & MNEW) ! 768: break; ! 769: if (mp >= &message[msgCount]) ! 770: for (mp = &message[0]; mp < &message[msgCount]; mp++) ! 771: if ((mp->m_flag & MREAD) == 0) ! 772: break; ! 773: if (mp < &message[msgCount]) ! 774: mdot = mp - &message[0] + 1; ! 775: else ! 776: mdot = 1; ! 777: s = d = 0; ! 778: for (mp = &message[0], n = 0, u = 0; mp < &message[msgCount]; mp++) { ! 779: if (mp->m_flag & MNEW) ! 780: n++; ! 781: if ((mp->m_flag & MREAD) == 0) ! 782: u++; ! 783: if (mp->m_flag & MDELETED) ! 784: d++; ! 785: if (mp->m_flag & MSAVED) ! 786: s++; ! 787: } ! 788: ename=origname; ! 789: if (getfold(fname) >= 0) { ! 790: strcat(fname, "/"); ! 791: if (strncmp(fname, mailname, strlen(fname)) == 0) { ! 792: sprintf(zname, "+%s", mailname + strlen(fname)); ! 793: ename = zname; ! 794: } ! 795: } ! 796: printf("\"%s\": ", ename); ! 797: if (msgCount == 1) ! 798: printf("1 message"); ! 799: else ! 800: printf("%d messages", msgCount); ! 801: if (n > 0) ! 802: printf(" %d new", n); ! 803: if (u-n > 0) ! 804: printf(" %d unread", u); ! 805: if (d > 0) ! 806: printf(" %d deleted", d); ! 807: if (s > 0) ! 808: printf(" %d saved", s); ! 809: if (readonly) ! 810: printf(" [Read only]"); ! 811: printf("\n"); ! 812: return(mdot); ! 813: } ! 814: ! 815: /* ! 816: * Print the current version number. ! 817: */ ! 818: ! 819: pversion(e) ! 820: char *e; ! 821: { ! 822: (void) e; ! 823: printf("%s\n", version); ! 824: return(0); ! 825: } ! 826: ! 827: /* ! 828: * Load a file of user definitions. ! 829: */ ! 830: void ! 831: load(name) ! 832: char *name; ! 833: { ! 834: register FILE *in, *oldin; ! 835: ! 836: if ((in = fopen(name, "r")) == NULL) ! 837: return; ! 838: oldin = input; ! 839: input = in; ! 840: loading = 1; ! 841: sourcing = 1; ! 842: commands(); ! 843: loading = 0; ! 844: sourcing = 0; ! 845: input = oldin; ! 846: fclose(in); ! 847: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.