diff options
Diffstat (limited to 'usr.bin/msgs')
-rw-r--r-- | usr.bin/msgs/Makefile | 7 | ||||
-rw-r--r-- | usr.bin/msgs/msgs.1 | 214 | ||||
-rw-r--r-- | usr.bin/msgs/msgs.c | 863 | ||||
-rw-r--r-- | usr.bin/msgs/pathnames.h | 40 |
4 files changed, 1124 insertions, 0 deletions
diff --git a/usr.bin/msgs/Makefile b/usr.bin/msgs/Makefile new file mode 100644 index 0000000..09ef68d --- /dev/null +++ b/usr.bin/msgs/Makefile @@ -0,0 +1,7 @@ +# @(#)Makefile 8.1 (Berkeley) 6/6/93 + +PROG= msgs +DPADD= ${LIBTERM} ${LIBCOMPAT} +LDADD= -ltermlib -lcompat + +.include <bsd.prog.mk> diff --git a/usr.bin/msgs/msgs.1 b/usr.bin/msgs/msgs.1 new file mode 100644 index 0000000..87d826a --- /dev/null +++ b/usr.bin/msgs/msgs.1 @@ -0,0 +1,214 @@ +.\" Copyright (c) 1980, 1990, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)msgs.1 8.1 (Berkeley) 6/6/93 +.\" +.Dd June 6, 1993 +.Dt MSGS 1 +.Os BSD 4 +.Sh NAME +.Nm msgs +.Nd system messages and junk mail program +.Sh SYNOPSIS +.Nm msgs +.Op Fl fhlpq +.Op Ar number +.Op Ar \-number +.Nm msgs +.Op Fl s +.Nm msgs +.Op Fl c +.Op \-days +.Sh DESCRIPTION +.Nm Msgs +is used to read system messages. +These messages are +sent by mailing to the login `msgs' and should be short +pieces of information which are suitable to be read once by most users +of the system. +.Pp +.Nm Msgs +is normally invoked each time you login, by placing it in the file +.Pa .login +(or +.Pa .profile +if you use +.Xr sh 1 ) . +It will then prompt you with the source and subject of each new message. +If there is no subject line, the first few non-blank lines of the +message will be displayed. +If there is more to the message, you will be told how +long it is and asked whether you wish to see the rest of the message. +The possible responses are: +.Bl -tag -width Fl +.It Fl y +Type the rest of the message. +.It Ic RETURN +Synonym for y. +.It Fl n +Skip this message +and go on to the next message. +.It Fl +Redisplay the last message. +.It Fl q +Drop out of +.Nm msgs ; +the next time +.Nm msgs +will pick up where it last left off. +.It Fl s +Append the current message to the file ``Messages'' in the current directory; +`s\-' will save the previously displayed message. A `s' or `s\-' may +be followed by a space and a file name to receive the message replacing +the default ``Messages''. +.It Fl m +A copy of the specified message is placed in a temporary +mailbox and +.Xr mail 1 +is invoked on that mailbox. +Both `m' and `s' accept a numeric argument in place of the `\-'. +.El +.Pp +.Nm Msgs +keeps track of the next message you will see by a number in the file +.Pa \&.msgsrc +in your home directory. +In the directory +.Pa /var/msgs +it keeps a set of files whose names are the (sequential) numbers +of the messages they represent. +The file +.Pa /var/msgs/bounds +shows the low and high number of the messages in the directory +so that +.Nm msgs +can quickly determine if there are no messages for you. +If the contents of +.Pa bounds +is incorrect it can be fixed by removing it; +.Nm msgs +will make a new +.Pa bounds +file the next time it is run. +.Pp +The +.Fl s +option is used for setting up the posting of messages. The line +.Pp +.Dl msgs: \&"\&| /usr/ucb/msgs \-s\&" +.Pp +should be included in +.Pa /etc/aliases +(see +.Xr newaliases 1 ) +to enable posting of messages. +.Pp +The +.Fl c +option is used for performing cleanup on +.Pa /var/msgs. +An entry with the +.Fl c +option should be placed in +.Pa /etc/crontab +to run every night. This will remove all messages over 21 days old. +A different expiration may be specified on the command line to override +the default. +.Pp +Options when reading messages include: +.Bl -tag -width Fl +.It Fl f +Do not to say ``No new messages.''. +This is useful in a +.Pa .login +file since this is often the case here. +.It Fl q +Queries whether there are messages, printing +``There are new messages.'' if there are. +The command ``msgs \-q'' is often used in login scripts. +.It Fl h +Print the first part of messages only. +.It Fl l +Option causes only locally originated messages to be reported. +.It Ar num +A message number can be given +on the command line, causing +.Nm msgs +to start at the specified message rather than at the next message +indicated by your +.Pa \&.msgsrc +file. +Thus +.Pp +.Dl msgs \-h 1 +.Pp +prints the first part of all messages. +.It Ar \-number +Start +.Ar number +messages back from the one indicated in the +.Pa \&.msgsrc +file, useful for reviews of recent messages. +.It Fl p +Pipe long messages through +.Xr more 1 . +.El +.Pp +Within +.Nm msgs +you can also go to any specific message by typing its number when +.Nm msgs +requests input as to what to do. +.Sh ENVIRONMENT +.Nm Msgs +uses the +.Ev HOME +and +.Ev TERM +environment variables for the default home directory and +terminal type. +.Sh FILES +.Bl -tag -width /usr/msgs/* -compact +.It Pa /usr/msgs/* +database +.It ~/.msgsrc +number of next message to be presented +.El +.Sh SEE ALSO +.Xr aliases 5 , +.\".Xr crontab 5 , +.Xr mail 1 , +.Xr more 1 +.Sh HISTORY +The +.Nm msgs +command appeared in +.Bx 3.0 . diff --git a/usr.bin/msgs/msgs.c b/usr.bin/msgs/msgs.c new file mode 100644 index 0000000..9a5311a --- /dev/null +++ b/usr.bin/msgs/msgs.c @@ -0,0 +1,863 @@ +/*- + * Copyright (c) 1980, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1980, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)msgs.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ + +/* + * msgs - a user bulletin board program + * + * usage: + * msgs [fhlopq] [[-]number] to read messages + * msgs -s to place messages + * msgs -c [-days] to clean up the bulletin board + * + * prompt commands are: + * y print message + * n flush message, go to next message + * q flush message, quit + * p print message, turn on 'pipe thru more' mode + * P print message, turn off 'pipe thru more' mode + * - reprint last message + * s[-][<num>] [<filename>] save message + * m[-][<num>] mail with message in temp mbox + * x exit without flushing this message + * <num> print message number <num> + */ + +#define V7 /* will look for TERM in the environment */ +#define OBJECT /* will object to messages without Subjects */ +/* #define REJECT /* will reject messages without Subjects + (OBJECT must be defined also) */ +/* #define UNBUFFERED /* use unbuffered output */ + +#include <sys/param.h> +#include <sys/dir.h> +#include <sys/stat.h> +#include <ctype.h> +#include <errno.h> +#include <pwd.h> +#include <setjmp.h> +#include <sgtty.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <unistd.h> +#include "pathnames.h" + +#define CMODE 0666 /* bounds file creation mode */ +#define NO 0 +#define YES 1 +#define SUPERUSER 0 /* superuser uid */ +#define DAEMON 1 /* daemon uid */ +#define NLINES 24 /* default number of lines/crt screen */ +#define NDAYS 21 /* default keep time for messages */ +#define DAYS *24*60*60 /* seconds/day */ +#define MSGSRC ".msgsrc" /* user's rc file */ +#define BOUNDS "bounds" /* message bounds file */ +#define NEXT "Next message? [yq]" +#define MORE "More? [ynq]" +#define NOMORE "(No more) [q] ?" + +typedef char bool; + +FILE *msgsrc; +FILE *newmsg; +char *sep = "-"; +char inbuf[BUFSIZ]; +char fname[128]; +char cmdbuf[128]; +char subj[128]; +char from[128]; +char date[128]; +char *ptr; +char *in; +bool local; +bool ruptible; +bool totty; +bool seenfrom; +bool seensubj; +bool blankline; +bool printing = NO; +bool mailing = NO; +bool quitit = NO; +bool sending = NO; +bool intrpflg = NO; +int uid; +int msg; +int prevmsg; +int lct; +int nlines; +int Lpp = 0; +time_t t; +time_t keep; +struct sgttyb otty; + +char *mktemp(); +char *nxtfld(); +void onintr(); +void onsusp(); + +/* option initialization */ +bool hdrs = NO; +bool qopt = NO; +bool hush = NO; +bool send_msg = NO; +bool locomode = NO; +bool use_pager = NO; +bool clean = NO; +bool lastcmd = NO; +jmp_buf tstpbuf; + +main(argc, argv) +int argc; char *argv[]; +{ + bool newrc, already; + int rcfirst = 0; /* first message to print (from .rc) */ + int rcback = 0; /* amount to back off of rcfirst */ + int firstmsg, nextmsg, lastmsg = 0; + int blast = 0; + FILE *bounds; + +#ifdef UNBUFFERED + setbuf(stdout, NULL); +#endif + + gtty(fileno(stdout), &otty); + time(&t); + setuid(uid = getuid()); + ruptible = (signal(SIGINT, SIG_IGN) == SIG_DFL); + if (ruptible) + signal(SIGINT, SIG_DFL); + + argc--, argv++; + while (argc > 0) { + if (isdigit(argv[0][0])) { /* starting message # */ + rcfirst = atoi(argv[0]); + } + else if (isdigit(argv[0][1])) { /* backward offset */ + rcback = atoi( &( argv[0][1] ) ); + } + else { + ptr = *argv; + while (*ptr) switch (*ptr++) { + + case '-': + break; + + case 'c': + if (uid != SUPERUSER && uid != DAEMON) { + fprintf(stderr, "Sorry\n"); + exit(1); + } + clean = YES; + break; + + case 'f': /* silently */ + hush = YES; + break; + + case 'h': /* headers only */ + hdrs = YES; + break; + + case 'l': /* local msgs only */ + locomode = YES; + break; + + case 'o': /* option to save last message */ + lastcmd = YES; + break; + + case 'p': /* pipe thru 'more' during long msgs */ + use_pager = YES; + break; + + case 'q': /* query only */ + qopt = YES; + break; + + case 's': /* sending TO msgs */ + send_msg = YES; + break; + + default: + fprintf(stderr, + "usage: msgs [fhlopq] [[-]number]\n"); + exit(1); + } + } + argc--, argv++; + } + + /* + * determine current message bounds + */ + sprintf(fname, "%s/%s", _PATH_MSGS, BOUNDS); + bounds = fopen(fname, "r"); + + if (bounds != NULL) { + fscanf(bounds, "%d %d\n", &firstmsg, &lastmsg); + fclose(bounds); + blast = lastmsg; /* save upper bound */ + } + + if (clean) + keep = t - (rcback? rcback : NDAYS) DAYS; + + if (clean || bounds == NULL) { /* relocate message bounds */ + struct direct *dp; + struct stat stbuf; + bool seenany = NO; + DIR *dirp; + + dirp = opendir(_PATH_MSGS); + if (dirp == NULL) { + perror(_PATH_MSGS); + exit(errno); + } + + firstmsg = 32767; + lastmsg = 0; + + for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)){ + register char *cp = dp->d_name; + register int i = 0; + + if (dp->d_ino == 0) + continue; + if (dp->d_namlen == 0) + continue; + + if (clean) + sprintf(inbuf, "%s/%s", _PATH_MSGS, cp); + + while (isdigit(*cp)) + i = i * 10 + *cp++ - '0'; + if (*cp) + continue; /* not a message! */ + + if (clean) { + if (stat(inbuf, &stbuf) != 0) + continue; + if (stbuf.st_mtime < keep + && stbuf.st_mode&S_IWRITE) { + unlink(inbuf); + continue; + } + } + + if (i > lastmsg) + lastmsg = i; + if (i < firstmsg) + firstmsg = i; + seenany = YES; + } + closedir(dirp); + + if (!seenany) { + if (blast != 0) /* never lower the upper bound! */ + lastmsg = blast; + firstmsg = lastmsg + 1; + } + else if (blast > lastmsg) + lastmsg = blast; + + if (!send_msg) { + bounds = fopen(fname, "w"); + if (bounds == NULL) { + perror(fname); + exit(errno); + } + chmod(fname, CMODE); + fprintf(bounds, "%d %d\n", firstmsg, lastmsg); + fclose(bounds); + } + } + + if (send_msg) { + /* + * Send mode - place msgs in _PATH_MSGS + */ + bounds = fopen(fname, "w"); + if (bounds == NULL) { + perror(fname); + exit(errno); + } + + nextmsg = lastmsg + 1; + sprintf(fname, "%s/%d", _PATH_MSGS, nextmsg); + newmsg = fopen(fname, "w"); + if (newmsg == NULL) { + perror(fname); + exit(errno); + } + chmod(fname, 0644); + + fprintf(bounds, "%d %d\n", firstmsg, nextmsg); + fclose(bounds); + + sending = YES; + if (ruptible) + signal(SIGINT, onintr); + + if (isatty(fileno(stdin))) { + ptr = getpwuid(uid)->pw_name; + printf("Message %d:\nFrom %s %sSubject: ", + nextmsg, ptr, ctime(&t)); + fflush(stdout); + fgets(inbuf, sizeof inbuf, stdin); + putchar('\n'); + fflush(stdout); + fprintf(newmsg, "From %s %sSubject: %s\n", + ptr, ctime(&t), inbuf); + blankline = seensubj = YES; + } + else + blankline = seensubj = NO; + for (;;) { + fgets(inbuf, sizeof inbuf, stdin); + if (feof(stdin) || ferror(stdin)) + break; + blankline = (blankline || (inbuf[0] == '\n')); + seensubj = (seensubj || (!blankline && (strncmp(inbuf, "Subj", 4) == 0))); + fputs(inbuf, newmsg); + } +#ifdef OBJECT + if (!seensubj) { + printf("NOTICE: Messages should have a Subject field!\n"); +#ifdef REJECT + unlink(fname); +#endif + exit(1); + } +#endif + exit(ferror(stdin)); + } + if (clean) + exit(0); + + /* + * prepare to display messages + */ + totty = (isatty(fileno(stdout)) != 0); + use_pager = use_pager && totty; + + sprintf(fname, "%s/%s", getenv("HOME"), MSGSRC); + msgsrc = fopen(fname, "r"); + if (msgsrc) { + newrc = NO; + fscanf(msgsrc, "%d\n", &nextmsg); + fclose(msgsrc); + if (nextmsg > lastmsg+1) { + printf("Warning: bounds have been reset (%d, %d)\n", + firstmsg, lastmsg); + truncate(fname, (off_t)0); + newrc = YES; + } + else if (!rcfirst) + rcfirst = nextmsg - rcback; + } + else + newrc = YES; + msgsrc = fopen(fname, "r+"); + if (msgsrc == NULL) + msgsrc = fopen(fname, "w"); + if (msgsrc == NULL) { + perror(fname); + exit(errno); + } + if (rcfirst) { + if (rcfirst > lastmsg+1) { + printf("Warning: the last message is number %d.\n", + lastmsg); + rcfirst = nextmsg; + } + if (rcfirst > firstmsg) + firstmsg = rcfirst; /* don't set below first msg */ + } + if (newrc) { + nextmsg = firstmsg; + fseek(msgsrc, 0L, 0); + fprintf(msgsrc, "%d\n", nextmsg); + fflush(msgsrc); + } + +#ifdef V7 + if (totty) { + struct winsize win; + if (ioctl(fileno(stdout), TIOCGWINSZ, &win) != -1) + Lpp = win.ws_row; + if (Lpp <= 0) { + if (tgetent(inbuf, getenv("TERM")) <= 0 + || (Lpp = tgetnum("li")) <= 0) { + Lpp = NLINES; + } + } + } +#endif + Lpp -= 6; /* for headers, etc. */ + + already = NO; + prevmsg = firstmsg; + printing = YES; + if (ruptible) + signal(SIGINT, onintr); + + /* + * Main program loop + */ + for (msg = firstmsg; msg <= lastmsg; msg++) { + + sprintf(fname, "%s/%d", _PATH_MSGS, msg); + newmsg = fopen(fname, "r"); + if (newmsg == NULL) + continue; + + gfrsub(newmsg); /* get From and Subject fields */ + if (locomode && !local) { + fclose(newmsg); + continue; + } + + if (qopt) { /* This has to be located here */ + printf("There are new messages.\n"); + exit(0); + } + + if (already && !hdrs) + putchar('\n'); + + /* + * Print header + */ + if (totty) + signal(SIGTSTP, onsusp); + (void) setjmp(tstpbuf); + already = YES; + nlines = 2; + if (seenfrom) { + printf("Message %d:\nFrom %s %s", msg, from, date); + nlines++; + } + if (seensubj) { + printf("Subject: %s", subj); + nlines++; + } + else { + if (seenfrom) { + putchar('\n'); + nlines++; + } + while (nlines < 6 + && fgets(inbuf, sizeof inbuf, newmsg) + && inbuf[0] != '\n') { + fputs(inbuf, stdout); + nlines++; + } + } + + lct = linecnt(newmsg); + if (lct) + printf("(%d%slines) ", lct, seensubj? " " : " more "); + + if (hdrs) { + printf("\n-----\n"); + fclose(newmsg); + continue; + } + + /* + * Ask user for command + */ + if (totty) + ask(lct? MORE : (msg==lastmsg? NOMORE : NEXT)); + else + inbuf[0] = 'y'; + if (totty) + signal(SIGTSTP, SIG_DFL); +cmnd: + in = inbuf; + switch (*in) { + case 'x': + case 'X': + exit(0); + + case 'q': + case 'Q': + quitit = YES; + printf("--Postponed--\n"); + exit(0); + /* intentional fall-thru */ + case 'n': + case 'N': + if (msg >= nextmsg) sep = "Flushed"; + prevmsg = msg; + break; + + case 'p': + case 'P': + use_pager = (*in++ == 'p'); + /* intentional fallthru */ + case '\n': + case 'y': + default: + if (*in == '-') { + msg = prevmsg-1; + sep = "replay"; + break; + } + if (isdigit(*in)) { + msg = next(in); + sep = in; + break; + } + + prmesg(nlines + lct + (seensubj? 1 : 0)); + prevmsg = msg; + + } + + printf("--%s--\n", sep); + sep = "-"; + if (msg >= nextmsg) { + nextmsg = msg + 1; + fseek(msgsrc, 0L, 0); + fprintf(msgsrc, "%d\n", nextmsg); + fflush(msgsrc); + } + if (newmsg) + fclose(newmsg); + if (quitit) + break; + } + + /* + * Make sure .rc file gets updated + */ + if (--msg >= nextmsg) { + nextmsg = msg + 1; + fseek(msgsrc, 0L, 0); + fprintf(msgsrc, "%d\n", nextmsg); + fflush(msgsrc); + } + if (already && !quitit && lastcmd && totty) { + /* + * save or reply to last message? + */ + msg = prevmsg; + ask(NOMORE); + if (inbuf[0] == '-' || isdigit(inbuf[0])) + goto cmnd; + } + if (!(already || hush || qopt)) + printf("No new messages.\n"); + exit(0); +} + +prmesg(length) +int length; +{ + FILE *outf; + + if (use_pager && length > Lpp) { + signal(SIGPIPE, SIG_IGN); + signal(SIGQUIT, SIG_IGN); + sprintf(cmdbuf, _PATH_PAGER, Lpp); + outf = popen(cmdbuf, "w"); + if (!outf) + outf = stdout; + else + setbuf(outf, (char *)NULL); + } + else + outf = stdout; + + if (seensubj) + putc('\n', outf); + + while (fgets(inbuf, sizeof inbuf, newmsg)) { + fputs(inbuf, outf); + if (ferror(outf)) { + clearerr(outf); + break; + } + } + + if (outf != stdout) { + pclose(outf); + signal(SIGPIPE, SIG_DFL); + signal(SIGQUIT, SIG_DFL); + } + else { + fflush(stdout); + } + + /* trick to force wait on output */ + stty(fileno(stdout), &otty); +} + +void +onintr() +{ + signal(SIGINT, onintr); + if (mailing) + unlink(fname); + if (sending) { + unlink(fname); + puts("--Killed--"); + exit(1); + } + if (printing) { + putchar('\n'); + if (hdrs) + exit(0); + sep = "Interrupt"; + if (newmsg) + fseek(newmsg, 0L, 2); + intrpflg = YES; + } +} + +/* + * We have just gotten a susp. Suspend and prepare to resume. + */ +void +onsusp() +{ + + signal(SIGTSTP, SIG_DFL); + sigsetmask(0); + kill(0, SIGTSTP); + signal(SIGTSTP, onsusp); + if (!mailing) + longjmp(tstpbuf, 0); +} + +linecnt(f) +FILE *f; +{ + off_t oldpos = ftell(f); + int l = 0; + char lbuf[BUFSIZ]; + + while (fgets(lbuf, sizeof lbuf, f)) + l++; + clearerr(f); + fseek(f, oldpos, 0); + return (l); +} + +next(buf) +char *buf; +{ + int i; + sscanf(buf, "%d", &i); + sprintf(buf, "Goto %d", i); + return(--i); +} + +ask(prompt) +char *prompt; +{ + char inch; + int n, cmsg; + off_t oldpos; + FILE *cpfrom, *cpto; + + printf("%s ", prompt); + fflush(stdout); + intrpflg = NO; + (void) fgets(inbuf, sizeof inbuf, stdin); + if ((n = strlen(inbuf)) > 0 && inbuf[n - 1] == '\n') + inbuf[n - 1] = '\0'; + if (intrpflg) + inbuf[0] = 'x'; + + /* + * Handle 'mail' and 'save' here. + */ + if ((inch = inbuf[0]) == 's' || inch == 'm') { + if (inbuf[1] == '-') + cmsg = prevmsg; + else if (isdigit(inbuf[1])) + cmsg = atoi(&inbuf[1]); + else + cmsg = msg; + sprintf(fname, "%s/%d", _PATH_MSGS, cmsg); + + oldpos = ftell(newmsg); + + cpfrom = fopen(fname, "r"); + if (!cpfrom) { + printf("Message %d not found\n", cmsg); + ask (prompt); + return; + } + + if (inch == 's') { + in = nxtfld(inbuf); + if (*in) { + for (n=0; in[n] > ' '; n++) { /* sizeof fname? */ + fname[n] = in[n]; + } + fname[n] = NULL; + } + else + strcpy(fname, "Messages"); + } + else { + strcpy(fname, _PATH_TMP); + mktemp(fname); + sprintf(cmdbuf, _PATH_MAIL, fname); + mailing = YES; + } + cpto = fopen(fname, "a"); + if (!cpto) { + perror(fname); + mailing = NO; + fseek(newmsg, oldpos, 0); + ask(prompt); + return; + } + + while (n = fread(inbuf, 1, sizeof inbuf, cpfrom)) + fwrite(inbuf, 1, n, cpto); + + fclose(cpfrom); + fclose(cpto); + fseek(newmsg, oldpos, 0); /* reposition current message */ + if (inch == 's') + printf("Message %d saved in \"%s\"\n", cmsg, fname); + else { + system(cmdbuf); + unlink(fname); + mailing = NO; + } + ask(prompt); + } +} + +gfrsub(infile) +FILE *infile; +{ + off_t frompos; + + seensubj = seenfrom = NO; + local = YES; + subj[0] = from[0] = date[0] = NULL; + + /* + * Is this a normal message? + */ + if (fgets(inbuf, sizeof inbuf, infile)) { + if (strncmp(inbuf, "From", 4)==0) { + /* + * expected form starts with From + */ + seenfrom = YES; + frompos = ftell(infile); + ptr = from; + in = nxtfld(inbuf); + if (*in) while (*in && *in > ' ') { + if (*in == ':' || *in == '@' || *in == '!') + local = NO; + *ptr++ = *in++; + /* what about sizeof from ? */ + } + *ptr = NULL; + if (*(in = nxtfld(in))) + strncpy(date, in, sizeof date); + else { + date[0] = '\n'; + date[1] = NULL; + } + } + else { + /* + * not the expected form + */ + fseek(infile, 0L, 0); + return; + } + } + else + /* + * empty file ? + */ + return; + + /* + * look for Subject line until EOF or a blank line + */ + while (fgets(inbuf, sizeof inbuf, infile) + && !(blankline = (inbuf[0] == '\n'))) { + /* + * extract Subject line + */ + if (!seensubj && strncmp(inbuf, "Subj", 4)==0) { + seensubj = YES; + frompos = ftell(infile); + strncpy(subj, nxtfld(inbuf), sizeof subj); + } + } + if (!blankline) + /* + * ran into EOF + */ + fseek(infile, frompos, 0); + + if (!seensubj) + /* + * for possible use with Mail + */ + strncpy(subj, "(No Subject)\n", sizeof subj); +} + +char * +nxtfld(s) +char *s; +{ + if (*s) while (*s && *s > ' ') s++; /* skip over this field */ + if (*s) while (*s && *s <= ' ') s++; /* find start of next field */ + return (s); +} diff --git a/usr.bin/msgs/pathnames.h b/usr.bin/msgs/pathnames.h new file mode 100644 index 0000000..90f23f4 --- /dev/null +++ b/usr.bin/msgs/pathnames.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)pathnames.h 8.1 (Berkeley) 6/6/93 + */ + +#define _PATH_MSGS "/var/msgs" +#define _PATH_MAIL "/usr/bin/Mail -f %s" +#define _PATH_PAGER "/usr/bin/more -%d" +#undef _PATH_TMP +#define _PATH_TMP "/tmp/msgXXXXXX" |