home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
misc
/
volume30
/
tin
/
part11
/
open.c
< prev
Wrap
C/C++ Source or Header
|
1992-05-20
|
14KB
|
707 lines
/*
* Project : tin - a threaded Netnews reader
* Module : open.c
* Author : I.Lea & R.Skrenta
* Created : 01-04-91
* Updated : 12-05-92
* Notes : reads news locally (ie. /usr/spool/news) or via NNTP
* Copyright : (c) Copyright 1991-92 by Iain Lea & Rich Skrenta
* You may freely copy or redistribute this software,
* so long as there is no profit made from its use, sale
* trade or reproduction. You may not change this copy-
* right notice, and it must be included in any copy made
*/
#include "tin.h"
#include "nntplib.h"
/*
* Directory handling code - Hopefully one of these is right for you.
*/
#ifdef BSD
# ifdef sinix
# include <dir.h>
# else
# include <sys/dir.h>
# endif
# define DIR_BUF struct direct
# define D_LENGTH d_namlen
#endif
#ifdef M_XENIX
# include <sys/ndir.h>
# define DIR_BUF struct direct
# define D_LENGTH d_namlen
#endif
#ifndef DIR_BUF
# include <dirent.h>
# define DIR_BUF struct dirent
# define D_LENGTH d_reclen
#endif
int nntp_codeno = 0;
#ifdef NNTP_ABLE
int compiled_with_nntp = TRUE; /* used in mail_bug_report() info */
#else
int compiled_with_nntp = FALSE;
#endif
#ifdef NO_POSTING
int can_post = FALSE;
#else
int can_post = TRUE;
#endif
char server_name[LEN];
void nntp_open ()
{
#ifdef NNTP_ABLE
char *server;
int ret;
if (read_news_via_nntp) {
debug_nntp ("nntp_open", "BEGIN");
if (nntp_server[0]) {
server = nntp_server;
} else {
server = getserverbyfile (NNTP_SERVER_FILE);
}
if (server == (char *) 0) {
error_message (txt_cannot_get_nntp_server_name, "");
error_message (txt_server_name_in_file_env_var, NNTP_SERVER_FILE);
exit(1);
}
if (update == FALSE) {
sprintf (msg, txt_connecting, server);
wait_message (msg);
}
debug_nntp ("nntp_open", server);
ret = server_init (server);
if (update == FALSE) {
fputc ('\n', stdout);
}
debug_nntp_respcode (ret);
switch (ret) {
case OK_CANPOST:
#ifndef NO_POSTING
can_post = TRUE;
#endif
break;
case OK_NOPOST:
can_post = FALSE;
break;
case -1:
error_message (txt_failed_to_connect_to_server, server);
exit (1);
default:
sprintf (msg, "%s: %s", progname, nntp_respcode (ret));
error_message (msg, "");
exit (1);
}
/*
* Find out if NNTP supports my XINDEX & XUSER commands
*/
debug_nntp ("nntp_open", "xindex");
put_server ("xindex");
if (get_respcode () != ERR_COMMAND) {
xindex_supported = TRUE;
}
debug_nntp ("nntp_open", "xuser");
put_server ("xuser");
if (get_respcode () != ERR_COMMAND) {
xuser_supported = TRUE;
}
/*
* If INN NNTP & XINDEX not supported switch to mode reader
*/
if (! xindex_supported) {
debug_nntp ("nntp_open", "mode reader");
put_server ("mode reader");
if (get_respcode () != ERR_COMMAND) {
inn_nntp_server = TRUE;
}
}
}
/*
* Find out if NNTP supports SPOOLDIR command
*/
get_spooldir ();
#endif
}
void nntp_close ()
{
#ifdef NNTP_ABLE
if (read_news_via_nntp) {
debug_nntp ("nntp_close", "END");
close_server ();
}
#endif
}
FILE *open_active_fp ()
{
if (read_news_via_nntp) {
#ifdef NNTP_ABLE
put_server ("list");
if (get_respcode () != OK_GROUPS) {
debug_nntp ("open_active_fp", "NOT_OK");
return (FILE *) 0;
}
debug_nntp ("open_active_fp", "OK");
return nntp_to_fp ();
#else
return (FILE *) 0;
#endif
} else {
return fopen (active_file, "r");
}
}
FILE *open_subscription_fp ()
{
if (read_news_via_nntp) {
#ifdef NNTP_ABLE
put_server ("list subscriptions");
if (get_respcode () != OK_GROUPS) {
debug_nntp ("open_subscription_fp", "NOT_OK");
return (FILE *) 0;
}
debug_nntp ("open_subscription_fp", "OK");
return nntp_to_fp ();
#else
return (FILE *) 0;
#endif
} else {
return fopen (subscriptions_file, "r");
}
}
FILE *open_index_fp (group_name)
char *group_name;
{
char line[NNTP_STRLEN];
extern char index_file[PATH_LEN];
find_index_file (group_name);
if (read_news_via_nntp && xindex_supported) {
sprintf (line, "xindex %s", group_name);
debug_nntp ("open_index_fp", line);
put_server (line);
if (get_respcode () != OK_XINDEX) {
debug_nntp ("open_index_fp", "NOT_OK");
return (FILE *) 0;
}
debug_nntp ("open_index_fp", "OK");
return nntp_to_fp ();
} else {
return fopen (index_file, "r");
}
}
FILE *open_art_fp (group_path, art)
char *group_path;
long art;
{
char buf[LEN];
int respcode;
struct stat sb;
extern long note_size;
if (read_news_via_nntp) {
#ifdef NNTP_ABLE
sprintf (buf, "article %ld", art);
debug_nntp ("open_art_fp", buf);
put_server (buf);
if ((respcode = get_respcode ()) != OK_ARTICLE) {
error_message ("%s", nntp_respcode (respcode));
debug_nntp ("open_art_fp", buf);
return (FILE *) 0;
}
debug_nntp ("open_art_fp", "OK");
return nntp_to_fp ();
#else
return (FILE *) 0;
#endif
} else {
sprintf (buf, "%s/%s/%ld", spooldir, group_path, art);
if (stat (buf, &sb) < 0) {
note_size = 0;
} else {
note_size = sb.st_size;
}
return fopen (buf, "r");
}
}
FILE *open_header_fp (group_path, art)
char *group_path;
long art;
{
char buf[LEN];
if (read_news_via_nntp) {
#ifdef NNTP_ABLE
sprintf(buf, "head %ld", art);
debug_nntp ("open_header_fp", buf);
put_server (buf);
if (get_respcode () != OK_HEAD) {
debug_nntp ("open_header_fp", "NOT_OK_HEAD");
return (FILE *) 0;
}
debug_nntp ("open_header_fp", "OK_HEAD");
return nntp_to_fp ();
#else
return (FILE *) 0;
#endif
} else {
sprintf (buf, "%s/%s/%ld", spooldir, group_path, art);
return fopen (buf, "r");
}
}
/*
* Longword comparison routine for the qsort()
*/
int base_comp (p1, p2)
char *p1;
char *p2;
{
long *a = (long *) p1;
long *b = (long *) p2;
if (*a < *b)
return -1;
if (*a > *b)
return 1;
return 0;
}
/*
* Read the article numbers existing in a group's spool directory
* into base[] and sort them. top_base is one past top.
*/
void setup_base (group, group_path)
char *group;
char *group_path;
{
char buf[LEN];
#ifdef NNTP_ABLE
char line[NNTP_STRLEN];
#endif
DIR *d;
DIR_BUF *e;
long art, start, last, dummy, count;
top_base = 0;
if (read_news_via_nntp) {
#ifdef NNTP_ABLE
sprintf (buf, "group %s", group);
debug_nntp ("setup_base", buf);
put_server (buf);
if (get_server (line, NNTP_STRLEN) == -1) {
error_message (txt_connection_to_server_broken, "");
tin_done (1);
}
if (atoi(line) != OK_GROUP) {
debug_nntp ("setup_base", "NOT_OK");
return;
}
debug_nntp ("setup_base", line);
sscanf (line,"%ld %ld %ld %ld", &dummy, &count, &start, &last);
if (last - count > start) {
start = last - count;
}
while (start <= last) {
if (top_base >= max_art) {
expand_art();
}
base[top_base++] = start++;
}
#else
return;
#endif
} else {
sprintf (buf, "%s/%s", spooldir, group_path);
if (access (buf, 4) != 0) {
return;
}
d = opendir (buf);
if (d != NULL) {
while ((e = readdir (d)) != NULL) {
art = my_atol (e->d_name, (int) e->D_LENGTH);
if (art >= 0) {
if (top_base >= max_art)
expand_art ();
base[top_base++] = art;
}
}
closedir (d);
qsort ((char *) base, top_base, sizeof (long), base_comp);
}
}
}
/*
* get a response code from the server and return it to the caller
*/
int get_respcode ()
{
#ifdef NNTP_ABLE
char line[NNTP_STRLEN];
if (get_server (line, NNTP_STRLEN) == -1) {
error_message (txt_connection_to_server_broken, "");
tin_done (1);
}
debug_nntp ("get_respcode", line);
return atoi (line);
#else
return (0);
#endif
}
int stuff_nntp (fnam)
char *fnam;
{
#ifdef NNTP_ABLE
FILE *fp;
char line[NNTP_STRLEN];
extern char *mktemp ();
struct stat sb;
extern long note_size;
strcpy (fnam, "/tmp/tin_nntpXXXXXX");
mktemp (fnam);
if ((fp = fopen (fnam, "w")) == (FILE *) 0) {
perror_message (txt_stuff_nntp_cannot_open, fnam);
return FALSE;
}
while (1) {
if (get_server (line, NNTP_STRLEN) == -1) {
error_message (txt_connection_to_server_broken, "");
tin_done (1);
}
debug_nntp ("stuff_nntp", line);
if (strcmp (line, ".") == 0)
break; /* end of text */
strcat (line, "\n");
if (line[0] == '.') /* reduce leading .'s */
fputs (&line[1], fp);
else
fputs (line, fp);
}
fclose (fp);
if (stat (fnam, &sb) < 0)
note_size = 0;
else
note_size = sb.st_size;
return TRUE;
#else
return TRUE;
#endif
}
FILE *nntp_to_fp ()
{
#ifdef NNTP_ABLE
char fnam[LEN];
FILE *fp = (FILE *) 0;
if (! stuff_nntp (fnam)) {
debug_nntp ("nntp_to_fp", "! stuff_nntp()");
return (FILE *) 0;
}
if ((fp = fopen (fnam, "r")) == (FILE *) 0) {
perror_message (txt_nntp_to_fp_cannot_reopen, fnam);
return (FILE *) 0;
}
unlink (fnam);
return fp;
#else
return (FILE *) 0;
#endif
}
/*
* Log user info to local file or NNTP logfile
*/
void log_user ()
{
char buf[32], *ptr;
char line[NNTP_STRLEN];
#ifdef LOG_USER
FILE *fp;
long epoch;
#endif
extern struct passwd *myentry;
my_strncpy (buf, myentry->pw_gecos, sizeof (buf)-1);
if (read_news_via_nntp && xuser_supported) {
if ((ptr = (char *) strchr(buf, ','))) {
*ptr = '\0';
}
sprintf (line, "xuser %s (%s)", myentry->pw_name, buf);
debug_nntp ("log_user", line);
put_server (line);
} else {
#ifdef LOG_USER
if ((fp = fopen (LOG_USER_FILE, "a+")) != (FILE *) 0) {
time (&epoch);
fprintf (fp, "%s%d: %-32s (%-8s) %s", VERSION, PATCHLEVEL,
buf, myentry->pw_name, ctime (&epoch));
fclose (fp);
chmod (LOG_USER_FILE, 0666);
}
#endif
}
}
/*
* NNTP strings for get_respcode()
*/
char *nntp_respcode (respcode)
int respcode;
{
#ifdef NNTP_ABLE
static char *text;
switch (respcode) {
case 0:
text = "";
break;
case INF_HELP:
text = "100 Help text on way";
break;
case INF_AUTH:
text = "180 Authorization capabilities";
break;
case INF_DEBUG:
text = "199 Debug output";
break;
case OK_CANPOST:
text = "200 Hello; you can post";
break;
case OK_NOPOST:
text = "201 Hello; you can't post";
break;
case OK_SLAVE:
text = "202 Slave status noted";
break;
case OK_GOODBYE:
text = "205 Closing connection";
break;
case OK_GROUP:
text = "211 Group selected";
break;
case OK_GROUPS:
text = "215 Newsgroups follow";
break;
case OK_XINDEX:
text = "218 Group index file follows";
break;
case OK_ARTICLE:
text = "220 Article (head & body) follows";
break;
case OK_HEAD:
text = "221 Head follows";
break;
case OK_BODY:
text = "222 Body follows";
break;
case OK_NOTEXT:
text = "223 No text sent -- stat, next, last";
break;
case OK_NEWNEWS:
text = "230 New articles by message-id follow";
break;
case OK_NEWGROUPS:
text = "231 New newsgroups follow";
break;
case OK_XFERED:
text = "235 Article transferred successfully";
break;
case OK_POSTED:
text = "240 Article posted successfully";
break;
case OK_AUTHSYS:
text = "280 Authorization system ok";
break;
case OK_AUTH:
text = "281 Authorization (user/pass) ok";
break;
case OK_BIN:
text = "282 binary data follows";
break;
case OK_SPLIST:
text = "283 spooldir list follows";
break;
case OK_SPSWITCH:
text = "284 Switching to a different spooldir";
break;
case OK_SPNOCHANGE:
text = "285 Still using same spooldir";
break;
case OK_SPLDIRCUR:
text = "286 Current spooldir";
break;
case OK_SPLDIRAVL:
text = "287 Available spooldir";
break;
case OK_SPLDIRERR:
text = "288 Unavailable spooldir or invalid entry";
break;
case CONT_XFER:
text = "335 Continue to send article";
break;
case CONT_POST:
text = "340 Continue to post article";
break;
case NEED_AUTHINFO:
text = "380 authorization is required";
break;
case NEED_AUTHDATA:
text = "381 <type> authorization data required";
break;
case ERR_GOODBYE:
text = "400 Have to hang up for some reason";
break;
case ERR_NOGROUP:
text = "411 No such newsgroup";
break;
case ERR_NCING:
text = "412 Not currently in newsgroup";
break;
case ERR_XINDEX:
text = "418 No index file for this group";
break;
case ERR_NOCRNT:
text = "420 No current article selected";
break;
case ERR_NONEXT:
text = "421 No next article in this group";
break;
case ERR_NOPREV:
text = "422 No previous article in this group";
break;
case ERR_NOARTIG:
text = "423 No such article in this group";
break;
case ERR_NOART:
text = "430 No such article at all";
break;
case ERR_GOTIT:
text = "435 Already got that article, don't send";
break;
case ERR_XFERFAIL:
text = "436 Transfer failed";
break;
case ERR_XFERRJCT:
text = "437 Article rejected, don't resend";
break;
case ERR_NOPOST:
text = "440 Posting not allowed";
break;
case ERR_POSTFAIL:
text = "441 Posting failed";
break;
case ERR_NOAUTH:
text = "480 authorization required for command";
break;
case ERR_AUTHSYS:
text = "481 Authorization system invalid";
break;
case ERR_AUTHREJ:
text = "482 Authorization data rejected";
break;
case ERR_INVALIAS:
text = "483 Invalid alias on spooldir cmd";
break;
case ERR_INVNOSPDIR:
text = "484 No spooldir file found";
break;
case ERR_COMMAND:
text = "500 Command not recognized";
break;
case ERR_CMDSYN:
text = "501 Command syntax error";
break;
case ERR_ACCESS:
text = "502 Access to server denied";
break;
case ERR_FAULT:
text = "503 Program fault, command not performed";
break;
case ERR_AUTHBAD:
text = "580 Authorization Failed";
break;
default:
text = "Unknown NNTP response code";
break;
}
return (text);
#else
return ("");
#endif
}