home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The World of Computer Software
/
World_Of_Computer_Software-02-387-Vol-3of3.iso
/
s
/
slurp103.zip
/
SLURP.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-12-20
|
12KB
|
527 lines
/*
* slurp - a passive nntp news client
*
* Copyright (C) 1992 Stephen Hebditch. All rights reserved.
* TQM Communications, BCM Box 225, London, WC1N 3XX.
* steveh@orbital.demon.co.uk +44 836 825962
*
* See README for more information and disclaimers
*
* This is the main routine for slurp together with the routines to
* handle the configuration files and command line arguments.
*
* 1.00 7 Aug 92 SH Initial coding.
* 1.01 4 Dec 92 SH Fixed null dereferencing of nn_distributions.
* 1.01 6 Dec 92 SH Made no_time_flag global.
* 1.02 7 Dec 92 SH Corrected test for 4.2/4.3 syslog open.
* 1.03 15 Dec 92 SH Open syslog *before* we start doing things that
* might write to it. Informational messages logged
* as LOG_INFO.
* Assorted minor tidy-ups.
*
*/
#include "slurp.h"
#include <sys/stat.h>
char *hostname = NULL;
char *pname;
int debug_flag = 0;
int no_time_flag = 0;
static int local_time_flag = 0;
int dupart = 0;
int misart = 0;
int newart = 0;
long totalsize = 0;
char *nn_newsgroups = NULL;
char *nn_time = NULL;
char *nn_distributions = NULL;
struct mnode *root = NULL;
int entries = 0;
static long newdate, newtime;
/*
* test_time - Check NEWNEWS time string is in the right format (ish)
*/
static int
test_time ()
{
return (!(isdigit (nn_time [0]) &&
isdigit (nn_time [1]) &&
isdigit (nn_time [2]) &&
isdigit (nn_time [3]) &&
isdigit (nn_time [4]) &&
isdigit (nn_time [5]) &&
isspace (nn_time [6]) &&
isdigit (nn_time [7]) &&
isdigit (nn_time [8]) &&
isdigit (nn_time [9]) &&
isdigit (nn_time [10]) &&
isdigit (nn_time [11]) &&
isdigit (nn_time [12])));
}
/*
* parse_args - Parse the command line arguments. Returns 1 if there is
* an error, otherwise returns 0.
*/
static int
parse_args (int argc, char **argv)
{
int c;
extern int optind;
extern char *optarg;
while ((c = getopt (argc, argv, "s:t:g:d:lwx")) != EOF)
switch (c)
{
case 's': /* System name */
hostname = optarg;
break;
case 't': /* Start time */
nn_time = optarg;
break;
case 'g': /* Newsgroups list */
nn_newsgroups = optarg;
no_time_flag++;
break;
case 'd': /* Distributions */
nn_distributions = optarg;
break;
case 'l': /* Use local time */
local_time_flag++;
break;
case 'w': /* Don't set next time */
no_time_flag++;
break;
case 'x': /* Debugging on */
debug_flag++;
break;
default:
return (1);
}
/* There must be a system name supplied */
if (hostname == NULL)
{
(void) fprintf (stderr, "No server name supplied\n");
return (1);
}
/* If groups are specified, then must have a time */
if ((nn_newsgroups != NULL) && (nn_time == NULL))
{
(void) fprintf (stderr, "Time must be specified for -g option\n");
return (1);
}
/* Verify that the time is in something like the right format */
if (nn_time)
if (test_time ())
return (1);
/* Don't run if too many args as user probably got it wrong */
if (argc > optind)
return (1);
return (0);
}
/*
* read_sys_line - Read a line from the slurp.sys file, skipping lines
* which are blank or all comments, truncating lines at comments.
* Identical interface-wise to fgets.
*/
static char *
read_sys_line (char *line, int size, FILE *sysfp)
{
char *status;
char *pos;
for (;;)
{
if ((status = fgets (line, size, sysfp)) == NULL)
return (status);
if (pos = strchr (line, '\n'))
*pos = '\0';
if (pos = strchr (line, '#'))
*pos = '\0';
if (strlen (line))
return (status);
}
}
/*
* read_sys - Read in the appropriate entry from the slurp.sys file
* for the specified hostname. Stores the relevant newsgroups for that
* host in nn_newsgroups and the relevant distribution in nn_distributions.
* Returns 0 if an appropriate entry for the current host is found,
* otherwise returns 1.
*/
static int
read_sys ()
{
FILE *sysfp;
char buf [BUFSIZ];
char searchname [BUFSIZ];
size_t tlen;
struct stat stbuf;
int more, distfound;
/* Attempt to open the sys file */
if ((sysfp = fopen (SYSFILE, "r")) == NULL)
log_sys ("read_sys: Error opening %s", SYSFILE);
/* Allocate memory block for newsgroups list */
if (fstat (fileno (sysfp), &stbuf) < 0)
log_sys ("read_sys: Can't fstat %s", SYSFILE);
if (stbuf.st_size == 0)
{
log_msg ("read_sys: Host %s not found in %s", hostname, SYSFILE);
return (1);
}
nn_newsgroups = (char *) malloc (stbuf.st_size);
nn_newsgroups [0] = '\0';
/* Get hostname and add a colon on the end */
(void) strcpy (searchname, hostname);
(void) strcat (searchname, ":");
tlen = strlen (searchname);
/* Read in file until we find hostname */
for (;;)
{
if (read_sys_line (buf, sizeof (buf), sysfp) == NULL)
{
if (feof (sysfp))
{
log_msg ("read_sys: Host %s not found in %s",
hostname, SYSFILE);
return (1);
}
else
log_sys ("read_sys: Error reading %s", SYSFILE);
}
if (strncmp (buf, searchname, tlen) == 0)
break;
}
/* Read groups up to '/' or line without '\' at end */
(void) strcpy (buf, buf + tlen);
for (;;)
{
tlen = (size_t) strchr (buf, '/');
if (tlen == NULL)
{
distfound = FALSE;
tlen = (size_t) strchr (buf, '\\');
if (tlen == NULL)
{
more = FALSE;
tlen = strlen (buf);
}
else
{
tlen = tlen - (size_t) &buf;
more = TRUE;
}
}
else
{
tlen = tlen - (size_t) &buf;
distfound = TRUE;
}
(void) strncat (nn_newsgroups, buf, tlen);
if (distfound)
break;
if (!more)
return (0);
if (read_sys_line (buf, sizeof (buf), sysfp) == NULL)
log_sys ("read_sys: Error reading %s", SYSFILE);
}
/* Set distributions from file if not already set */
if (nn_distributions != NULL)
return (0);
nn_distributions = (char *) malloc (stbuf.st_size);
nn_distributions [0] = '\0';
/* Read distributions up to line without '\' at end */
(void) strcpy (buf, buf + tlen + 1);
for (;;)
{
tlen = (size_t) strchr (buf, '\\');
if (tlen == NULL)
{
tlen = tlen - (size_t) &buf;
more = TRUE;
}
else
{
tlen = strlen (buf);
more = FALSE;
}
(void) strncat (nn_distributions, buf, tlen);
if (!more)
return (0);
if (read_sys_line (buf, sizeof (buf), sysfp) == NULL)
log_sys ("read_sys: Error reading %s", SYSFILE);
}
}
/*
* get_ntime - Get the start time for this NEWNEWS for system. Returns 0
* if an appropriate entry for the current host is found, otherwise 1.
*/
static int
get_ntime ()
{
FILE *timefp;
char buf [BUFSIZ];
size_t tlen;
/* Attempt to open the time file */
if ((timefp = fopen (TIMFILE, "r")) == NULL)
log_sys ("get_ntime: error opening %s", TIMFILE);
/* Read in file until we find hostname */
tlen = strlen (hostname);
for (;;)
{
if (fgets (buf, sizeof (buf), timefp) == NULL)
{
if (feof (timefp))
{
log_msg ("get_ntime: Host %s not found in %s",
hostname, TIMFILE);
return (1);
}
else
log_sys ("get_ntime: Error reading %s", TIMFILE);
(void) fclose (timefp);
return (1);
}
if (strncmp (buf, hostname, tlen) == 0)
break;
}
(void) fclose (timefp);
/* Get the time following the hostname */
nn_time = (char *) malloc (14);
(void) strncpy (nn_time, buf + tlen + 1, 13);
nn_time [13] = '\0';
/* And check it's in the right format */
return (test_time ());
}
/*
* set_ntime - Set the start time for the next NEWNEWS for system
*/
static void
set_ntime ()
{
FILE *oldfp;
FILE *newfp;
char backup [PATH_MAX];
char buf [BUFSIZ];
int tlen;
/* Copy the file to a backup */
(void) strcpy (backup, TIMFILE);
(void) strcat (backup, ".o");
if (rename (TIMFILE, backup))
log_sys ("set_ntime: Error renaming %s to %s", TIMFILE, backup);
/* Attempt to open the backup and new file */
if ((oldfp = fopen (backup, "r")) == NULL)
log_sys ("get_ntime: Error opening %s", backup);
if ((newfp = fopen (TIMFILE, "w")) == NULL)
log_sys ("get_ntime: Error opening %s", TIMFILE);
/* Copy file line by line, excluding the current host */
tlen = strlen (hostname);
for (;;)
{
if (fgets (buf, sizeof (buf), oldfp) == NULL)
if (feof (oldfp))
break;
else
log_sys ("set_ntime: Error reading %s", backup);
if (strncmp (buf, hostname, tlen) != 0)
if (fputs (buf, newfp) == NULL)
log_sys ("set_ntime: Error writing %s", TIMFILE);
}
/* Write the new time for current host at end */
(void) fprintf (newfp, "%s %06ld %06ld\n", hostname, newdate, newtime);
if (ferror (newfp))
log_sys ("set_ntime: Error writing %s", TIMFILE);
(void) fclose (oldfp);
(void) fclose (newfp);
}
/*
* MAIN PROCEDURE
*/
void
main (int argc, char **argv)
{
int ret;
time_t clock, starttime, endtime;
struct tm *now;
/* Set the name of the program and parse the args */
pname = (pname = (char *) strrchr (argv [0], '/')) ? pname + 1 : argv [0];
if (parse_args (argc, argv))
{
(void) fprintf (stderr, "Usage: %s -s server [-g newsgroups] [-t time] [-d distribution] [-l] [-w] [-x]\n", pname);
exit (2);
}
/* Open syslog if required with appropriate BSD 4.2/4.3 call */
#ifdef SYSLOG
#ifdef LOG_AUTH
openlog(pname, LOG_PID, SYSLOG);
#else
openlog(pname, LOG_PID);
#endif
#endif
/* If groups not supplied in args, then get from slurp.sys file */
if (nn_newsgroups == NULL)
if (read_sys ())
exit (2);
/* If distributions not set, then point at null string */
if (!nn_distributions)
nn_distributions = "";
/* If start time not supplied in args, then get from slurp.tim file */
if (nn_time == NULL)
if (get_ntime ())
exit (2);
if (debug_flag)
{
(void) fprintf (stderr, "server: %s\n", hostname);
(void) fprintf (stderr, "time: %s\n", nn_time);
(void) fprintf (stderr, "newsgroups: '%s'\n", nn_newsgroups);
(void) fprintf (stderr, "distributions: '%s'\n", nn_distributions);
}
/* Unless don't write flag set, get time for next NEWNEWS */
if (!no_time_flag)
{
if (local_time_flag)
clock = time ((time_t *) 0);
else
if ((clock = server_time (hostname)) == 0)
exit (3);
now = gmtime (&clock);
newdate = (now->tm_year * 10000) +
((now->tm_mon + 1) * 100) +
now->tm_mday;
newtime = (now->tm_hour * 10000) +
(now->tm_min * 100) +
now->tm_sec;
}
/* Open the history file */
if (open_history ())
log_sys ("Can't open history file %s", HISTORY_FILE);
/* Set up the connection to the server */
switch (ret = server_init (hostname))
{
case -1 :
exit (3);
case OK_CANPOST :
case OK_NOPOST :
break;
default :
log_msg ("Can't talk to %s: got response code %d", hostname, ret);
exit (4);
}
/* Get a list of the new articles */
get_ids ();
/* Now get the actual articles */
starttime = time ((time_t *) 0);
if (entries > 0)
get_articles ();
endtime = time ((time_t *) 0);
/* Time to say goodbye */
close_server ();
close_history ();
/* Submit the remaining batch, if present */
enqueue_batch ();
/* do we want to update the timestamp file? */
if (!no_time_flag)
set_ntime ();
#ifdef SYSLOG
if (!debug_flag)
syslog (LOG_INFO,"Processed %d new, %d duplicate, %d missing articles",
newart, dupart, misart);
else
#endif
(void) fprintf (stderr, "Processed %d new, %d duplicate, %d missing articles\n",
newart, dupart, misart);
#ifdef SPEEDSTATS
#ifdef SYSLOG
if (!debug_flag)
syslog (LOG_INFO, "Average transfer speed %ld cps",
totalsize / (starttime == endtime ? 1 : endtime - starttime));
else
#endif
(void) fprintf (stderr, "Average transfer speed %ld cps\n",
totalsize / (starttime == endtime ? 1 : endtime - starttime));
#endif
exit (0);
}
/* END-OF-FILE */