#include "rcv.h"
#include <locale.h>
static int igshow(void);
static int igcomp(const void *l, const void *r);
static int save1(char str[], int mark);
static int Save1(int *msgvec, int mark);
static void savemsglist(char *file, int *msgvec, int flag);
static int put1(char str[], int doign);
static int svputs(const char *line, FILE *obuf);
static int wrputs(const char *line, FILE *obuf);
static int retshow(void);
#define S_MARK 1
#define S_NOHEADER 2
#define S_SAVING 4
#define S_NOIGNORE 8
int
next(int *msgvec)
{
register struct message *mp;
int list[2];
if (*msgvec != 0) {
if (*msgvec < 0) {
printf((gettext("Negative message given\n")));
return (1);
}
mp = &message[*msgvec - 1];
if ((mp->m_flag & MDELETED) == 0) {
dot = mp;
goto hitit;
}
printf(gettext("No applicable message\n"));
return (1);
}
if (!sawcom)
goto hitit;
for (mp = dot+1; mp < &message[msgCount]; mp++)
if ((mp->m_flag & (MDELETED|MSAVED)) == 0)
break;
if (mp >= &message[msgCount]) {
printf(gettext("At EOF\n"));
return (0);
}
dot = mp;
hitit:
list[0] = dot - &message[0] + 1;
list[1] = 0;
return (type(list));
}
int
save(char str[])
{
return (save1(str, S_MARK));
}
int
copycmd(char str[])
{
return (save1(str, 0));
}
static int
save1(char str[], int mark)
{
char *file, *cmd;
int f, *msgvec;
cmd = mark ? "save" : "copy";
msgvec = (int *)salloc((msgCount + 2) * sizeof (*msgvec));
if ((file = snarf(str, &f, 0)) == NOSTR)
file = Getf("MBOX");
if (f == -1)
return (1);
if (!f) {
*msgvec = first(0, MMNORM);
if (*msgvec == 0) {
printf(gettext("No messages to %s.\n"), cmd);
return (1);
}
msgvec[1] = 0;
}
if (f && getmsglist(str, msgvec, 0) < 0)
return (1);
if ((file = expand(file)) == NOSTR)
return (1);
savemsglist(file, msgvec, mark | S_SAVING);
return (0);
}
int
Save(int *msgvec)
{
return (Save1(msgvec, S_MARK));
}
int
Copy(int *msgvec)
{
return (Save1(msgvec, 0));
}
static int
Save1(int *msgvec, int mark)
{
register char *from;
char recfile[BUFSIZ];
#ifdef notdef
from = striphosts(nameof(&message[*msgvec-1], 0));
#else
from = nameof(&message[*msgvec-1]);
#endif
getrecf(from, recfile, 1, sizeof (recfile));
if (*recfile != '\0')
savemsglist(safeexpand(recfile), msgvec, mark | S_SAVING);
return (0);
}
int
sput(char str[])
{
return (put1(str, 0));
}
int
Sput(char str[])
{
return (put1(str, S_NOIGNORE));
}
static int
put1(char str[], int doign)
{
char *file;
int f, *msgvec;
msgvec = (int *)salloc((msgCount + 2) * sizeof (*msgvec));
if ((file = snarf(str, &f, 0)) == NOSTR)
file = Getf("MBOX");
if (f == -1)
return (1);
if (!f) {
*msgvec = first(0, MMNORM);
if (*msgvec == 0) {
printf(gettext("No messages to put.\n"));
return (1);
}
msgvec[1] = 0;
}
if (f && getmsglist(str, msgvec, 0) < 0)
return (1);
if ((file = expand(file)) == NOSTR)
return (1);
savemsglist(file, msgvec, doign);
return (0);
}
static int wr_linecount;
static int wr_charcount;
static int wr_inlines;
static long wr_maxlines;
static int wr_inhead;
static void
savemsglist(char *file, int *msgvec, int flag)
{
register int *ip, mesg;
register struct message *mp;
char *disp;
FILE *obuf;
struct stat statb;
long lc, cc, t;
int bnry, mflag;
printf("\"%s\" ", file);
flush();
if (stat(file, &statb) >= 0)
disp = "[Appended]";
else
disp = "[New file]";
if ((obuf = fopen(file, "a")) == NULL) {
perror("");
return;
}
lc = cc = 0;
bnry = 0;
if (flag & S_SAVING)
mflag = (int)value("alwaysignore")?(M_IGNORE|M_SAVING):M_SAVING;
else if (flag & S_NOIGNORE)
mflag = 0;
else
mflag = M_IGNORE;
for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) {
mesg = *ip;
mp = &message[mesg-1];
if (!mp->m_text) {
bnry = 1;
}
wr_linecount = 0;
wr_charcount = 0;
if (flag & S_NOHEADER) {
wr_inhead = 1;
wr_maxlines = mp->m_lines;
wr_inlines = 0;
t = msend(mp, obuf, 0, wrputs);
} else {
t = msend(mp, obuf, mflag, svputs);
}
if (t < 0) {
perror(file);
fclose(obuf);
return;
}
touch(mesg);
dot = mp;
lc += wr_linecount;
cc += wr_charcount;
if (flag & S_MARK)
mp->m_flag |= MSAVED;
}
fflush(obuf);
if (fferror(obuf))
perror(file);
fclose(obuf);
if (!bnry) {
printf("%s %ld/%ld\n", disp, lc, cc);
} else {
printf("%s binary/%ld\n", disp, cc);
}
}
static int
svputs(const char *line, FILE *obuf)
{
wr_linecount++;
wr_charcount += strlen(line);
return (fputs(line, obuf));
}
static int
wrputs(const char *line, FILE *obuf)
{
wr_inlines++;
if (wr_inhead) {
if (strcmp(line, "\n") == 0)
wr_inhead = 0;
return (0);
}
if (wr_inlines >= wr_maxlines && strcmp(line, "\n") == 0)
return (0);
wr_linecount++;
wr_charcount += strlen(line);
return (fputs(line, obuf));
}
int
swrite(char str[])
{
register char *file;
int f, *msgvec;
msgvec = (int *)salloc((msgCount + 2) * sizeof (*msgvec));
if ((file = snarf(str, &f, 1)) == NOSTR)
return (1);
if (f == -1)
return (1);
if ((file = expand(file)) == NOSTR)
return (1);
if (!f) {
*msgvec = first(0, MMNORM);
if (*msgvec == 0) {
printf(gettext("No messages to write.\n"));
return (1);
}
msgvec[1] = 0;
}
if (f && getmsglist(str, msgvec, 0) < 0)
return (1);
savemsglist(file, msgvec, S_MARK|S_NOHEADER);
return (0);
}
#define SN_DELIM 1
#define SN_TOKEN 2
#define SN_QUOTE 4
char *
snarf(char linebuf[], int *flag, int erf)
{
register char *p;
register char qc;
register unsigned int pc_type;
register char *tok_beg;
register char *tok_end;
char *line_beg;
for (line_beg = linebuf;
*line_beg && any(*line_beg, " \t");
line_beg++) {
}
if (!*line_beg) {
if (erf) {
printf(gettext("No file specified.\n"));
}
*flag = 0;
return (NOSTR);
}
pc_type = SN_DELIM;
tok_beg = tok_end = NOSTR;
p = line_beg;
while (*p != '\0') {
if (any(*p, " \t")) {
if (pc_type & (SN_TOKEN|SN_QUOTE)) {
tok_end = p - 1;
}
pc_type = SN_DELIM;
p++;
} else if ((qc = *p) == '"' || qc == '\'') {
if (pc_type == SN_TOKEN) {
p++;
continue;
}
for (tok_beg = p, tok_end = NOSTR, p++;
*p != '\0' && *p != qc;
p++) {
if (*p == '\\' && *(p+1) == qc) {
p++;
}
}
if (*p == '\0') {
printf(gettext("Syntax error: missing "
"%c.\n"), qc);
*flag = -1;
return (NOSTR);
}
tok_end = p;
pc_type = SN_QUOTE;
p++;
} else {
if (pc_type & (SN_DELIM|SN_TOKEN)) {
if (pc_type & SN_DELIM) {
tok_beg = p;
tok_end = NOSTR;
}
} else {
printf(gettext("improper quotes"
" at \"%s\".\n"), p);
*flag = -1;
return (NOSTR);
}
if (*p == '\\' && *++p == '\0') {
printf(gettext("\'\\\' at "
"end of line.\n"));
*flag = -1;
return (NOSTR);
}
pc_type = SN_TOKEN;
p++;
}
}
if (pc_type == SN_TOKEN) {
tok_end = p - 1;
}
if (tok_beg != NOSTR && tok_end != NOSTR) {
if (tok_beg == line_beg) {
*flag = 0;
} else {
tok_beg[-1] = '\0';
*flag = 1;
}
tok_end[1] = '\0';
return (tok_beg);
} else {
if (erf) {
printf(gettext("No file specified.\n"));
}
*flag = 0;
return (NOSTR);
}
}
int
deltype(int msgvec[])
{
int list[2];
int lastdot;
lastdot = dot - &message[0] + 1;
if (delm(msgvec) >= 0) {
list[0] = dot - &message[0];
list[0]++;
if (list[0] > lastdot) {
touch(list[0]);
list[1] = 0;
return (type(list));
}
printf(gettext("At EOF\n"));
return (0);
} else {
printf(gettext("No more messages\n"));
return (0);
}
}
int
delm(int *msgvec)
{
register struct message *mp;
int *ip, mesg;
int last;
last = 0;
for (ip = msgvec; *ip != 0; ip++) {
mesg = *ip;
touch(mesg);
mp = &message[mesg-1];
mp->m_flag |= MDELETED|MTOUCH;
mp->m_flag &= ~(MPRESERVE|MSAVED|MBOX);
last = mesg;
}
if (last != 0) {
dot = &message[last-1];
last = first(0, MDELETED);
if (last != 0) {
dot = &message[last-1];
return (0);
} else {
dot = &message[0];
return (-1);
}
}
return (-1);
}
int
undelete(int *msgvec)
{
register struct message *mp;
int *ip, mesg;
for (ip = msgvec; ip-msgvec < msgCount; ip++) {
mesg = *ip;
if (mesg == 0)
return (0);
touch(mesg);
mp = &message[mesg-1];
dot = mp;
mp->m_flag &= ~MDELETED;
}
return (0);
}
int
retfield(char *list[])
{
char field[BUFSIZ];
register int h;
register struct ignore *igp;
char **ap;
if (argcount(list) == 0)
return (retshow());
for (ap = list; *ap != 0; ap++) {
istrcpy(field, sizeof (field), *ap);
if (member(field, retain))
continue;
h = hash(field);
if ((igp = (struct ignore *)
calloc(1, sizeof (struct ignore))) == NULL) {
panic("Couldn't allocate memory");
}
if ((igp->i_field = (char *)
calloc(strlen(field) + 1, sizeof (char))) == NULL) {
panic("Couldn't allocate memory");
}
strcpy(igp->i_field, field);
igp->i_link = retain[h];
retain[h] = igp;
nretained++;
}
return (0);
}
static int
retshow(void)
{
register int h, count;
struct ignore *igp;
char **ap, **ring;
count = 0;
for (h = 0; h < HSHSIZE; h++)
for (igp = retain[h]; igp != 0; igp = igp->i_link)
count++;
if (count == 0) {
printf(gettext("No fields currently being retained.\n"));
return (0);
}
ring = (char **)salloc((count + 1) * sizeof (char *));
ap = ring;
for (h = 0; h < HSHSIZE; h++)
for (igp = retain[h]; igp != 0; igp = igp->i_link)
*ap++ = igp->i_field;
*ap = 0;
qsort(ring, count, sizeof (char *), igcomp);
for (ap = ring; *ap != 0; ap++)
printf("%s\n", *ap);
return (0);
}
int
unretfield(char *list[])
{
char **ap, field[BUFSIZ];
register int h, count = 0;
register struct ignore *ig1, *ig2;
if (argcount(list) == 0) {
for (h = 0; h < HSHSIZE; h++) {
ig1 = retain[h];
while (ig1) {
free(ig1->i_field);
ig2 = ig1->i_link;
free((char *)ig1);
ig1 = ig2;
count++;
}
retain[h] = NULL;
}
if (count == 0)
printf(gettext(
"No fields currently being retained.\n"));
nretained = 0;
return (0);
}
for (ap = list; *ap; ap++) {
istrcpy(field, sizeof (field), *ap);
h = hash(field);
for (ig1 = retain[h]; ig1; ig2 = ig1, ig1 = ig1->i_link)
if (strcmp(ig1->i_field, field) == 0) {
if (ig1 == retain[h])
retain[h] = ig1->i_link;
else
ig2->i_link = ig1->i_link;
free(ig1->i_field);
free((char *)ig1);
nretained--;
break;
}
}
return (0);
}
int
igfield(char *list[])
{
char field[BUFSIZ];
register int h;
register struct ignore *igp;
char **ap;
if (argcount(list) == 0)
return (igshow());
for (ap = list; *ap != 0; ap++) {
if (isign(*ap, 0))
continue;
istrcpy(field, sizeof (field), *ap);
h = hash(field);
if ((igp = (struct ignore *)
calloc(1, sizeof (struct ignore))) == NULL) {
panic("Couldn't allocate memory");
}
if ((igp->i_field = (char *)
calloc((unsigned)strlen(field) + 1,
sizeof (char))) == NULL) {
panic("Couldn't allocate memory");
}
strcpy(igp->i_field, field);
igp->i_link = ignore[h];
ignore[h] = igp;
}
return (0);
}
static int
igshow(void)
{
register int h, count;
struct ignore *igp;
char **ap, **ring;
count = 0;
for (h = 0; h < HSHSIZE; h++)
for (igp = ignore[h]; igp != 0; igp = igp->i_link)
count++;
if (count == 0) {
printf(gettext("No fields currently being ignored.\n"));
return (0);
}
ring = (char **)salloc((count + 1) * sizeof (char *));
ap = ring;
for (h = 0; h < HSHSIZE; h++)
for (igp = ignore[h]; igp != 0; igp = igp->i_link)
*ap++ = igp->i_field;
*ap = 0;
qsort((char *)ring, (unsigned)count, sizeof (char *), igcomp);
for (ap = ring; *ap != 0; ap++)
printf("%s\n", *ap);
return (0);
}
static int
igcomp(const void *l, const void *r)
{
return (strcmp(*(char **)l, *(char **)r));
}
int
unigfield(char *list[])
{
char **ap, field[BUFSIZ];
register int h, count = 0;
register struct ignore *ig1, *ig2;
if (argcount(list) == 0) {
for (h = 0; h < HSHSIZE; h++) {
ig1 = ignore[h];
while (ig1) {
free(ig1->i_field);
ig2 = ig1->i_link;
free((char *)ig1);
ig1 = ig2;
count++;
}
ignore[h] = NULL;
}
if (count == 0)
printf(gettext("No fields currently being ignored.\n"));
return (0);
}
for (ap = list; *ap; ap++) {
istrcpy(field, sizeof (field), *ap);
h = hash(field);
for (ig1 = ignore[h]; ig1; ig2 = ig1, ig1 = ig1->i_link)
if (strcmp(ig1->i_field, field) == 0) {
if (ig1 == ignore[h])
ignore[h] = ig1->i_link;
else
ig2->i_link = ig1->i_link;
free(ig1->i_field);
free((char *)ig1);
break;
}
}
return (0);
}