* readr - /bin/mail and msgs interface and associated functions.
static char *SccsId
= "@(#)readr.c 2.26 5/3/83";
static char lbuf
[BUFLEN
*2];
#define saveart oobit = bit;strcpy(ofilename1, filename);strcpy(ogroupdir, groupdir);hbufcp(&hbuf1, &h);ongsize = pngsize
#define NLINES(h, fp) (h.numlines[0] ? h.intnumlines : (h.intnumlines=linecnt(fp),sprintf(h.numlines, "%d", h.intnumlines), h.intnumlines))
char *tft
= "/tmp/folXXXXXX";
static int hascaught
= 0;
* These were made static for u370 with its buggy cc.
* I judged it better to have one copy with no ifdefs than
* to conditionally compile them as automatic variables
* in readr (which they originally were). Performance
* considerations might warrent moving some of the simple
* things into register variables, but I don't know what
static char goodone
[BUFLEN
]; /* last decent article */
static char ogroupdir
[BUFLEN
]; /* last groupdir */
static char address
[PATHLEN
]; /* for reply copy */
static char edcmdbuf
[128];
static int rfq
= 0; /* for last article */
static long ongsize
; /* Previous ngsize */
static long pngsize
; /* Printing ngsize */
static char *bptr
; /* temp pointer. */
static struct srec srec
; /* srec for sys file entries */
static char *tfilename
; /* temporary file name */
static char ofilename1
[BUFLEN
]; /* previous file name */
static struct hbuf hbuf1
, hbuf2
, *hptr
; /* for minusing */
static char *ptr1
, *ptr2
, *ptr3
; /* for reply manipulation */
static int abs
= FALSE
; /* TRUE if we asked absolutely */
static char *ed
, tf
[100];
static struct hbuf h
; /* ditto. */
static int oobit
; /* last bit, really */
static FILE *ofp
; /* Current output file to terminal*/
static FILE *fp
; /* current article to be printed*/
static int holdup
; /* 1 iff should stop before hdr */
static int ignorenews
; /* 1 iff readnews -p > /dev/null*/
static long timelastsaved
; /* time newsrc last written out */
fprintf(stderr
, "readr()\n");
if ((atime
= cgtdate(datebuf
)) == -1)
xerror("Cannot parse date string");
if (cflag
&& coptbuf
[0] != '\0') {
mktemp(outfile
); /* get "unique" file name */
ofp
= xfopen(outfile
, "w");
/* loop reading articles. */
printf("after getnextart, fp %x, pos %d, bit %d, group '%s', filename '%s'\n",
fp
, ftell(fp
), bit
, groupdir
, filename
);
strcpy(goodone
, filename
);
if (pflag
|| lflag
|| eflag
) {
/* This code should be gotten rid of */
_exit(0); /* kludge! drop when qfflush works */
fprintf(ofp
, "Last article. [qfr] ");
fprintf(ofp
, "(%d lines) More? [ynq] ", NLINES(h
, fp
));
ocont
= signal(SIGCONT
, catchcont
);
pp
= fgets(bptr
, BUFLEN
, stdin
);
while (*bptr
== ' ' || *bptr
== '\t')
fprintf(stderr
, "No news.\n");
#define EOL() if (*bptr != '\0') { fprintf(ofp, "? for commands.\n"); return FALSE; }
* Process one command, which has already been typed in.
/* No. Go on to next article. */
/* Undigestify the article. */
/* yes: print this article, go on. */
/* The user hit return. Default is 'y' unless rfq, then it's 'q'. */
* Unsubscribe to the newsgroup and go on to next group
fprintf(ofp
, "To unsubscribe, use 'U'\n");
fprintf(ofp
, "Unsubscribing to newsgroup: %s\n", groupdir
);
if (actdirect
== BACKWARD
)
fprintf(ofp
, "Can't back up.\n");
/* Print the current version of news */
fprintf(ofp
, "News version: %s\n", news_version
);
/* reprint the article */
/* write out the article someplace */
if (*bptr
!= '\0' && *bptr
!= ' ') {
fprintf(ofp
, "Bad file name.\n");
if (*bptr
!= '|' && *bptr
!= '/') {
if (boxptr
= getenv("NEWSBOX"))
sprintf(bptr
, boxptr
, grn
);
else if (hetyped
[0] == '~' && hetyped
[1] == '/') {
strcat(bptr
, "Articles");
fwait(fsubr(save
, tfilename
, bptr
));
fprintf(ofp
, "Can't back up.\n");
strcpy(filename
, ofilename1
);
if (strcmp(groupdir
, ogroupdir
)) {
strcpy(groupdir
, ogroupdir
);
for (i
= 0; i
< atoi(bptr
); i
++) {
if ((bit
> pngsize
) || (rflag
&& bit
< 1))
/* exit - time updated to that of most recently read article */
/* exit - no time update. */
/* cancel the article. */
fwait(fsubr(ushell
, bptr
, (char *)NULL
));
/* send to some system */
sscanf(--bptr
, "%d", &i
);
fprintf(ofp
, "Bad article no.\n");
fprintf(ofp
, "Not that many articles.\n");
/* specific message ID. */
fprintf(ofp
, "No such article: %s.\n", bptr
);
ptr2
= index(ptr1
, '\t');
ptr3
= index(++ptr2
, '\t');
ptr2
= index(++ptr3
, ' ');
if (strcmp(groupdir
, ogroupdir
)) {
strcpy(groupdir
, ogroupdir
);
sscanf(ptr2
, "%d", &bit
);
/* erase - pretend we haven't seen this article. */
if (rfq
|| *bptr
== '-') {
if (strcmp(groupdir
, ogroupdir
)) {
printf("Holding article %d newsgroup %s\n", oobit
, ogroupdir
),
strcpy(groupdir
, ogroupdir
);
printf("Holding article %d\n", oobit
),
printf("Holding article %d\n", bit
),
goto caseplus
; /* skip this article for now */
fprintf(ofp
, "Article %d:\n", oobit
);
hprint(&hbuf1
, ofp
, 1 + (i
=='H'));
fprintf(ofp
, "Article %d of %ld: %s\n",
rfq
? oobit
: bit
, pngsize
, h
.ident
);
hprint(&h
, ofp
, 1 + (i
=='H'));
fprintf(ofp
, "Article %d of %ld: newsgroup %s\n",
rfq
? oobit
: bit
, pngsize
, rfq
? ogroupdir
: groupdir
);
fprintf(ofp
, "? for commands.\n");
strcpy(rcbuf
, hptr
->path
);
ptr1
= index(rcbuf
, ' ');
i
= 0; /* root gets to cancel */
i
= strcmp(username
, rcbuf
);
fprintf(ofp
, "Can't cancel what you didn't write.\n");
if (!cancel(ofp
, hptr
, i
) && hptr
== &h
) {
register char *pathptr
, *ptr
;
extern char MAILPARSER
[];
while (*bptr
&& index("d-", *bptr
)) {
/* Followup the previous article. */
/* Don't edit the headers */
if (edit
&& access(MAILPARSER
, 1)) {
fprintf(stderr
, "Can't edit headers, 'recmail' missing.\n");
fprintf(stderr
, "Can't edit headers without %s\n", MAILPARSER
);
pathptr
= replyname(hptr
);;
for (ptr1
= address
, ptr2
= pathptr
; *ptr2
; ptr1
++, ptr2
++) {
if (index("\"\\$", *ptr2
))
folbuf
[0] = 0; /* References */
strcpy(folbuf
, hptr
->followid
);
strcat(folbuf
, hptr
->ident
);
strcpy(subj
, hptr
->title
); /* Subject */
if (!prefix(subj
, "Re:") && !prefix(subj
, "re:")) {
sprintf(subj
, "Re: %s", bfr
);
fprintf(ofp
, "To: %s\n", pathptr
);
fprintf(ofp
, "Subject: %s\n", subj
);
/* Put the user in the editor to create the body of the followup. */
fprintf(tfp
, "To: %s\n", pathptr
);
fprintf(tfp
, "Subject: %s\n", subj
);
fprintf(tfp
, "References: %s\n\n", folbuf
);
sprintf(edcmdbuf
, "%s %s", ed
, tf
);
strcpy(rcbuf
, MAILPARSER
);
fprintf(stderr
, "Reply not sent: no input file.\n");
printf("Sending reply.\n");
sprintf(rcbuf
, MAILER
, hptr
->title
);
sprintf(bfr
, "%s %s", rcbuf
, address
);
if (*bptr
!= '\0' && *bptr
!= ' ') {
fprintf(ofp
, "Bad system name.\n");
fprintf(ofp
, "Missing system name.\n");
if (s_find(&srec
, bptr
) == NULL
) {
fprintf(ofp
, "%s not in SYSFILE\n", bptr
);
transmit(&srec
, tfilename
);
if (!*bptr
|| *bptr
== '-') {
if (actdirect
== BACKWARD
)
fprintf(ofp
, "Can't back up.\n");
fprintf(ofp
, "No such group.\n");
while (*bptr
&& index("d-", *bptr
)) {
/* Followup the previous article. */
/* Don't edit the headers */
/* Figure out the subject, newsgroups, and references for the followup. */
ng
= hptr
->nbuf
; /* Newsgroups */
folbuf
[0] = 0; /* References */
strcpy(folbuf
, hptr
->followid
);
strcat(folbuf
, hptr
->ident
);
strcpy(subj
, hptr
->title
); /* Subject */
if (!prefix(subj
, "Re:") && !prefix(subj
, "re:")) {
sprintf(subj
, "Re: %s", bfr
);
/* Determine the command line for the shell. */
sprintf(bfr
, "%s -h -D", FOLLOWUP
);
sprintf(bfr
, "%s -D -F '%s' -n %s -t \'", FOLLOWUP
, folbuf
, ng
);
/* backslash special characters */
for (ptr1
= rcbuf
, ptr2
= bfr
; *ptr2
; ptr1
++, ptr2
++) {
/* Let the user know what's going on. */
fprintf(ofp
, "Posting followup article to network. Please use\n");
fprintf(ofp
, "reply ('r') instead unless your article is of general\n");
fprintf(ofp
, "interest. (To abort press BREAK.)\n");
fprintf(ofp
, "Subject: %s\n", subj
);
fprintf(ofp
, "Newsgroups: %s\n", ng
);
fprintf(ofp
, "Hit <return> to continue, BREAK to abort: ");
/* Give the user a chance to hit BREAK and back out. */
oldsig
= (char *) signal(SIGINT
, catchintr
);
/* Play obnoxious warnings, if necessary. */
if (recording(hptr
->nbuf
, 0))
/* Put the user in the editor to create the body of the followup. */
if (ed
== NULL
|| *ed
== '\0')
fprintf(tfp
, "Newsgroups: %s\n", ng
);
fprintf(tfp
, "Subject: %s\n", subj
);
fprintf(tfp
, "References: %s\n", folbuf
);
fprintf(tfp
, "Keywords: %s\n", hptr
->keywords
);
sprintf(edcmdbuf
, "%s %s", ed
, tf
);
fprintf(stderr
, "Article not posted: no input file.\n");
printf("Posting article.\n");
fprintf(stderr
, "Caesar decoding:\n");
if (NLINES(h
, fp
) > LNCNT
&& *PAGER
) {
* Show the user the tail, if any, of the message on file
* descriptor fd, and close fd. The digester is considered,
* and the pager is used if appropriate.
} else if (!lflag
&& !pflag
&& !eflag
) {
/* Filter the tail of long messages through PAGER. */
if (NLINES(h
, fd
) > LNCNT
&& *PAGER
) {
if (!index(PAGER
, FMETA
)) {
* What follows is an attempt to prevent the
* next message from scrolling part of this
* message off the top of the screen before
* the poor luser can read it.
tprint(fd
, ofp
, FALSE
), itsbeenseen(h
.ident
);
* Find the next article we want to consider, if we're done with
* the last one, and show the header.
goto nextart2
; /* Kludge for "-" command. */
if (bit
== obit
) /* Return if still on same article as last time */
/* If done with this newsgroup, find the next one. */
while (((long) bit
> ngsize
) || (rflag
&& bit
< 1)) {
if (actdirect
== BACKWARD
) {
fprintf(ofp
, "Can't back up.\n");
else if (rfq
++ || pflag
|| cflag
)
if (now
- timelastsaved
> 5*60 /* 5 minutes */) {
printf("[Saving .newsrc]\n");
fprintf(stderr
, "article: %s/%d\n", groupdir
, bit
);
rcreadok
= 2; /* have seen >= 1 article */
sprintf(filename
, "%s/%d", dirname(groupdir
), bit
);
strcpy(filename
, goodone
);
fprintf(ofp
, "Abort (n)? ");
if (*bfr
== 'y' || *bfr
== 'Y')
fprintf(stderr
, "filename = '%s'\n", filename
);
/* Decide if we want to show this article. */
|| ((fp
= fopen(filename
, "r")) == NULL
)
|| (hread(&h
, fp
, TRUE
) == NULL
)
|| (!rfq
&& !select(&h
, abs
))) {
fprintf(stderr
, "Bad article '%s'\n", filename
);
if ((cflag
&& !lflag
&& !eflag
) || pflag
)
if (cflag
&& lflag
&& eflag
|| pflag
) {
* Print out whatever the appropriate header is
/* Wait for user to read previous article. */
fprintf(ofp
, "Article %d of %ld, %s.\n",
bit
, pngsize
, briefdate(h
.subdate
));
hprint(&h
, ofp
, pflag
? 1 : 0);
static int calledbefore
= 0;
fprintf(ofp
, "\n'%s' ignored.\n", bfr
);
if (calledbefore
++ == 0) {
fprintf(ofp
, "The colon is to give you a chance to finish reading the\n");
fprintf(ofp
, "previous article before the next header scrolls it off\n");
fprintf(ofp
, "the top of the screen. You should hit `return' or `newline'\n");
fprintf(ofp
, "when you are ready to go on to the next article.\n\n");
char *tstr
= "Newsgroup ";
int l
= strlen(title
) + strlen(tstr
);
fprintf(ofp
, "%s%s\n", tstr
, title
);
fprintf(ofp
, "%s%s, ", tstr
, title
);
fprintf(ofp
, "%ld\n", pngsize
);
fprintf(ofp
, "%d-%ld\n", bit
, pngsize
);
* Routine to catch a continue signal.
signal(SIGCONT
, catchcont
);