Annotation of src/usr.bin/msgs/msgs.c, Revision 1.1
1.1 ! deraadt 1: /* $NetBSD: msgs.c,v 1.7 1995/09/28 06:57:40 tls Exp $ */
! 2:
! 3: /*-
! 4: * Copyright (c) 1980, 1993
! 5: * The Regents of the University of California. All rights reserved.
! 6: *
! 7: * Redistribution and use in source and binary forms, with or without
! 8: * modification, are permitted provided that the following conditions
! 9: * are met:
! 10: * 1. Redistributions of source code must retain the above copyright
! 11: * notice, this list of conditions and the following disclaimer.
! 12: * 2. Redistributions in binary form must reproduce the above copyright
! 13: * notice, this list of conditions and the following disclaimer in the
! 14: * documentation and/or other materials provided with the distribution.
! 15: * 3. All advertising materials mentioning features or use of this software
! 16: * must display the following acknowledgement:
! 17: * This product includes software developed by the University of
! 18: * California, Berkeley and its contributors.
! 19: * 4. Neither the name of the University nor the names of its contributors
! 20: * may be used to endorse or promote products derived from this software
! 21: * without specific prior written permission.
! 22: *
! 23: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
! 24: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 25: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 26: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
! 27: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 28: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 29: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 30: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 31: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 32: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 33: * SUCH DAMAGE.
! 34: */
! 35:
! 36: #ifndef lint
! 37: static char copyright[] =
! 38: "@(#) Copyright (c) 1980, 1993\n\
! 39: The Regents of the University of California. All rights reserved.\n";
! 40: #endif /* not lint */
! 41:
! 42: #ifndef lint
! 43: #if 0
! 44: static char sccsid[] = "@(#)msgs.c 8.2 (Berkeley) 4/28/95";
! 45: #else
! 46: static char rcsid[] = "$NetBSD: msgs.c,v 1.7 1995/09/28 06:57:40 tls Exp $";
! 47: #endif
! 48: #endif /* not lint */
! 49:
! 50: /*
! 51: * msgs - a user bulletin board program
! 52: *
! 53: * usage:
! 54: * msgs [fhlopqr] [[-]number] to read messages
! 55: * msgs -s to place messages
! 56: * msgs -c [-days] to clean up the bulletin board
! 57: *
! 58: * prompt commands are:
! 59: * y print message
! 60: * n flush message, go to next message
! 61: * q flush message, quit
! 62: * p print message, turn on 'pipe thru more' mode
! 63: * P print message, turn off 'pipe thru more' mode
! 64: * - reprint last message
! 65: * s[-][<num>] [<filename>] save message
! 66: * m[-][<num>] mail with message in temp mbox
! 67: * x exit without flushing this message
! 68: * <num> print message number <num>
! 69: */
! 70:
! 71: #define V7 /* will look for TERM in the environment */
! 72: #define OBJECT /* will object to messages without Subjects */
! 73: #define REJECT /* will reject messages without Subjects
! 74: (OBJECT must be defined also) */
! 75: /* #define UNBUFFERED /* use unbuffered output */
! 76:
! 77: #include <sys/param.h>
! 78: #include <sys/ioctl.h>
! 79: #include <sys/stat.h>
! 80: #include <dirent.h>
! 81: #include <ctype.h>
! 82: #include <errno.h>
! 83: #include <pwd.h>
! 84: #include <setjmp.h>
! 85: #include <signal.h>
! 86: #include <stdio.h>
! 87: #include <stdlib.h>
! 88: #include <string.h>
! 89: #include <termios.h>
! 90: #include <time.h>
! 91: #include <unistd.h>
! 92: #include "pathnames.h"
! 93:
! 94: #define CMODE 0664 /* bounds file creation mode */
! 95: #define NO 0
! 96: #define YES 1
! 97: #define SUPERUSER 0 /* superuser uid */
! 98: #define DAEMON 1 /* daemon uid */
! 99: #define NLINES 24 /* default number of lines/crt screen */
! 100: #define NDAYS 21 /* default keep time for messages */
! 101: #define DAYS *24*60*60 /* seconds/day */
! 102: #define MSGSRC ".msgsrc" /* user's rc file */
! 103: #define BOUNDS "bounds" /* message bounds file */
! 104: #define NEXT "Next message? [yq]"
! 105: #define MORE "More? [ynq]"
! 106: #define NOMORE "(No more) [q] ?"
! 107:
! 108: typedef char bool;
! 109:
! 110: FILE *msgsrc;
! 111: FILE *newmsg;
! 112: char *sep = "-";
! 113: char inbuf[BUFSIZ];
! 114: char fname[128];
! 115: char cmdbuf[128];
! 116: char subj[128];
! 117: char from[128];
! 118: char date[128];
! 119: char *ptr;
! 120: char *in;
! 121: bool local;
! 122: bool ruptible;
! 123: bool totty;
! 124: bool seenfrom;
! 125: bool seensubj;
! 126: bool blankline;
! 127: bool printing = NO;
! 128: bool mailing = NO;
! 129: bool quitit = NO;
! 130: bool sending = NO;
! 131: bool intrpflg = NO;
! 132: bool restricted = NO;
! 133: int uid;
! 134: int msg;
! 135: int prevmsg;
! 136: int lct;
! 137: int nlines;
! 138: int Lpp = 0;
! 139: time_t t;
! 140: time_t keep;
! 141:
! 142: char *mktemp();
! 143: char *nxtfld();
! 144: void onintr();
! 145: void onsusp();
! 146:
! 147: /* option initialization */
! 148: bool hdrs = NO;
! 149: bool qopt = NO;
! 150: bool hush = NO;
! 151: bool send_msg = NO;
! 152: bool locomode = NO;
! 153: bool use_pager = NO;
! 154: bool clean = NO;
! 155: bool lastcmd = NO;
! 156: jmp_buf tstpbuf;
! 157:
! 158: main(argc, argv)
! 159: int argc; char *argv[];
! 160: {
! 161: bool newrc, already;
! 162: int rcfirst = 0; /* first message to print (from .rc) */
! 163: int rcback = 0; /* amount to back off of rcfirst */
! 164: int firstmsg, nextmsg, lastmsg = 0;
! 165: int blast = 0;
! 166: FILE *bounds;
! 167:
! 168: #ifdef UNBUFFERED
! 169: setbuf(stdout, NULL);
! 170: #endif
! 171:
! 172: time(&t);
! 173: setuid(uid = getuid());
! 174: ruptible = (signal(SIGINT, SIG_IGN) == SIG_DFL);
! 175: if (ruptible)
! 176: signal(SIGINT, SIG_DFL);
! 177:
! 178: argc--, argv++;
! 179: while (argc > 0) {
! 180: if (isdigit(argv[0][0])) { /* starting message # */
! 181: rcfirst = atoi(argv[0]);
! 182: }
! 183: else if (isdigit(argv[0][1])) { /* backward offset */
! 184: rcback = atoi( &( argv[0][1] ) );
! 185: }
! 186: else {
! 187: ptr = *argv;
! 188: while (*ptr) switch (*ptr++) {
! 189:
! 190: case '-':
! 191: break;
! 192:
! 193: case 'c':
! 194: if (uid != SUPERUSER && uid != DAEMON) {
! 195: fprintf(stderr, "Sorry\n");
! 196: exit(1);
! 197: }
! 198: clean = YES;
! 199: break;
! 200:
! 201: case 'f': /* silently */
! 202: hush = YES;
! 203: break;
! 204:
! 205: case 'h': /* headers only */
! 206: hdrs = YES;
! 207: break;
! 208:
! 209: case 'l': /* local msgs only */
! 210: locomode = YES;
! 211: break;
! 212:
! 213: case 'o': /* option to save last message */
! 214: lastcmd = YES;
! 215: break;
! 216:
! 217: case 'p': /* pipe thru 'more' during long msgs */
! 218: use_pager = YES;
! 219: break;
! 220:
! 221: case 'q': /* query only */
! 222: qopt = YES;
! 223: break;
! 224:
! 225: case 'r': /* restricted */
! 226: restricted = YES;
! 227: break;
! 228:
! 229:
! 230: case 's': /* sending TO msgs */
! 231: send_msg = YES;
! 232: break;
! 233:
! 234: default:
! 235: fprintf(stderr,
! 236: "usage: msgs [fhlopqr] [[-]number]\n");
! 237: exit(1);
! 238: }
! 239: }
! 240: argc--, argv++;
! 241: }
! 242:
! 243: /*
! 244: * determine current message bounds
! 245: */
! 246: sprintf(fname, "%s/%s", _PATH_MSGS, BOUNDS);
! 247: bounds = fopen(fname, "r");
! 248:
! 249: if (bounds != NULL) {
! 250: fscanf(bounds, "%d %d\n", &firstmsg, &lastmsg);
! 251: fclose(bounds);
! 252: blast = lastmsg; /* save upper bound */
! 253: }
! 254:
! 255: if (clean)
! 256: keep = t - (rcback? rcback : NDAYS) DAYS;
! 257:
! 258: if (clean || bounds == NULL) { /* relocate message bounds */
! 259: struct dirent *dp;
! 260: struct stat stbuf;
! 261: bool seenany = NO;
! 262: DIR *dirp;
! 263:
! 264: dirp = opendir(_PATH_MSGS);
! 265: if (dirp == NULL) {
! 266: perror(_PATH_MSGS);
! 267: exit(errno);
! 268: }
! 269: chmod(fname, CMODE);
! 270:
! 271: firstmsg = 32767;
! 272: lastmsg = 0;
! 273:
! 274: for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)){
! 275: register char *cp = dp->d_name;
! 276: register int i = 0;
! 277:
! 278: if (dp->d_ino == 0)
! 279: continue;
! 280: if (dp->d_namlen == 0)
! 281: continue;
! 282:
! 283: if (clean)
! 284: sprintf(inbuf, "%s/%s", _PATH_MSGS, cp);
! 285:
! 286: while (isdigit(*cp))
! 287: i = i * 10 + *cp++ - '0';
! 288: if (*cp)
! 289: continue; /* not a message! */
! 290:
! 291: if (clean) {
! 292: if (stat(inbuf, &stbuf) != 0)
! 293: continue;
! 294: if (stbuf.st_mtime < keep
! 295: && stbuf.st_mode&S_IWRITE) {
! 296: unlink(inbuf);
! 297: continue;
! 298: }
! 299: }
! 300:
! 301: if (i > lastmsg)
! 302: lastmsg = i;
! 303: if (i < firstmsg)
! 304: firstmsg = i;
! 305: seenany = YES;
! 306: }
! 307: closedir(dirp);
! 308:
! 309: if (!seenany) {
! 310: if (blast != 0) /* never lower the upper bound! */
! 311: lastmsg = blast;
! 312: firstmsg = lastmsg + 1;
! 313: }
! 314: else if (blast > lastmsg)
! 315: lastmsg = blast;
! 316:
! 317: if (!send_msg) {
! 318: bounds = fopen(fname, "w");
! 319: if (bounds == NULL) {
! 320: perror(fname);
! 321: exit(errno);
! 322: }
! 323: chmod(fname, CMODE);
! 324: fprintf(bounds, "%d %d\n", firstmsg, lastmsg);
! 325: fclose(bounds);
! 326: }
! 327: }
! 328:
! 329: if (send_msg) {
! 330: /*
! 331: * Send mode - place msgs in _PATH_MSGS
! 332: */
! 333: bounds = fopen(fname, "w");
! 334: if (bounds == NULL) {
! 335: perror(fname);
! 336: exit(errno);
! 337: }
! 338:
! 339: nextmsg = lastmsg + 1;
! 340: sprintf(fname, "%s/%d", _PATH_MSGS, nextmsg);
! 341: newmsg = fopen(fname, "w");
! 342: if (newmsg == NULL) {
! 343: perror(fname);
! 344: exit(errno);
! 345: }
! 346: chmod(fname, 0644);
! 347:
! 348: fprintf(bounds, "%d %d\n", firstmsg, nextmsg);
! 349: fclose(bounds);
! 350:
! 351: sending = YES;
! 352: if (ruptible)
! 353: signal(SIGINT, onintr);
! 354:
! 355: if (isatty(fileno(stdin))) {
! 356: ptr = getpwuid(uid)->pw_name;
! 357: printf("Message %d:\nFrom %s %sSubject: ",
! 358: nextmsg, ptr, ctime(&t));
! 359: fflush(stdout);
! 360: fgets(inbuf, sizeof inbuf, stdin);
! 361: putchar('\n');
! 362: fflush(stdout);
! 363: fprintf(newmsg, "From %s %sSubject: %s\n",
! 364: ptr, ctime(&t), inbuf);
! 365: blankline = seensubj = YES;
! 366: }
! 367: else
! 368: blankline = seensubj = NO;
! 369: for (;;) {
! 370: fgets(inbuf, sizeof inbuf, stdin);
! 371: if (feof(stdin) || ferror(stdin))
! 372: break;
! 373: blankline = (blankline || (inbuf[0] == '\n'));
! 374: seensubj = (seensubj || (!blankline && (strncmp(inbuf, "Subj", 4) == 0)));
! 375: fputs(inbuf, newmsg);
! 376: }
! 377: #ifdef OBJECT
! 378: if (!seensubj) {
! 379: printf("NOTICE: Messages should have a Subject field!\n");
! 380: #ifdef REJECT
! 381: unlink(fname);
! 382: #endif
! 383: exit(1);
! 384: }
! 385: #endif
! 386: exit(ferror(stdin));
! 387: }
! 388: if (clean)
! 389: exit(0);
! 390:
! 391: /*
! 392: * prepare to display messages
! 393: */
! 394: totty = (isatty(fileno(stdout)) != 0);
! 395: use_pager = use_pager && totty;
! 396:
! 397: sprintf(fname, "%s/%s", getenv("HOME"), MSGSRC);
! 398: msgsrc = fopen(fname, "r");
! 399: if (msgsrc) {
! 400: newrc = NO;
! 401: fscanf(msgsrc, "%d\n", &nextmsg);
! 402: fclose(msgsrc);
! 403: if (nextmsg > lastmsg+1) {
! 404: printf("Warning: bounds have been reset (%d, %d)\n",
! 405: firstmsg, lastmsg);
! 406: truncate(fname, (off_t)0);
! 407: newrc = YES;
! 408: }
! 409: else if (!rcfirst)
! 410: rcfirst = nextmsg - rcback;
! 411: }
! 412: else
! 413: newrc = YES;
! 414: msgsrc = fopen(fname, "r+");
! 415: if (msgsrc == NULL)
! 416: msgsrc = fopen(fname, "w");
! 417: if (msgsrc == NULL) {
! 418: perror(fname);
! 419: exit(errno);
! 420: }
! 421: if (rcfirst) {
! 422: if (rcfirst > lastmsg+1) {
! 423: printf("Warning: the last message is number %d.\n",
! 424: lastmsg);
! 425: rcfirst = nextmsg;
! 426: }
! 427: if (rcfirst > firstmsg)
! 428: firstmsg = rcfirst; /* don't set below first msg */
! 429: }
! 430: if (newrc) {
! 431: nextmsg = firstmsg;
! 432: fseek(msgsrc, 0L, 0);
! 433: fprintf(msgsrc, "%d\n", nextmsg);
! 434: fflush(msgsrc);
! 435: }
! 436:
! 437: #ifdef V7
! 438: if (totty) {
! 439: struct winsize win;
! 440: if (ioctl(fileno(stdout), TIOCGWINSZ, &win) != -1)
! 441: Lpp = win.ws_row;
! 442: if (Lpp <= 0) {
! 443: if (tgetent(inbuf, getenv("TERM")) <= 0
! 444: || (Lpp = tgetnum("li")) <= 0) {
! 445: Lpp = NLINES;
! 446: }
! 447: }
! 448: }
! 449: #endif
! 450: Lpp -= 6; /* for headers, etc. */
! 451:
! 452: already = NO;
! 453: prevmsg = firstmsg;
! 454: printing = YES;
! 455: if (ruptible)
! 456: signal(SIGINT, onintr);
! 457:
! 458: /*
! 459: * Main program loop
! 460: */
! 461: for (msg = firstmsg; msg <= lastmsg; msg++) {
! 462:
! 463: sprintf(fname, "%s/%d", _PATH_MSGS, msg);
! 464: newmsg = fopen(fname, "r");
! 465: if (newmsg == NULL)
! 466: continue;
! 467:
! 468: gfrsub(newmsg); /* get From and Subject fields */
! 469: if (locomode && !local) {
! 470: fclose(newmsg);
! 471: continue;
! 472: }
! 473:
! 474: if (qopt) { /* This has to be located here */
! 475: printf("There are new messages.\n");
! 476: exit(0);
! 477: }
! 478:
! 479: if (already && !hdrs)
! 480: putchar('\n');
! 481:
! 482: /*
! 483: * Print header
! 484: */
! 485: if (totty)
! 486: signal(SIGTSTP, onsusp);
! 487: (void) setjmp(tstpbuf);
! 488: already = YES;
! 489: nlines = 2;
! 490: if (seenfrom) {
! 491: printf("Message %d:\nFrom %s %s", msg, from, date);
! 492: nlines++;
! 493: }
! 494: if (seensubj) {
! 495: printf("Subject: %s", subj);
! 496: nlines++;
! 497: }
! 498: else {
! 499: if (seenfrom) {
! 500: putchar('\n');
! 501: nlines++;
! 502: }
! 503: while (nlines < 6
! 504: && fgets(inbuf, sizeof inbuf, newmsg)
! 505: && inbuf[0] != '\n') {
! 506: fputs(inbuf, stdout);
! 507: nlines++;
! 508: }
! 509: }
! 510:
! 511: lct = linecnt(newmsg);
! 512: if (lct)
! 513: printf("(%d%slines) ", lct, seensubj? " " : " more ");
! 514:
! 515: if (hdrs) {
! 516: printf("\n-----\n");
! 517: fclose(newmsg);
! 518: continue;
! 519: }
! 520:
! 521: /*
! 522: * Ask user for command
! 523: */
! 524: if (totty)
! 525: ask(lct? MORE : (msg==lastmsg? NOMORE : NEXT));
! 526: else
! 527: inbuf[0] = 'y';
! 528: if (totty)
! 529: signal(SIGTSTP, SIG_DFL);
! 530: cmnd:
! 531: in = inbuf;
! 532: switch (*in) {
! 533: case 'x':
! 534: case 'X':
! 535: exit(0);
! 536:
! 537: case 'q':
! 538: case 'Q':
! 539: quitit = YES;
! 540: printf("--Postponed--\n");
! 541: exit(0);
! 542: /* intentional fall-thru */
! 543: case 'n':
! 544: case 'N':
! 545: if (msg >= nextmsg) sep = "Flushed";
! 546: prevmsg = msg;
! 547: break;
! 548:
! 549: case 'p':
! 550: case 'P':
! 551: use_pager = (*in++ == 'p');
! 552: /* intentional fallthru */
! 553: case '\n':
! 554: case 'y':
! 555: default:
! 556: if (*in == '-') {
! 557: msg = prevmsg-1;
! 558: sep = "replay";
! 559: break;
! 560: }
! 561: if (isdigit(*in)) {
! 562: msg = next(in);
! 563: sep = in;
! 564: break;
! 565: }
! 566:
! 567: prmesg(nlines + lct + (seensubj? 1 : 0));
! 568: prevmsg = msg;
! 569:
! 570: }
! 571:
! 572: printf("--%s--\n", sep);
! 573: sep = "-";
! 574: if (msg >= nextmsg) {
! 575: nextmsg = msg + 1;
! 576: fseek(msgsrc, 0L, 0);
! 577: fprintf(msgsrc, "%d\n", nextmsg);
! 578: fflush(msgsrc);
! 579: }
! 580: if (newmsg)
! 581: fclose(newmsg);
! 582: if (quitit)
! 583: break;
! 584: }
! 585:
! 586: /*
! 587: * Make sure .rc file gets updated
! 588: */
! 589: if (--msg >= nextmsg) {
! 590: nextmsg = msg + 1;
! 591: fseek(msgsrc, 0L, 0);
! 592: fprintf(msgsrc, "%d\n", nextmsg);
! 593: fflush(msgsrc);
! 594: }
! 595: if (already && !quitit && lastcmd && totty) {
! 596: /*
! 597: * save or reply to last message?
! 598: */
! 599: msg = prevmsg;
! 600: ask(NOMORE);
! 601: if (inbuf[0] == '-' || isdigit(inbuf[0]))
! 602: goto cmnd;
! 603: }
! 604: if (!(already || hush || qopt))
! 605: printf("No new messages.\n");
! 606: exit(0);
! 607: }
! 608:
! 609: prmesg(length)
! 610: int length;
! 611: {
! 612: FILE *outf;
! 613: char *env_pager;
! 614:
! 615: if (use_pager && length > Lpp) {
! 616: signal(SIGPIPE, SIG_IGN);
! 617: signal(SIGQUIT, SIG_IGN);
! 618: if ((env_pager = getenv("PAGER")) == NULL) {
! 619: sprintf(cmdbuf, _PATH_PAGER, Lpp);
! 620: } else {
! 621: strcpy(cmdbuf, env_pager);
! 622: }
! 623: outf = popen(cmdbuf, "w");
! 624: if (!outf)
! 625: outf = stdout;
! 626: else
! 627: setbuf(outf, (char *)NULL);
! 628: }
! 629: else
! 630: outf = stdout;
! 631:
! 632: if (seensubj)
! 633: putc('\n', outf);
! 634:
! 635: while (fgets(inbuf, sizeof inbuf, newmsg)) {
! 636: fputs(inbuf, outf);
! 637: if (ferror(outf)) {
! 638: clearerr(outf);
! 639: break;
! 640: }
! 641: }
! 642:
! 643: if (outf != stdout) {
! 644: pclose(outf);
! 645: signal(SIGPIPE, SIG_DFL);
! 646: signal(SIGQUIT, SIG_DFL);
! 647: }
! 648: else {
! 649: fflush(stdout);
! 650: }
! 651:
! 652: /* trick to force wait on output */
! 653: tcdrain(fileno(stdout));
! 654: }
! 655:
! 656: void
! 657: onintr()
! 658: {
! 659: signal(SIGINT, onintr);
! 660: if (mailing)
! 661: unlink(fname);
! 662: if (sending) {
! 663: unlink(fname);
! 664: puts("--Killed--");
! 665: exit(1);
! 666: }
! 667: if (printing) {
! 668: putchar('\n');
! 669: if (hdrs)
! 670: exit(0);
! 671: sep = "Interrupt";
! 672: if (newmsg)
! 673: fseek(newmsg, 0L, 2);
! 674: intrpflg = YES;
! 675: }
! 676: }
! 677:
! 678: /*
! 679: * We have just gotten a susp. Suspend and prepare to resume.
! 680: */
! 681: void
! 682: onsusp()
! 683: {
! 684:
! 685: signal(SIGTSTP, SIG_DFL);
! 686: sigsetmask(0);
! 687: kill(0, SIGTSTP);
! 688: signal(SIGTSTP, onsusp);
! 689: if (!mailing)
! 690: longjmp(tstpbuf, 0);
! 691: }
! 692:
! 693: linecnt(f)
! 694: FILE *f;
! 695: {
! 696: off_t oldpos = ftell(f);
! 697: int l = 0;
! 698: char lbuf[BUFSIZ];
! 699:
! 700: while (fgets(lbuf, sizeof lbuf, f))
! 701: l++;
! 702: clearerr(f);
! 703: fseek(f, oldpos, 0);
! 704: return (l);
! 705: }
! 706:
! 707: next(buf)
! 708: char *buf;
! 709: {
! 710: int i;
! 711: sscanf(buf, "%d", &i);
! 712: sprintf(buf, "Goto %d", i);
! 713: return(--i);
! 714: }
! 715:
! 716: ask(prompt)
! 717: char *prompt;
! 718: {
! 719: char inch;
! 720: int n, cmsg;
! 721: off_t oldpos;
! 722: FILE *cpfrom, *cpto;
! 723:
! 724: printf("%s ", prompt);
! 725: fflush(stdout);
! 726: intrpflg = NO;
! 727: (void) fgets(inbuf, sizeof inbuf, stdin);
! 728: if ((n = strlen(inbuf)) > 0 && inbuf[n - 1] == '\n')
! 729: inbuf[n - 1] = '\0';
! 730: if (intrpflg)
! 731: inbuf[0] = 'x';
! 732:
! 733: /*
! 734: * Handle 'mail' and 'save' here.
! 735: */
! 736: if (((inch = inbuf[0]) == 's' || inch == 'm') && !restricted) {
! 737: if (inbuf[1] == '-')
! 738: cmsg = prevmsg;
! 739: else if (isdigit(inbuf[1]))
! 740: cmsg = atoi(&inbuf[1]);
! 741: else
! 742: cmsg = msg;
! 743: sprintf(fname, "%s/%d", _PATH_MSGS, cmsg);
! 744:
! 745: oldpos = ftell(newmsg);
! 746:
! 747: cpfrom = fopen(fname, "r");
! 748: if (!cpfrom) {
! 749: printf("Message %d not found\n", cmsg);
! 750: ask (prompt);
! 751: return;
! 752: }
! 753:
! 754: if (inch == 's') {
! 755: in = nxtfld(inbuf);
! 756: if (*in) {
! 757: for (n=0; in[n] > ' '; n++) { /* sizeof fname? */
! 758: fname[n] = in[n];
! 759: }
! 760: fname[n] = NULL;
! 761: }
! 762: else
! 763: strcpy(fname, "Messages");
! 764: }
! 765: else {
! 766: strcpy(fname, _PATH_TMP);
! 767: mktemp(fname);
! 768: sprintf(cmdbuf, _PATH_MAIL, fname);
! 769: mailing = YES;
! 770: }
! 771: cpto = fopen(fname, "a");
! 772: if (!cpto) {
! 773: perror(fname);
! 774: mailing = NO;
! 775: fseek(newmsg, oldpos, 0);
! 776: ask(prompt);
! 777: return;
! 778: }
! 779:
! 780: while (n = fread(inbuf, 1, sizeof inbuf, cpfrom))
! 781: fwrite(inbuf, 1, n, cpto);
! 782:
! 783: fclose(cpfrom);
! 784: fclose(cpto);
! 785: fseek(newmsg, oldpos, 0); /* reposition current message */
! 786: if (inch == 's')
! 787: printf("Message %d saved in \"%s\"\n", cmsg, fname);
! 788: else {
! 789: system(cmdbuf);
! 790: unlink(fname);
! 791: mailing = NO;
! 792: }
! 793: ask(prompt);
! 794: }
! 795: }
! 796:
! 797: gfrsub(infile)
! 798: FILE *infile;
! 799: {
! 800: off_t frompos;
! 801:
! 802: seensubj = seenfrom = NO;
! 803: local = YES;
! 804: subj[0] = from[0] = date[0] = NULL;
! 805:
! 806: /*
! 807: * Is this a normal message?
! 808: */
! 809: if (fgets(inbuf, sizeof inbuf, infile)) {
! 810: if (strncmp(inbuf, "From", 4)==0) {
! 811: /*
! 812: * expected form starts with From
! 813: */
! 814: seenfrom = YES;
! 815: frompos = ftell(infile);
! 816: ptr = from;
! 817: in = nxtfld(inbuf);
! 818: if (*in) while (*in && *in > ' ') {
! 819: if (*in == ':' || *in == '@' || *in == '!')
! 820: local = NO;
! 821: *ptr++ = *in++;
! 822: /* what about sizeof from ? */
! 823: }
! 824: *ptr = NULL;
! 825: if (*(in = nxtfld(in)))
! 826: strncpy(date, in, sizeof date);
! 827: else {
! 828: date[0] = '\n';
! 829: date[1] = NULL;
! 830: }
! 831: }
! 832: else {
! 833: /*
! 834: * not the expected form
! 835: */
! 836: fseek(infile, 0L, 0);
! 837: return;
! 838: }
! 839: }
! 840: else
! 841: /*
! 842: * empty file ?
! 843: */
! 844: return;
! 845:
! 846: /*
! 847: * look for Subject line until EOF or a blank line
! 848: */
! 849: while (fgets(inbuf, sizeof inbuf, infile)
! 850: && !(blankline = (inbuf[0] == '\n'))) {
! 851: /*
! 852: * extract Subject line
! 853: */
! 854: if (!seensubj && strncmp(inbuf, "Subj", 4)==0) {
! 855: seensubj = YES;
! 856: frompos = ftell(infile);
! 857: strncpy(subj, nxtfld(inbuf), sizeof subj);
! 858: }
! 859: }
! 860: if (!blankline)
! 861: /*
! 862: * ran into EOF
! 863: */
! 864: fseek(infile, frompos, 0);
! 865:
! 866: if (!seensubj)
! 867: /*
! 868: * for possible use with Mail
! 869: */
! 870: strncpy(subj, "(No Subject)\n", sizeof subj);
! 871: }
! 872:
! 873: char *
! 874: nxtfld(s)
! 875: char *s;
! 876: {
! 877: if (*s) while (*s && *s > ' ') s++; /* skip over this field */
! 878: if (*s) while (*s && *s <= ' ') s++; /* find start of next field */
! 879: return (s);
! 880: }