NetBSD/usr.sbin/sup/source/supscan.c

444 lines
12 KiB
C

/* $NetBSD: supscan.c,v 1.7 1998/07/06 07:05:48 mrg Exp $ */
/*
* Copyright (c) 1992 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software_Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie Mellon
* the rights to redistribute these changes.
*/
/*
* supscan -- SUP Scan File Builder
*
* Usage: supscan [ -v ] collection [ basedir ]
* supscan [ -v ] -f dirfile
* supscan [ -v ] -s
* -f "file" -- use dirfile instead of system coll.dir
* -s "system" -- perform scan for system supfile
* -v "verbose" -- print messages as you go
* collection -- name of the desired collection if not -s
* basedir -- name of the base directory, if not
* the default or recorded in coll.dir
* dirfile -- name of replacement for system coll.dir.
*
**********************************************************************
* HISTORY
* Revision 1.14 92/08/11 12:08:30 mrt
* Picked up Brad's deliniting and variable argument changes
* [92/08/10 mrt]
*
* Revision 1.13 92/02/08 18:04:44 dlc
* Once again revised localhost(). Do not use gethostbyname() at
* all, but assume that the host names in the coll.host file are at
* least a prefix of the fully qualified name. Modcoll (and related
* scripts) will maintain this fact.
* [92/02/08 dlc]
*
* Revision 1.12 91/08/17 23:35:31 dlc
* Changes to localhost() function:
* - Use host name in kernel for local host name; assume it is
* fully qualified.
* - If gethostbyname() of host to see if we are the repository
* fails, with TRY_AGAIN or NO_RECOVERY, then use the "host"
* parameter. Print a diagnostic in this case.
* [91/08/17 dlc]
*
* Revision 1.11 90/04/04 10:53:01 dlc
* Changed localhost to retry getting the local host name 4 times with
* 30 second sleep intervals before aborting; after 4 tries, things are
* probably too messed up for the supscan to do anything useful
* [90/04/04 dlc]
*
* Revision 1.10 89/08/03 19:49:33 mja
* Updated to use v*printf() in place of _doprnt().
* [89/04/19 mja]
*
* Revision 1.9 89/06/18 14:41:37 gm0w
* Fixed up some notify messages of errors to use "SUP:" prefix.
* [89/06/18 gm0w]
*
* 13-May-88 Glenn Marcy (gm0w) at Carnegie-Mellon University
* Changed goaway to longjmp back to top-level to scan next
* collection. [V7.6]
*
* 19-Feb-88 Glenn Marcy (gm0w) at Carnegie-Mellon University
* Added -f <filename> switch to scan all (or part) of the
* collections in a file of collection/base-directory pairs.
* [V7.5]
*
* 27-Dec-87 Glenn Marcy (gm0w) at Carnegie-Mellon University
* Removed nameserver support (which means to use a new
* datafile).
*
* 09-Sep-87 Glenn Marcy (gm0w) at Carnegie-Mellon University
* Use case-insensitive hostname comparison.
*
* 28-Jun-87 Glenn Marcy (gm0w) at Carnegie-Mellon University
* Added code for "release" support. [V6.4]
*
* 05-Jan-86 Glenn Marcy (gm0w) at Carnegie-Mellon University
* Changed collection setup errors to be non-fatal. [V5.3]
*
* 29-Dec-85 Glenn Marcy (gm0w) at Carnegie-Mellon University
* Moved most of the scanning code to scan.c. [V4.2]
*
* 02-Nov-85 Glenn Marcy (gm0w) at Carnegie-Mellon University
* Added "-s" option.
*
* 22-Sep-85 Glenn Marcy (gm0w) at Carnegie-Mellon University
* Merged 4.1 and 4.2 versions together.
*
* 04-Jun-85 Steven Shafer (sas) at Carnegie-Mellon University
* Created for 4.2 BSD.
*
**********************************************************************
*/
#include <libc.h>
#include <c.h>
#include <netdb.h>
#include <setjmp.h>
#ifdef __STDC__
#include <stdarg.h>
#else
#include <varargs.h>
#endif
#include <sys/time.h>
#include <sys/param.h>
#include "supcdefs.h"
#include "supextern.h"
#define PGMVERSION 6
/*******************************************
*** D A T A S T R U C T U R E S ***
*******************************************/
struct scan_collstruct { /* one per collection to be upgraded */
char *Cname; /* collection name */
char *Cbase; /* local base directory */
char *Cprefix; /* local collection pathname prefix */
struct scan_collstruct *Cnext; /* next collection */
};
typedef struct scan_collstruct SCAN_COLLECTION;
/*********************************************
*** G L O B A L V A R I A B L E S ***
*********************************************/
int trace; /* -v flag */
int quiet; /* -q flag */
SCAN_COLLECTION *firstC; /* collection list pointer */
char *collname; /* collection name */
char *basedir; /* base directory name */
char *prefix; /* collection pathname prefix */
time_t lasttime = 0; /* time of last upgrade */
time_t scantime; /* time of this scan */
int newonly = FALSE; /* new files only */
jmp_buf sjbuf; /* jump location for errors */
TREELIST *listTL; /* list of all files specified by <coll>.list */
TREE *listT; /* final list of files in collection */
TREE *refuseT = NULL; /* list of all files specified by <coll>.list */
void usage __P((void));
void init __P((int, char **));
static SCAN_COLLECTION *getscancoll __P((char *, char *, char *));
int localhost __P((char *));
int main __P((int, char **));
/*************************************
*** M A I N R O U T I N E ***
*************************************/
int
main (argc,argv)
int argc;
char **argv;
{
SCAN_COLLECTION *c;
#if __GNUC__
/* Avoid longjmp clobbering */
(void) &c;
#endif
init (argc,argv); /* process arguments */
for (c = firstC; c; c = c->Cnext) {
collname = c->Cname;
basedir = c->Cbase;
prefix = c->Cprefix;
(void) chdir (basedir);
scantime = time ((time_t *)NULL);
if (!quiet)
printf ("SUP Scan for %s starting at %s",collname,
ctime (&scantime));
(void) fflush (stdout);
if (!setjmp (sjbuf)) {
makescanlists (); /* record names in scan files */
scantime = time ((time_t *)NULL);
if (!quiet)
printf ("SUP Scan for %s completed at %s",
collname, ctime (&scantime));
} else
fprintf(stderr,
"SUP: Scan for %s aborted at %s",collname,
ctime (&scantime));
if (!quiet)
(void) fflush (stdout);
}
while ((c = firstC) != NULL) {
firstC = firstC->Cnext;
free (c->Cname);
free (c->Cbase);
if (c->Cprefix) free (c->Cprefix);
free ((char *)c);
}
exit (0);
}
/*****************************************
*** I N I T I A L I Z A T I O N ***
*****************************************/
void
usage ()
{
fprintf (stderr,"Usage: supscan [ -vq ] collection [ basedir ]\n");
fprintf (stderr," supscan [ -vq ] -f dirfile\n");
fprintf (stderr," supscan [ -vq ] -s\n");
exit (1);
}
void
init (argc,argv)
int argc;
char **argv;
{
char buf[STRINGLENGTH],fbuf[STRINGLENGTH],*p,*q;
FILE *f;
SCAN_COLLECTION **c;
int fflag,sflag;
char *filename = NULL;
quiet = FALSE;
trace = FALSE;
fflag = FALSE;
sflag = FALSE;
while (argc > 1 && argv[1][0] == '-') {
switch (argv[1][1]) {
case 'f':
fflag = TRUE;
if (argc == 2)
usage ();
--argc;
argv++;
filename = argv[1];
break;
case 'q':
quiet = TRUE;
break;
case 'v':
trace = TRUE;
break;
case 's':
sflag = TRUE;
break;
default:
fprintf (stderr,"supscan: Invalid flag %s ignored\n",
argv[1]);
(void) fflush (stderr);
}
--argc;
argv++;
}
if (!fflag) {
(void) sprintf (fbuf,FILEDIRS,DEFDIR);
filename = fbuf;
}
if (sflag) {
if (argc != 1)
usage ();
firstC = NULL;
c = &firstC;
(void) sprintf (buf,FILEHOSTS,DEFDIR);
if ((f = fopen (buf,"r")) == NULL)
quit (1,"supscan: Unable to open %s\n",buf);
while ((p = fgets (buf,STRINGLENGTH,f)) != NULL) {
q = index (p,'\n');
if (q) *q = 0;
if (index ("#;:",*p)) continue;
collname = nxtarg (&p," \t=");
p = skipover (p," \t=");
if (!localhost (p)) continue;
*c = getscancoll(filename,salloc (collname),
(char *)NULL);
if (*c) c = &((*c)->Cnext);
}
(void) fclose (f);
return;
}
if (argc < 2 && fflag) {
firstC = NULL;
c = &firstC;
if ((f = fopen (filename,"r")) == NULL)
quit (1,"supscan: Unable to open %s\n",filename);
while ((p = fgets (buf,STRINGLENGTH,f)) != NULL) {
q = index (p,'\n');
if (q) *q = 0;
if (index ("#;:",*p)) continue;
q = nxtarg (&p," \t=");
p = skipover (p," \t=");
*c = getscancoll(filename,salloc (q),salloc (p));
if (*c) c = &((*c)->Cnext);
}
(void) fclose (f);
return;
}
if (argc < 2 || argc > 3)
usage ();
firstC = getscancoll(filename,salloc (argv[1]),
argc > 2 ? salloc (argv[2]) : (char *)NULL);
}
static SCAN_COLLECTION *
getscancoll(filename, collname, basedir)
register char *filename,*collname,*basedir;
{
char buf[STRINGLENGTH],*p,*q;
FILE *f;
SCAN_COLLECTION *c;
if (basedir == NULL) {
if ((f = fopen (filename,"r")) != NULL) {
while ((p = fgets (buf,STRINGLENGTH,f)) != NULL) {
q = index (p,'\n');
if (q) *q = 0;
if (index ("#;:",*p)) continue;
q = nxtarg (&p," \t=");
if (strcmp (q,collname) == 0) {
p = skipover (p," \t=");
basedir = salloc (p);
break;
}
}
(void) fclose (f);
}
if (basedir == NULL) {
(void) sprintf (buf,FILEBASEDEFAULT,collname);
basedir = salloc (buf);
}
}
if (chdir(basedir) < 0) {
fprintf (stderr,"supscan: Can't chdir to base directory %s for %s\n",
basedir,collname);
return (NULL);
}
prefix = NULL;
(void) sprintf (buf,FILEPREFIX,collname);
if ((f = fopen (buf,"r")) != NULL) {
while ((p = fgets (buf,STRINGLENGTH,f)) != NULL) {
q = index (p,'\n');
if (q) *q = 0;
if (index ("#;:",*p)) continue;
prefix = salloc (p);
if (chdir(prefix) < 0) {
fprintf (stderr,"supscan: can't chdir to %s from base directory %s for %s\n",
prefix,basedir,collname);
return (NULL);
}
break;
}
(void) fclose (f);
}
if ((c = (SCAN_COLLECTION *) malloc (sizeof(SCAN_COLLECTION))) == NULL)
quit (1,"supscan: can't malloc collection structure\n");
c->Cname = collname;
c->Cbase = basedir;
c->Cprefix = prefix;
c->Cnext = NULL;
return (c);
}
void
#ifdef __STDC__
goaway (char *fmt,...)
#else
/*VARARGS*//*ARGSUSED*/
goaway (va_alist)
va_dcl
#endif
{
va_list ap;
#ifdef __STDC__
va_start(ap,fmt);
#else
char *fmt;
va_start(ap);
fmt = va_arg(ap,char *);
#endif
vfprintf(stderr, fmt, ap);
va_end(ap);
(void) putc ('\n',stderr);
(void) fflush (stderr);
longjmp (sjbuf,TRUE);
}
int localhost (host)
register char *host;
{
static char myhost[MAXHOSTNAMELEN + 1];
static int myhostlen;
register int hostlen;
if (*myhost == '\0') {
/*
* We assume that the host name in the kernel is the
* fully qualified form.
*/
if (gethostname (myhost,sizeof (myhost)) < 0) {
quit (1,"supscan: can't get kernel host name\n");
}
myhost[sizeof(myhost) - 1] = '\0';
myhostlen = strlen(myhost);
}
/*
* Here, we assume that the 'host' parameter from the
* coll.host file is at least a prefix of the fully qualified
* host name of some machine. This will be true when modcoll(8)
* (and related scripts) maintain the relevant files, but if
* a person makes a manual change, problems could result. In
* particular, if a nicname, such as "Y" for "GANDALF.CS.CMU.EDU"
* is present in the coll.host file, things will not work as
* expected.
*/
hostlen = strlen(host);
return(strncasecmp (myhost,
host,
hostlen < myhostlen ? hostlen : myhostlen) == 0);
}