187ed968223a0e87feddd091d7f1a2d8ba1f8803
[unix-history] / usr / src / usr.bin / mail / cmd2.c
#
#include "rcv.h"
#include <sys/stat.h>
/*
* Mail -- a mail program
*
* More user commands.
*/
static char *SccsId = "@(#)cmd2.c 1.1 %G%";
/*
* If any arguments were given, go to the next applicable argument
* following dot, otherwise, go to the next applicable message.
* If given as first command with no arguments, print first message.
*/
next(msgvec)
int *msgvec;
{
register struct message *mp;
register int *ip, *ip2;
int list[2], mdot;
if (*msgvec != NULL) {
/*
* If some messages were supplied, find the
* first applicable one following dot using
* wrap around.
*/
mdot = dot - &message[0] + 1;
for (ip = msgvec; *ip != NULL; ip++)
if (*ip > mdot)
break;
if (*ip == NULL)
ip = msgvec;
ip2 = ip;
do {
if (*ip2 != NULL)
ip2++;
if (*ip2 == NULL)
ip2 = msgvec;
mp = &message[*ip2 - 1];
if ((mp->m_flag & MDELETED) == 0) {
dot = mp;
goto hitit;
}
} while (ip2 != ip);
printf("No messages applicable\n");
return(1);
}
/*
* If this is the first command, select message 1.
* Note that this must exist for us to get here at all.
*/
if (!sawcom) {
dot = &message[0];
goto hitit;
}
/*
* Just find the next good message after dot, no
* wraparound.
*/
for (mp = dot+1; mp < &message[msgCount]; mp++)
if ((mp->m_flag & (MDELETED|MSAVED)) == 0)
break;
if (mp >= &message[msgCount]) {
printf("At EOF\n");
return(0);
}
dot = mp;
hitit:
/*
* Print dot.
*/
list[0] = dot - &message[0] + 1;
list[1] = NULL;
return(type(list));
}
/*
* Save the indicated messages at the end of the passed file name.
*/
save(str)
char str[];
{
register int *ip, mesg;
register struct message *mp;
char *file, *disp;
int f, *msgvec, lc, cc, t;
FILE *obuf;
struct stat statb;
msgvec = (int *) salloc((msgCount + 2) * sizeof *msgvec);
if ((file = snarf(str, &f)) == NOSTR)
return(1);
if (!f) {
*msgvec = first(0, MMNORM);
if (*msgvec == NULL) {
printf("No messages to save.\n");
return(1);
}
msgvec[1] = NULL;
}
if (f && getmsglist(str, msgvec, 0) < 0)
return(1);
if ((file = expand(file)) == NOSTR)
return(1);
printf("\"%s\" ", file);
flush();
if (stat(file, &statb) >= 0)
disp = "[Appended]";
else
disp = "[New file]";
if ((obuf = fopen(file, "a")) == NULL) {
perror(NOSTR);
return(1);
}
cc = lc = 0;
for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) {
mesg = *ip;
touch(mesg);
mp = &message[mesg-1];
if ((t = send(mp, obuf)) < 0) {
perror(file);
fclose(obuf);
return(1);
}
lc += t;
cc += msize(mp);
mp->m_flag |= MSAVED;
}
fflush(obuf);
if (ferror(obuf))
perror(file);
fclose(obuf);
printf("%s %d/%d\n", disp, lc, cc);
return(0);
}
/*
* Write the indicated messages at the end of the passed
* file name, minus header and trailing blank line.
*/
swrite(str)
char str[];
{
register int *ip, mesg;
register struct message *mp;
register char *file, *disp;
char linebuf[BUFSIZ];
int f, *msgvec, lc, cc, t;
FILE *obuf, *mesf;
struct stat statb;
msgvec = (int *) salloc((msgCount + 2) * sizeof *msgvec);
if ((file = snarf(str, &f)) == NOSTR)
return(1);
if ((file = expand(file)) == NOSTR)
return(1);
if (!f) {
*msgvec = first(0, MMNORM);
if (*msgvec == NULL) {
printf("No messages to write.\n");
return(1);
}
msgvec[1] = NULL;
}
if (f && getmsglist(str, msgvec, 0) < 0)
return(1);
printf("\"%s\" ", file);
flush();
if (stat(file, &statb) >= 0)
disp = "[Appended]";
else
disp = "[New file]";
if ((obuf = fopen(file, "a")) == NULL) {
perror(NOSTR);
return(1);
}
cc = lc = 0;
for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) {
mesg = *ip;
touch(mesg);
mp = &message[mesg-1];
mesf = setinput(mp);
t = mp->m_lines - 2;
readline(mesf, linebuf);
while (t-- > 0) {
fgets(linebuf, BUFSIZ, mesf);
fputs(linebuf, obuf);
cc += strlen(linebuf);
}
lc += mp->m_lines - 2;
mp->m_flag |= MSAVED;
}
fflush(obuf);
if (ferror(obuf))
perror(file);
fclose(obuf);
printf("%s %d/%d\n", disp, lc, cc);
return(0);
}
/*
* Snarf the file from the end of the command line and
* return a pointer to it. If there is no file attached,
* just return NOSTR. Put a null in front of the file
* name so that the message list processing won't see it,
* unless the file name is the only thing on the line, in
* which case, return 0 in the reference flag variable.
*/
char *
snarf(linebuf, flag)
char linebuf[];
int *flag;
{
register char *cp;
*flag = 1;
cp = strlen(linebuf) + linebuf - 1;
/*
* Strip away trailing blanks.
*/
while (*cp == ' ' && cp > linebuf)
cp--;
*++cp = 0;
/*
* Now search for the beginning of the file name.
*/
while (cp > linebuf && !any(*cp, "\t "))
cp--;
if (*cp == '\0') {
printf("No file specified.\n");
return(NOSTR);
}
if (any(*cp, " \t"))
*cp++ = 0;
else
*flag = 0;
return(cp);
}
/*
* Delete messages.
*/
delete(msgvec)
int msgvec[];
{
return(delm(msgvec));
}
/*
* Delete messages, then type the new dot.
*/
deltype(msgvec)
int msgvec[];
{
int list[2];
if (delm(msgvec) >= 0) {
list[0] = dot - &message[0];
list[0]++;
touch(list[0]);
list[1] = NULL;
return(type(list));
}
else {
printf("No more messages\n");
return(0);
}
}
/*
* Delete the indicated messages.
* Set dot to some nice place afterwards.
* Internal interface.
*/
delm(msgvec)
int *msgvec;
{
register struct message *mp;
register *ip, mesg;
int last;
last = NULL;
for (ip = msgvec; *ip != NULL; ip++) {
mesg = *ip;
touch(mesg);
mp = &message[mesg-1];
mp->m_flag |= MDELETED;
mp->m_flag &= ~(MPRESERVE|MSAVED);
last = mesg;
}
if (last != NULL) {
dot = &message[last-1];
last = first(0, MDELETED);
if (last != NULL) {
dot = &message[last-1];
return(0);
}
else {
dot = &message[0];
return(-1);
}
}
/*
* Following can't happen -- it keeps lint happy
*/
return(-1);
}
/*
* Undelete the indicated messages.
*/
undelete(msgvec)
int *msgvec;
{
register struct message *mp;
register *ip, mesg;
for (ip = msgvec; ip-msgvec < msgCount; ip++) {
mesg = *ip;
if (mesg == 0)
return;
touch(mesg);
mp = &message[mesg-1];
dot = mp;
mp->m_flag &= ~MDELETED;
}
}
/*
* Interactively dump core on "core"
*/
core()
{
register int pid;
int status;
if ((pid = vfork()) == -1) {
perror("fork");
return(1);
}
if (pid == 0) {
abort();
_exit(1);
}
printf("Okie dokie");
fflush(stdout);
while (wait(&status) != pid)
;
if (status & 0200)
printf(" -- Core dumped\n");
else
printf("\n");
}