/* inews.c
*/
/* This software is copyrighted as detailed in the LICENSE file. */
#include "EXTERN.h"
#include "common.h"
#include "env.h"
#include "init.h"
#include "util2.h"
#include "util3.h"
#include "nntpclient.h"
#include "nntpinit.h"
#define MAX_SIGNATURE 4
int debug = 0;
int new_connection = FALSE;
char* server_name;
char* nntp_auth_file;
char nullstr[1];
char buf[LBUFLEN+1];
int valid_header _((char*));
void append_signature _((void));
int
main(argc, argv)
int argc;
char* argv[];
{
bool has_fromline, in_header, has_pathline;
bool found_nl, had_nl;
int artpos, headbuf_size, len;
char* headbuf;
char* line_end;
register char* cp;
int i;
headbuf_size = LBUFLEN * 8;
headbuf = safemalloc(headbuf_size);
#ifdef LAX_INEWS
env_init(headbuf, 1);
#else
if (!env_init(headbuf, 0)) {
fprintf(stderr,"Can't get %s information. Please contact your system adminstrator.\n",
(*loginName || !*realName)? "user" : "host");
exit(1);
}
#endif
argv++;
while (argc > 1) {
if (*argv[0] != '-')
break;
argv++;
argc--;
}
if (argc > 1) {
if (freopen(*argv, "r", stdin) == NULL) {
perror(*argv);
exit(1);
}
}
cp = getenv("NNTPSERVER");
if (!cp) {
cp = filexp(SERVER_NAME);
if (FILE_REF(cp))
cp = nntp_servername(cp);
}
if (cp && *cp && strNE(cp,"local")) {
server_name = savestr(cp);
cp = index(server_name, ';');
if (cp) {
*cp = '\0';
nntplink.port_number = atoi(cp+1);
}
line_end = "\r\n";
nntp_auth_file = filexp(NNTP_AUTH_FILE);
if ((cp = getenv("NNTP_FORCE_AUTH")) != NULL
&& (*cp == 'y' || *cp == 'Y'))
nntplink.flags |= NNTP_FORCE_AUTH_NEEDED;
} else {
server_name = NULL;
line_end = "\n";
}
in_header = 0;
has_fromline = 0;
has_pathline = 0;
artpos = 0;
cp = headbuf;
had_nl = 1;
for (;;) {
if (headbuf_size < artpos + LBUFLEN + 1) {
len = cp - headbuf;
headbuf_size += LBUFLEN * 4;
headbuf = saferealloc(headbuf,headbuf_size);
cp = headbuf + len;
}
i = getc(stdin);
if (server_name && had_nl && i == '.')
*cp++ = '.';
if (i == '\n') {
if (!in_header)
continue;
break;
}
else if (i == EOF || !fgets(cp+1, LBUFLEN-1, stdin)) {
/* Still in header after EOF? Hmm... */
fprintf(stderr,"Article was all header -- no body.\n");
exit(1);
}
*cp = (char)i;
len = strlen(cp);
found_nl = (len && cp[len-1] == '\n');
if (had_nl) {
if ((i = valid_header(cp)) == 0) {
fprintf(stderr,"Invalid header:\n%s",cp);
exit(1);
}
if (i == 2) {
if (!in_header)
continue;
break;
}
in_header = 1;
if (strncaseEQ(cp, "From:", 5))
has_fromline = 1;
else if (strncaseEQ(cp, "Path:", 5))
has_pathline = 1;
}
artpos += len;
cp += len;
if ((had_nl = found_nl) != 0 && server_name) {
cp[-1] = '\r';
*cp++ = '\n';
}
}
*cp = '\0';
/* Well, the header looks ok, so let's get on with it. */
if (server_name) {
if ((cp = getenv("NNTPFDS")) != NULL) {
int rd_fd, wr_fd;
if (sscanf(cp,"%d.%d",&rd_fd,&wr_fd) == 2) {
nntplink.rd_fp = fdopen(rd_fd, "r");
if (nntplink.rd_fp) {
nntplink.wr_fp = fdopen(wr_fd, "w");
if (nntplink.wr_fp)
nntplink.flags |= NNTP_NEW_CMD_OK;
else
nntp_close(FALSE);
}
}
}
if (!nntplink.wr_fp) {
if (init_nntp() < 0 || !nntp_connect(server_name,0))
exit(1);
new_connection = TRUE;
}
if (nntp_command("POST") <= 0 || nntp_check() <= 0) {
if (new_connection)
nntp_close(TRUE);
fprintf(stderr,"Sorry, you can't post from this machine.\n");
exit(1);
}
}
else {
sprintf(buf, "%s -h", EXTRAINEWS);
nntplink.wr_fp = popen(buf,"w");
if (!nntplink.wr_fp) {
fprintf(stderr,"Unable to execute inews for local posting.\n");
exit(1);
}
}
fputs(headbuf, nntplink.wr_fp);
if (!has_pathline)
fprintf(nntplink.wr_fp,"Path: not-for-mail%s",line_end);
if (!has_fromline) {
fprintf(nntplink.wr_fp,"From: %s@%s (%s)%s",loginName,phostname,
getval("NAME",realName),line_end);
}
if (!getenv("NO_ORIGINATOR")) {
fprintf(nntplink.wr_fp,"Originator: %s@%s (%s)%s",loginName,phostname,
getval("NAME",realName),line_end);
}
fprintf(nntplink.wr_fp,"%s",line_end);
had_nl = 1;
while (fgets(headbuf, headbuf_size, stdin)) {
/* Single . is eof, so put in extra one */
if (server_name && had_nl && *headbuf == '.')
fputc('.', nntplink.wr_fp);
/* check on newline */
cp = headbuf + strlen(headbuf);
if (cp > headbuf && *--cp == '\n') {
*cp = '\0';
fprintf(nntplink.wr_fp, "%s%s", headbuf, line_end);
had_nl = 1;
}
else {
fputs(headbuf, nntplink.wr_fp);
had_nl = 0;
}
}
if (!server_name)
return pclose(nntplink.wr_fp);
if (!had_nl)
fputs(line_end, nntplink.wr_fp);
append_signature();
fputs(".\r\n",nntplink.wr_fp);
(void) fflush(nntplink.wr_fp);
if (nntp_gets(ser_line, sizeof ser_line) < 0
|| *ser_line != NNTP_CLASS_OK) {
if (atoi(ser_line) == NNTP_POSTFAIL_VAL) {
fprintf(stderr,"Article not accepted by server; not posted:\n");
for (cp = ser_line + 4; *cp && *cp != '\r'; cp++) {
if (*cp == '\\')
fputc('\n',stderr);
else
fputc(*cp,stderr);
}
fputc('\n', stderr);
}
else
fprintf(stderr, "Remote error: %s\n", ser_line);
if (new_connection)
nntp_close(TRUE);
exit(1);
}
if (new_connection)
nntp_close(TRUE);
cleanup_nntp();
return 0;
}
/* valid_header -- determine if a line is a valid header line */
int
valid_header(h)
register char* h;
{
char* colon;
char* space;
/* Blank or tab in first position implies this is a continuation header */
if (h[0] == ' ' || h[0] == '\t') {
while (*++h == ' ' || *h == '\t') ;
return *h && *h != '\n'? 1 : 2;
}
/* Just check for initial letter, colon, and space to make
* sure we discard only invalid headers. */
colon = index(h, ':');
space = index(h, ' ');
if (isalpha(h[0]) && colon && space == colon + 1)
return 1;
/* Anything else is a bad header */
return 0;
}
/* append_signature -- append the person's .signature file if
* they have one. Limit .signature to MAX_SIGNATURE lines.
* The rn-style DOTDIR environmental variable is used if present.
*/
void
append_signature()
{
char* cp;
FILE* fp;
int count = 0;
#ifdef NO_INEWS_DOTDIR
dotdir = homedir;
#endif
if (dotdir == NULL)
return;
fp = fopen(filexp(SIGNATURE_FILE), "r");
if (fp == NULL)
return;
fprintf(nntplink.wr_fp, "-- \r\n");
while (fgets(ser_line, sizeof ser_line, fp)) {
count++;
if (count > MAX_SIGNATURE) {
fprintf(stderr,"Warning: .signature files should be no longer than %d lines.\n",
MAX_SIGNATURE);
fprintf(stderr,"(Only %d lines of your .signature were posted.)\n",
MAX_SIGNATURE);
break;
}
/* Strip trailing newline */
cp = ser_line + strlen(ser_line) - 1;
if (cp >= ser_line && *cp == '\n')
*cp = '\0';
fprintf(nntplink.wr_fp, "%s\r\n", ser_line);
}
(void) fclose(fp);
}
#ifdef SUPPORT_NNTP
int
nntp_handle_timeout()
{
if (!new_connection) {
static bool handling_timeout = FALSE;
char last_command_save[NNTP_STRLEN];
if (strcaseEQ(last_command,"quit"))
return 0;
if (handling_timeout)
return -1;
handling_timeout = TRUE;
strcpy(last_command_save, last_command);
nntp_close(FALSE);
if (init_nntp() < 0 || nntp_connect(server_name,0) <= 0)
exit(1);
if (nntp_command(last_command_save) <= 0)
return -1;
handling_timeout = FALSE;
new_connection = TRUE;
return 1;
}
fputs("\n503 Server timed out.\n",stderr);
return -2;
}
#endif
syntax highlighted by Code2HTML, v. 0.9.1