141441Sbostic /*-
262133Sbostic * Copyright (c) 1980, 1993
362133Sbostic * The Regents of the University of California. All rights reserved.
441441Sbostic *
541441Sbostic * %sccs.include.redist.c%
621983Sdist */
721983Sdist
86856Srrh #ifndef lint
962133Sbostic static char copyright[] =
1062133Sbostic "@(#) Copyright (c) 1980, 1993\n\
1162133Sbostic The Regents of the University of California. All rights reserved.\n";
1241441Sbostic #endif /* not lint */
1321983Sdist
1421983Sdist #ifndef lint
15*69023Sbostic static char sccsid[] = "@(#)msgs.c 8.2 (Berkeley) 04/28/95";
1641441Sbostic #endif /* not lint */
1721983Sdist
186856Srrh /*
196856Srrh * msgs - a user bulletin board program
206856Srrh *
216856Srrh * usage:
226856Srrh * msgs [fhlopq] [[-]number] to read messages
236856Srrh * msgs -s to place messages
246856Srrh * msgs -c [-days] to clean up the bulletin board
256856Srrh *
266856Srrh * prompt commands are:
276856Srrh * y print message
286856Srrh * n flush message, go to next message
296856Srrh * q flush message, quit
306856Srrh * p print message, turn on 'pipe thru more' mode
316856Srrh * P print message, turn off 'pipe thru more' mode
326856Srrh * - reprint last message
336856Srrh * s[-][<num>] [<filename>] save message
346856Srrh * m[-][<num>] mail with message in temp mbox
356856Srrh * x exit without flushing this message
3616335Sralph * <num> print message number <num>
376856Srrh */
386856Srrh
396856Srrh #define V7 /* will look for TERM in the environment */
406856Srrh #define OBJECT /* will object to messages without Subjects */
416856Srrh /* #define REJECT /* will reject messages without Subjects
426856Srrh (OBJECT must be defined also) */
436856Srrh /* #define UNBUFFERED /* use unbuffered output */
446856Srrh
456858Srrh #include <sys/param.h>
4613616Ssam #include <sys/dir.h>
47*69023Sbostic #include <sys/ioctl.h>
486856Srrh #include <sys/stat.h>
496856Srrh #include <ctype.h>
5046257Storek #include <errno.h>
516856Srrh #include <pwd.h>
5246257Storek #include <setjmp.h>
5346257Storek #include <signal.h>
5437893Sbostic #include <stdio.h>
5546257Storek #include <stdlib.h>
5646257Storek #include <string.h>
57*69023Sbostic #include <termios.h>
5846257Storek #include <time.h>
5960134Sbostic #include <unistd.h>
6037893Sbostic #include "pathnames.h"
616856Srrh
626856Srrh #define CMODE 0666 /* bounds file creation mode */
636856Srrh #define NO 0
646856Srrh #define YES 1
656856Srrh #define SUPERUSER 0 /* superuser uid */
666856Srrh #define DAEMON 1 /* daemon uid */
676856Srrh #define NLINES 24 /* default number of lines/crt screen */
686856Srrh #define NDAYS 21 /* default keep time for messages */
696856Srrh #define DAYS *24*60*60 /* seconds/day */
706856Srrh #define MSGSRC ".msgsrc" /* user's rc file */
716856Srrh #define BOUNDS "bounds" /* message bounds file */
726856Srrh #define NEXT "Next message? [yq]"
736856Srrh #define MORE "More? [ynq]"
746856Srrh #define NOMORE "(No more) [q] ?"
756856Srrh
766856Srrh typedef char bool;
776856Srrh
7846257Storek FILE *msgsrc;
796856Srrh FILE *newmsg;
806856Srrh char *sep = "-";
816856Srrh char inbuf[BUFSIZ];
826856Srrh char fname[128];
836856Srrh char cmdbuf[128];
846856Srrh char subj[128];
856856Srrh char from[128];
866856Srrh char date[128];
876856Srrh char *ptr;
886856Srrh char *in;
896856Srrh bool local;
906856Srrh bool ruptible;
916856Srrh bool totty;
926856Srrh bool seenfrom;
936856Srrh bool seensubj;
946856Srrh bool blankline;
956856Srrh bool printing = NO;
966856Srrh bool mailing = NO;
976856Srrh bool quitit = NO;
986856Srrh bool sending = NO;
996856Srrh bool intrpflg = NO;
1006856Srrh int uid;
1016856Srrh int msg;
1026856Srrh int prevmsg;
1036856Srrh int lct;
1046856Srrh int nlines;
10527026Sbloom int Lpp = 0;
1066856Srrh time_t t;
1076856Srrh time_t keep;
1086856Srrh
10946160Sbostic char *mktemp();
1106856Srrh char *nxtfld();
11146160Sbostic void onintr();
11246160Sbostic void onsusp();
1136856Srrh
1146856Srrh /* option initialization */
1156856Srrh bool hdrs = NO;
1166856Srrh bool qopt = NO;
1176856Srrh bool hush = NO;
11846160Sbostic bool send_msg = NO;
1196856Srrh bool locomode = NO;
12046160Sbostic bool use_pager = NO;
1216856Srrh bool clean = NO;
1226856Srrh bool lastcmd = NO;
12314052Ssam jmp_buf tstpbuf;
1246856Srrh
main(argc,argv)1256856Srrh main(argc, argv)
1266856Srrh int argc; char *argv[];
1276856Srrh {
1286856Srrh bool newrc, already;
1296856Srrh int rcfirst = 0; /* first message to print (from .rc) */
13012515Sralph int rcback = 0; /* amount to back off of rcfirst */
1316856Srrh int firstmsg, nextmsg, lastmsg = 0;
1326856Srrh int blast = 0;
13346257Storek FILE *bounds;
1346856Srrh
13517196Sralph #ifdef UNBUFFERED
1366856Srrh setbuf(stdout, NULL);
1376856Srrh #endif
1386856Srrh
1396856Srrh time(&t);
1406856Srrh setuid(uid = getuid());
1416856Srrh ruptible = (signal(SIGINT, SIG_IGN) == SIG_DFL);
1426856Srrh if (ruptible)
1436856Srrh signal(SIGINT, SIG_DFL);
1446856Srrh
1456856Srrh argc--, argv++;
1466856Srrh while (argc > 0) {
1476856Srrh if (isdigit(argv[0][0])) { /* starting message # */
1486856Srrh rcfirst = atoi(argv[0]);
1496856Srrh }
1506856Srrh else if (isdigit(argv[0][1])) { /* backward offset */
1516856Srrh rcback = atoi( &( argv[0][1] ) );
1526856Srrh }
1536856Srrh else {
1546856Srrh ptr = *argv;
1556856Srrh while (*ptr) switch (*ptr++) {
1566856Srrh
1576856Srrh case '-':
1586856Srrh break;
1596856Srrh
1606856Srrh case 'c':
1616856Srrh if (uid != SUPERUSER && uid != DAEMON) {
1626856Srrh fprintf(stderr, "Sorry\n");
1636856Srrh exit(1);
1646856Srrh }
1656856Srrh clean = YES;
1666856Srrh break;
1676856Srrh
1686856Srrh case 'f': /* silently */
1696856Srrh hush = YES;
1706856Srrh break;
1716856Srrh
1726856Srrh case 'h': /* headers only */
1736856Srrh hdrs = YES;
1746856Srrh break;
1756856Srrh
1766856Srrh case 'l': /* local msgs only */
1776856Srrh locomode = YES;
1786856Srrh break;
1796856Srrh
1806856Srrh case 'o': /* option to save last message */
1816856Srrh lastcmd = YES;
1826856Srrh break;
1836856Srrh
1846856Srrh case 'p': /* pipe thru 'more' during long msgs */
18546160Sbostic use_pager = YES;
1866856Srrh break;
1876856Srrh
1886856Srrh case 'q': /* query only */
1896856Srrh qopt = YES;
1906856Srrh break;
1916856Srrh
1926856Srrh case 's': /* sending TO msgs */
19346160Sbostic send_msg = YES;
1946856Srrh break;
1956856Srrh
1966856Srrh default:
1976856Srrh fprintf(stderr,
1986856Srrh "usage: msgs [fhlopq] [[-]number]\n");
1996856Srrh exit(1);
2006856Srrh }
2016856Srrh }
2026856Srrh argc--, argv++;
2036856Srrh }
2046856Srrh
2056856Srrh /*
2066856Srrh * determine current message bounds
2076856Srrh */
20837893Sbostic sprintf(fname, "%s/%s", _PATH_MSGS, BOUNDS);
2096856Srrh bounds = fopen(fname, "r");
2106856Srrh
2116856Srrh if (bounds != NULL) {
2126856Srrh fscanf(bounds, "%d %d\n", &firstmsg, &lastmsg);
2136856Srrh fclose(bounds);
2146856Srrh blast = lastmsg; /* save upper bound */
2156856Srrh }
2166856Srrh
2176856Srrh if (clean)
2186856Srrh keep = t - (rcback? rcback : NDAYS) DAYS;
2196856Srrh
2206856Srrh if (clean || bounds == NULL) { /* relocate message bounds */
2216858Srrh struct direct *dp;
2226856Srrh struct stat stbuf;
2236856Srrh bool seenany = NO;
2246858Srrh DIR *dirp;
2256856Srrh
22637893Sbostic dirp = opendir(_PATH_MSGS);
2276858Srrh if (dirp == NULL) {
22837893Sbostic perror(_PATH_MSGS);
2296856Srrh exit(errno);
2306856Srrh }
2316856Srrh
2326856Srrh firstmsg = 32767;
2336856Srrh lastmsg = 0;
2346856Srrh
2356858Srrh for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)){
2366858Srrh register char *cp = dp->d_name;
2376856Srrh register int i = 0;
2386856Srrh
2396858Srrh if (dp->d_ino == 0)
2406856Srrh continue;
2416858Srrh if (dp->d_namlen == 0)
2426858Srrh continue;
2436856Srrh
2446856Srrh if (clean)
24537893Sbostic sprintf(inbuf, "%s/%s", _PATH_MSGS, cp);
2466856Srrh
2476856Srrh while (isdigit(*cp))
2486856Srrh i = i * 10 + *cp++ - '0';
2496856Srrh if (*cp)
2506856Srrh continue; /* not a message! */
2516856Srrh
2526856Srrh if (clean) {
2536856Srrh if (stat(inbuf, &stbuf) != 0)
2546856Srrh continue;
2556856Srrh if (stbuf.st_mtime < keep
2566856Srrh && stbuf.st_mode&S_IWRITE) {
2576856Srrh unlink(inbuf);
2586856Srrh continue;
2596856Srrh }
2606856Srrh }
2616856Srrh
2626856Srrh if (i > lastmsg)
2636856Srrh lastmsg = i;
2646856Srrh if (i < firstmsg)
2656856Srrh firstmsg = i;
2666856Srrh seenany = YES;
2676856Srrh }
2686858Srrh closedir(dirp);
2696856Srrh
2706856Srrh if (!seenany) {
2716856Srrh if (blast != 0) /* never lower the upper bound! */
2726856Srrh lastmsg = blast;
2736856Srrh firstmsg = lastmsg + 1;
2746856Srrh }
2756856Srrh else if (blast > lastmsg)
2766856Srrh lastmsg = blast;
2776856Srrh
27846160Sbostic if (!send_msg) {
2796856Srrh bounds = fopen(fname, "w");
2806856Srrh if (bounds == NULL) {
2816856Srrh perror(fname);
2826856Srrh exit(errno);
2836856Srrh }
2846856Srrh chmod(fname, CMODE);
2856856Srrh fprintf(bounds, "%d %d\n", firstmsg, lastmsg);
2866856Srrh fclose(bounds);
2876856Srrh }
2886856Srrh }
2896856Srrh
29046160Sbostic if (send_msg) {
2916856Srrh /*
29237893Sbostic * Send mode - place msgs in _PATH_MSGS
2936856Srrh */
2946856Srrh bounds = fopen(fname, "w");
2956856Srrh if (bounds == NULL) {
2966856Srrh perror(fname);
2976856Srrh exit(errno);
2986856Srrh }
2996856Srrh
3006856Srrh nextmsg = lastmsg + 1;
30137893Sbostic sprintf(fname, "%s/%d", _PATH_MSGS, nextmsg);
3026856Srrh newmsg = fopen(fname, "w");
3036856Srrh if (newmsg == NULL) {
3046856Srrh perror(fname);
3056856Srrh exit(errno);
3066856Srrh }
3076856Srrh chmod(fname, 0644);
3086856Srrh
3096856Srrh fprintf(bounds, "%d %d\n", firstmsg, nextmsg);
3106856Srrh fclose(bounds);
3116856Srrh
3126856Srrh sending = YES;
3136856Srrh if (ruptible)
3146856Srrh signal(SIGINT, onintr);
3156856Srrh
3166856Srrh if (isatty(fileno(stdin))) {
3176856Srrh ptr = getpwuid(uid)->pw_name;
3186856Srrh printf("Message %d:\nFrom %s %sSubject: ",
3196856Srrh nextmsg, ptr, ctime(&t));
3206856Srrh fflush(stdout);
3216856Srrh fgets(inbuf, sizeof inbuf, stdin);
3226856Srrh putchar('\n');
3236856Srrh fflush(stdout);
3246856Srrh fprintf(newmsg, "From %s %sSubject: %s\n",
3256856Srrh ptr, ctime(&t), inbuf);
3266856Srrh blankline = seensubj = YES;
3276856Srrh }
3286856Srrh else
3296856Srrh blankline = seensubj = NO;
3306856Srrh for (;;) {
3316856Srrh fgets(inbuf, sizeof inbuf, stdin);
3326856Srrh if (feof(stdin) || ferror(stdin))
3336856Srrh break;
3346856Srrh blankline = (blankline || (inbuf[0] == '\n'));
3356856Srrh seensubj = (seensubj || (!blankline && (strncmp(inbuf, "Subj", 4) == 0)));
3366856Srrh fputs(inbuf, newmsg);
3376856Srrh }
3386856Srrh #ifdef OBJECT
3396856Srrh if (!seensubj) {
3406856Srrh printf("NOTICE: Messages should have a Subject field!\n");
3416856Srrh #ifdef REJECT
3426856Srrh unlink(fname);
3436856Srrh #endif
3446856Srrh exit(1);
3456856Srrh }
3466856Srrh #endif
3476856Srrh exit(ferror(stdin));
3486856Srrh }
3496856Srrh if (clean)
3506856Srrh exit(0);
3516856Srrh
3526856Srrh /*
3536856Srrh * prepare to display messages
3546856Srrh */
3556856Srrh totty = (isatty(fileno(stdout)) != 0);
35646160Sbostic use_pager = use_pager && totty;
3576856Srrh
3586856Srrh sprintf(fname, "%s/%s", getenv("HOME"), MSGSRC);
3596856Srrh msgsrc = fopen(fname, "r");
3606856Srrh if (msgsrc) {
3616856Srrh newrc = NO;
3626856Srrh fscanf(msgsrc, "%d\n", &nextmsg);
3636856Srrh fclose(msgsrc);
36416335Sralph if (nextmsg > lastmsg+1) {
36516335Sralph printf("Warning: bounds have been reset (%d, %d)\n",
36616335Sralph firstmsg, lastmsg);
36746160Sbostic truncate(fname, (off_t)0);
36816335Sralph newrc = YES;
36916335Sralph }
37016335Sralph else if (!rcfirst)
3716856Srrh rcfirst = nextmsg - rcback;
3726856Srrh }
37316335Sralph else
3746856Srrh newrc = YES;
37558212Sbostic msgsrc = fopen(fname, "r+");
37658212Sbostic if (msgsrc == NULL)
37758212Sbostic msgsrc = fopen(fname, "w");
3786856Srrh if (msgsrc == NULL) {
3796856Srrh perror(fname);
3806856Srrh exit(errno);
3816856Srrh }
38216335Sralph if (rcfirst) {
38316335Sralph if (rcfirst > lastmsg+1) {
38416335Sralph printf("Warning: the last message is number %d.\n",
38516335Sralph lastmsg);
38616335Sralph rcfirst = nextmsg;
38716335Sralph }
38816335Sralph if (rcfirst > firstmsg)
38916335Sralph firstmsg = rcfirst; /* don't set below first msg */
39016335Sralph }
3916856Srrh if (newrc) {
3926856Srrh nextmsg = firstmsg;
3936856Srrh fseek(msgsrc, 0L, 0);
3946856Srrh fprintf(msgsrc, "%d\n", nextmsg);
3956856Srrh fflush(msgsrc);
3966856Srrh }
3976856Srrh
3986856Srrh #ifdef V7
3996856Srrh if (totty) {
40027026Sbloom struct winsize win;
40127026Sbloom if (ioctl(fileno(stdout), TIOCGWINSZ, &win) != -1)
40227026Sbloom Lpp = win.ws_row;
40327026Sbloom if (Lpp <= 0) {
40427026Sbloom if (tgetent(inbuf, getenv("TERM")) <= 0
40527026Sbloom || (Lpp = tgetnum("li")) <= 0) {
40627026Sbloom Lpp = NLINES;
40727026Sbloom }
4086856Srrh }
4096856Srrh }
4106856Srrh #endif
4116856Srrh Lpp -= 6; /* for headers, etc. */
4126856Srrh
4136856Srrh already = NO;
4146856Srrh prevmsg = firstmsg;
4156856Srrh printing = YES;
4166856Srrh if (ruptible)
4176856Srrh signal(SIGINT, onintr);
4186856Srrh
4196856Srrh /*
4206856Srrh * Main program loop
4216856Srrh */
4226856Srrh for (msg = firstmsg; msg <= lastmsg; msg++) {
4236856Srrh
42437893Sbostic sprintf(fname, "%s/%d", _PATH_MSGS, msg);
4256856Srrh newmsg = fopen(fname, "r");
4266856Srrh if (newmsg == NULL)
4276856Srrh continue;
4286856Srrh
4296856Srrh gfrsub(newmsg); /* get From and Subject fields */
4306856Srrh if (locomode && !local) {
4316856Srrh fclose(newmsg);
4326856Srrh continue;
4336856Srrh }
4346856Srrh
4356856Srrh if (qopt) { /* This has to be located here */
4366856Srrh printf("There are new messages.\n");
4376856Srrh exit(0);
4386856Srrh }
4396856Srrh
4406856Srrh if (already && !hdrs)
4416856Srrh putchar('\n');
4426856Srrh
4436856Srrh /*
4446856Srrh * Print header
4456856Srrh */
44611939Sleres if (totty)
44711939Sleres signal(SIGTSTP, onsusp);
44814052Ssam (void) setjmp(tstpbuf);
44946257Storek already = YES;
4506856Srrh nlines = 2;
4516856Srrh if (seenfrom) {
4526856Srrh printf("Message %d:\nFrom %s %s", msg, from, date);
4536856Srrh nlines++;
4546856Srrh }
4556856Srrh if (seensubj) {
4566856Srrh printf("Subject: %s", subj);
4576856Srrh nlines++;
4586856Srrh }
4596856Srrh else {
4606856Srrh if (seenfrom) {
4616856Srrh putchar('\n');
4626856Srrh nlines++;
4636856Srrh }
4646856Srrh while (nlines < 6
4656856Srrh && fgets(inbuf, sizeof inbuf, newmsg)
4666856Srrh && inbuf[0] != '\n') {
4676856Srrh fputs(inbuf, stdout);
4686856Srrh nlines++;
4696856Srrh }
4706856Srrh }
4716856Srrh
4726856Srrh lct = linecnt(newmsg);
4736856Srrh if (lct)
4746856Srrh printf("(%d%slines) ", lct, seensubj? " " : " more ");
4756856Srrh
4766856Srrh if (hdrs) {
4776856Srrh printf("\n-----\n");
4786856Srrh fclose(newmsg);
4796856Srrh continue;
4806856Srrh }
4816856Srrh
4826856Srrh /*
4836856Srrh * Ask user for command
4846856Srrh */
4856856Srrh if (totty)
4866856Srrh ask(lct? MORE : (msg==lastmsg? NOMORE : NEXT));
4876856Srrh else
4886856Srrh inbuf[0] = 'y';
48911939Sleres if (totty)
49011939Sleres signal(SIGTSTP, SIG_DFL);
4916856Srrh cmnd:
4926856Srrh in = inbuf;
4936856Srrh switch (*in) {
4946856Srrh case 'x':
4956856Srrh case 'X':
4966856Srrh exit(0);
4976856Srrh
4986856Srrh case 'q':
4996856Srrh case 'Q':
5006856Srrh quitit = YES;
5016856Srrh printf("--Postponed--\n");
5026856Srrh exit(0);
5036856Srrh /* intentional fall-thru */
5046856Srrh case 'n':
5056856Srrh case 'N':
5066856Srrh if (msg >= nextmsg) sep = "Flushed";
50713427Slayer prevmsg = msg;
5086856Srrh break;
5096856Srrh
5106856Srrh case 'p':
5116856Srrh case 'P':
51246160Sbostic use_pager = (*in++ == 'p');
5136856Srrh /* intentional fallthru */
5146856Srrh case '\n':
5156856Srrh case 'y':
5166856Srrh default:
5176856Srrh if (*in == '-') {
5186856Srrh msg = prevmsg-1;
5196856Srrh sep = "replay";
5206856Srrh break;
5216856Srrh }
5226856Srrh if (isdigit(*in)) {
5236856Srrh msg = next(in);
5246856Srrh sep = in;
5256856Srrh break;
5266856Srrh }
5276856Srrh
5286856Srrh prmesg(nlines + lct + (seensubj? 1 : 0));
5296856Srrh prevmsg = msg;
5306856Srrh
5316856Srrh }
5326856Srrh
5336856Srrh printf("--%s--\n", sep);
5346856Srrh sep = "-";
5356856Srrh if (msg >= nextmsg) {
5366856Srrh nextmsg = msg + 1;
5376856Srrh fseek(msgsrc, 0L, 0);
5386856Srrh fprintf(msgsrc, "%d\n", nextmsg);
5396856Srrh fflush(msgsrc);
5406856Srrh }
5416856Srrh if (newmsg)
5426856Srrh fclose(newmsg);
5436856Srrh if (quitit)
5446856Srrh break;
5456856Srrh }
5466856Srrh
54712254Sleres /*
54812254Sleres * Make sure .rc file gets updated
54912254Sleres */
55012254Sleres if (--msg >= nextmsg) {
55112254Sleres nextmsg = msg + 1;
55212254Sleres fseek(msgsrc, 0L, 0);
55312254Sleres fprintf(msgsrc, "%d\n", nextmsg);
55412254Sleres fflush(msgsrc);
55512254Sleres }
5566856Srrh if (already && !quitit && lastcmd && totty) {
5576856Srrh /*
5586856Srrh * save or reply to last message?
5596856Srrh */
5606856Srrh msg = prevmsg;
5616856Srrh ask(NOMORE);
5626856Srrh if (inbuf[0] == '-' || isdigit(inbuf[0]))
5636856Srrh goto cmnd;
5646856Srrh }
5656856Srrh if (!(already || hush || qopt))
5666856Srrh printf("No new messages.\n");
5676856Srrh exit(0);
5686856Srrh }
5696856Srrh
prmesg(length)5706856Srrh prmesg(length)
5716856Srrh int length;
5726856Srrh {
57346160Sbostic FILE *outf;
5746856Srrh
57546160Sbostic if (use_pager && length > Lpp) {
57614961Sralph signal(SIGPIPE, SIG_IGN);
57714961Sralph signal(SIGQUIT, SIG_IGN);
57837893Sbostic sprintf(cmdbuf, _PATH_PAGER, Lpp);
5796856Srrh outf = popen(cmdbuf, "w");
5806856Srrh if (!outf)
5816856Srrh outf = stdout;
5826856Srrh else
58346160Sbostic setbuf(outf, (char *)NULL);
5846856Srrh }
5856856Srrh else
5866856Srrh outf = stdout;
5876856Srrh
5886856Srrh if (seensubj)
5896856Srrh putc('\n', outf);
5906856Srrh
59114961Sralph while (fgets(inbuf, sizeof inbuf, newmsg)) {
5926856Srrh fputs(inbuf, outf);
59316076Sralph if (ferror(outf)) {
59416076Sralph clearerr(outf);
59514961Sralph break;
59616076Sralph }
59714961Sralph }
5986856Srrh
5996856Srrh if (outf != stdout) {
6006856Srrh pclose(outf);
60114961Sralph signal(SIGPIPE, SIG_DFL);
60214961Sralph signal(SIGQUIT, SIG_DFL);
6036856Srrh }
6046856Srrh else {
6056856Srrh fflush(stdout);
6066856Srrh }
6076856Srrh
6086856Srrh /* trick to force wait on output */
609*69023Sbostic tcdrain(fileno(stdout));
6106856Srrh }
6116856Srrh
61246160Sbostic void
onintr()6136856Srrh onintr()
6146856Srrh {
6156856Srrh signal(SIGINT, onintr);
6166856Srrh if (mailing)
6176856Srrh unlink(fname);
6186856Srrh if (sending) {
6196856Srrh unlink(fname);
6206856Srrh puts("--Killed--");
6216856Srrh exit(1);
6226856Srrh }
6236856Srrh if (printing) {
6246856Srrh putchar('\n');
6256856Srrh if (hdrs)
6266856Srrh exit(0);
6276856Srrh sep = "Interrupt";
6286856Srrh if (newmsg)
6296856Srrh fseek(newmsg, 0L, 2);
6306856Srrh intrpflg = YES;
6316856Srrh }
6326856Srrh }
6336856Srrh
63411939Sleres /*
63511939Sleres * We have just gotten a susp. Suspend and prepare to resume.
63611939Sleres */
63746160Sbostic void
onsusp()63811939Sleres onsusp()
63911939Sleres {
64014052Ssam
64111939Sleres signal(SIGTSTP, SIG_DFL);
64213999Ssam sigsetmask(0);
64311939Sleres kill(0, SIGTSTP);
64411939Sleres signal(SIGTSTP, onsusp);
64515689Sleres if (!mailing)
64646160Sbostic longjmp(tstpbuf, 0);
64711939Sleres }
64811939Sleres
linecnt(f)6496856Srrh linecnt(f)
6506856Srrh FILE *f;
6516856Srrh {
6526856Srrh off_t oldpos = ftell(f);
6536856Srrh int l = 0;
6546856Srrh char lbuf[BUFSIZ];
6556856Srrh
6566856Srrh while (fgets(lbuf, sizeof lbuf, f))
6576856Srrh l++;
6586856Srrh clearerr(f);
6596856Srrh fseek(f, oldpos, 0);
6606856Srrh return (l);
6616856Srrh }
6626856Srrh
next(buf)6636856Srrh next(buf)
6646856Srrh char *buf;
6656856Srrh {
6666856Srrh int i;
6676856Srrh sscanf(buf, "%d", &i);
6686856Srrh sprintf(buf, "Goto %d", i);
6696856Srrh return(--i);
6706856Srrh }
6716856Srrh
ask(prompt)6726856Srrh ask(prompt)
6736856Srrh char *prompt;
6746856Srrh {
6756856Srrh char inch;
6766856Srrh int n, cmsg;
6776856Srrh off_t oldpos;
6786856Srrh FILE *cpfrom, *cpto;
6796856Srrh
6806856Srrh printf("%s ", prompt);
6816856Srrh fflush(stdout);
6826856Srrh intrpflg = NO;
68342448Sbostic (void) fgets(inbuf, sizeof inbuf, stdin);
68442448Sbostic if ((n = strlen(inbuf)) > 0 && inbuf[n - 1] == '\n')
68542448Sbostic inbuf[n - 1] = '\0';
6866856Srrh if (intrpflg)
6876856Srrh inbuf[0] = 'x';
6886856Srrh
6896856Srrh /*
6906856Srrh * Handle 'mail' and 'save' here.
6916856Srrh */
6926856Srrh if ((inch = inbuf[0]) == 's' || inch == 'm') {
6936856Srrh if (inbuf[1] == '-')
6946856Srrh cmsg = prevmsg;
6956856Srrh else if (isdigit(inbuf[1]))
6966856Srrh cmsg = atoi(&inbuf[1]);
6976856Srrh else
6986856Srrh cmsg = msg;
69937893Sbostic sprintf(fname, "%s/%d", _PATH_MSGS, cmsg);
7006856Srrh
7016856Srrh oldpos = ftell(newmsg);
7026856Srrh
7036856Srrh cpfrom = fopen(fname, "r");
7046856Srrh if (!cpfrom) {
7056856Srrh printf("Message %d not found\n", cmsg);
7066856Srrh ask (prompt);
7076856Srrh return;
7086856Srrh }
7096856Srrh
7106856Srrh if (inch == 's') {
7116856Srrh in = nxtfld(inbuf);
7126856Srrh if (*in) {
7136856Srrh for (n=0; in[n] > ' '; n++) { /* sizeof fname? */
7146856Srrh fname[n] = in[n];
7156856Srrh }
7166856Srrh fname[n] = NULL;
7176856Srrh }
7186856Srrh else
7196856Srrh strcpy(fname, "Messages");
7206856Srrh }
7216856Srrh else {
72237893Sbostic strcpy(fname, _PATH_TMP);
7236856Srrh mktemp(fname);
72437893Sbostic sprintf(cmdbuf, _PATH_MAIL, fname);
7256856Srrh mailing = YES;
7266856Srrh }
7276856Srrh cpto = fopen(fname, "a");
7286856Srrh if (!cpto) {
7296856Srrh perror(fname);
7306856Srrh mailing = NO;
7316856Srrh fseek(newmsg, oldpos, 0);
7326856Srrh ask(prompt);
7336856Srrh return;
7346856Srrh }
7356856Srrh
7366856Srrh while (n = fread(inbuf, 1, sizeof inbuf, cpfrom))
7376856Srrh fwrite(inbuf, 1, n, cpto);
7386856Srrh
7396856Srrh fclose(cpfrom);
7406856Srrh fclose(cpto);
7416856Srrh fseek(newmsg, oldpos, 0); /* reposition current message */
7426856Srrh if (inch == 's')
7436856Srrh printf("Message %d saved in \"%s\"\n", cmsg, fname);
7446856Srrh else {
7456856Srrh system(cmdbuf);
7466856Srrh unlink(fname);
7476856Srrh mailing = NO;
7486856Srrh }
7496856Srrh ask(prompt);
7506856Srrh }
7516856Srrh }
7526856Srrh
gfrsub(infile)7536856Srrh gfrsub(infile)
7546856Srrh FILE *infile;
7556856Srrh {
7566856Srrh off_t frompos;
7576856Srrh
7586856Srrh seensubj = seenfrom = NO;
7596856Srrh local = YES;
7606856Srrh subj[0] = from[0] = date[0] = NULL;
7616856Srrh
7626856Srrh /*
7636856Srrh * Is this a normal message?
7646856Srrh */
7656856Srrh if (fgets(inbuf, sizeof inbuf, infile)) {
7666856Srrh if (strncmp(inbuf, "From", 4)==0) {
7676856Srrh /*
7686856Srrh * expected form starts with From
7696856Srrh */
7706856Srrh seenfrom = YES;
7716856Srrh frompos = ftell(infile);
7726856Srrh ptr = from;
7736856Srrh in = nxtfld(inbuf);
7746856Srrh if (*in) while (*in && *in > ' ') {
7758936Smckusick if (*in == ':' || *in == '@' || *in == '!')
7766856Srrh local = NO;
7776856Srrh *ptr++ = *in++;
7786856Srrh /* what about sizeof from ? */
7796856Srrh }
7806856Srrh *ptr = NULL;
7816856Srrh if (*(in = nxtfld(in)))
7826856Srrh strncpy(date, in, sizeof date);
7836856Srrh else {
7846856Srrh date[0] = '\n';
7856856Srrh date[1] = NULL;
7866856Srrh }
7876856Srrh }
7886856Srrh else {
7896856Srrh /*
7906856Srrh * not the expected form
7916856Srrh */
7926856Srrh fseek(infile, 0L, 0);
7936856Srrh return;
7946856Srrh }
7956856Srrh }
7966856Srrh else
7976856Srrh /*
7986856Srrh * empty file ?
7996856Srrh */
8006856Srrh return;
8016856Srrh
8026856Srrh /*
8036856Srrh * look for Subject line until EOF or a blank line
8046856Srrh */
8056856Srrh while (fgets(inbuf, sizeof inbuf, infile)
8066856Srrh && !(blankline = (inbuf[0] == '\n'))) {
8076856Srrh /*
8086856Srrh * extract Subject line
8096856Srrh */
8106856Srrh if (!seensubj && strncmp(inbuf, "Subj", 4)==0) {
8116856Srrh seensubj = YES;
8126856Srrh frompos = ftell(infile);
8136856Srrh strncpy(subj, nxtfld(inbuf), sizeof subj);
8146856Srrh }
8156856Srrh }
8166856Srrh if (!blankline)
8176856Srrh /*
8186856Srrh * ran into EOF
8196856Srrh */
8206856Srrh fseek(infile, frompos, 0);
8216856Srrh
8226856Srrh if (!seensubj)
8236856Srrh /*
8246856Srrh * for possible use with Mail
8256856Srrh */
8266856Srrh strncpy(subj, "(No Subject)\n", sizeof subj);
8276856Srrh }
8286856Srrh
8296856Srrh char *
nxtfld(s)8306856Srrh nxtfld(s)
8316856Srrh char *s;
8326856Srrh {
8336856Srrh if (*s) while (*s && *s > ' ') s++; /* skip over this field */
8346856Srrh if (*s) while (*s && *s <= ' ') s++; /* find start of next field */
8356856Srrh return (s);
8366856Srrh }
837