ftp.nice.ch/pub/next/unix/mail/smail3.1.20.s.tar.gz#/smail3.1.20/pd/uuwho/uuwho.c

This is uuwho.c in view mode; [Download] [Up]

/* @(#)pd/uuwho/uuwho.c	1.2 24 Oct 1990 05:19:37 */
/*
 * uuwho:
 *	store/retrieve uucp map info in dbm format
 *
 * uuwho uses a dbm file with pointers into the real map files,
 * hence initialization MUST be done any time a map file has changed.
 *
 * usage:
 *   initialize:  uuwho -i [-d dbmfile] mapfile ...
 *   retrieve  :  uuwho [-d dbmfile] [sitename ...]
 *
 * NOTE: this program requires DBM
 *
 * Based on a program written by someone in the public domain,
 * which was then ported to System V by Gordon Moffett, which 
 * was then improved by Landon Noll, which was then re-written
 * again to fit into the smail system.
 */

#include <stdio.h>
#include "defs.h"

#ifdef HAVE_DBM
#ifdef UNIX_SYS5
#include <sys/utsname.h>
#endif /* UNIX_SYS5 */
#undef NULL		/* dbm.h often defines NULL */
#include <dbm.h>
#undef NULL		/* in case dbm.h does not define NULL */
#define NULL 0

#define NLEN	255	/* max sitename length */
#define W_DBM "uuwho" /* database basename in SMAIL_LIB_DIR */

char *cmdname;		/* same as argv[0] */

/* variable length record stored in who database */
typedef struct {
	long	pos;
	char	name[NLEN+1];	/* NLEN+1 is max size, is often smaller */
} position;

datum fileinfo;
datum sitename;
void dbmtouch();	/* be sure that the .dir and .pag files exist */
void printmap();	/* print a map form using the location form dbm */
char *get_hostname();	/* get our histname */
char line[BUFSIZ + 1];
FILE *fp;

extern char *strcpy();
extern int errno;	/* last system error */

main(argc, argv)
    int argc;
    char *argv[];
{
    char *fbasename=W_DBM;	/* database basename */
    char *fname;		/* database filename */
    char *hostname=NULL;	/* != NULL ==> only print hostname */
    char *malloc();		/* mem allocator */
    char *realloc();		/* mem expander */
    int opt;			/* flag char */
    int namelen;		/* length of sitename */
    int newdbm = 0;		/* 1 ==> new database creation is requested */
    position *p;		/* the fetched record */
    extern char *optarg;	/* the arg of a flag */
    extern int optind;		/* the first non flag */
    
    /*
     * parse args
     */
    cmdname = argv[0];
    while ((opt = getopt(argc,argv,"id:")) != EOF) {
	switch (opt) {
	case 'i':	/* new database being formed */
	    newdbm = 1;
	    break;
	case 'd':
	    fbasename = optarg;
	    break;
	case '?':
	    usage();
	    break;
	}
    }
    if (newdbm == 1 && optind >= argc) {
	usage();			/* -i flag must have args */
    } else if (newdbm == 0 && optind >= argc) {
	/* looking now for the hostname, get it */
	hostname = get_hostname();
    }
    
    /*
     * open the database
     */
    if (fbasename[0] == '/' || fbasename[0] == '.') {
	fname = fbasename;
    } else {
	fname = malloc(strlen(SMAIL_LIB_DIR)+1+strlen(fbasename)+1);
	if (fname == NULL) {
	    perror(cmdname);
	    exit(1);
	}
	sprintf(fname, "%s/%s", SMAIL_LIB_DIR, fbasename);
    }
    dbmtouch(fname,newdbm);
    if (dbminit(fname) < 0) {
	fprintf(stderr, "%s: dbminit(%s) failed\n", cmdname, fname);
	exit(2);
    }
    
    /*
     * process each map or site
     */
    do {
	
	/*
	 * if we are initializing a database, just load each file
	 */
	if (newdbm) {
	    getfile(argv[optind]); /* add entries to database */
	    
	    
	    /*
	     * we are not loading but rather doing a querry, so look it up
	     */
	} else {
	    /*
	     * try to fetch something from the database
	     */
	    sitename.dptr = (hostname) ? hostname : argv[optind];
	    namelen = strlen(sitename.dptr);
	    sitename.dsize = namelen > NLEN ? NLEN : namelen;
	    fileinfo = fetch(sitename);
	    
	    /*
	     * did we fetch something from the database?  If so, process it
	     */
	    if ((p = (position *)fileinfo.dptr) == (position *)NULL) {
		/* no entry found, complain */
		fprintf(stderr, "no site entry for %s\n", sitename.dptr);
	    } else {
		printmap(p);
	    }
	}
    } while (++optind < argc);
    
    /* end of the show */
    exit(0);
}

/*
 * printmap - print a map file
 */
void
printmap(p)
    position *p;		/* the fetched record */
{
    int comment;		/* 1 ==> within a #comment set */
    int pathdata;		/* 1 ==> have seen path data */
    int ctr = 0;		/* >0 ==> we have a new #N record */
    char *cp;			/* pointer */
    char *tp;			/* pointer */
    char c;			/* the char we are looking at */
    char unknown[2];		/* unknown #x line name */
    
    /*
     * open the file
     */
    if ((fp = fopen(p->name, "r")) == (FILE *)NULL) {
	fprintf(stderr, "%s: Can't open data file %s\n",
		cmdname, p->name);
	return;
    }
    
    /* seek to the starting location in the file */
    fseek(fp, p->pos, 0);
    
    /*
     * process the entry one line at a time
     */
    pathdata = 0;	/* no path data seen yet */
    comment = 0;	/* not in a #comment set */
    unknown[1] = '\0';	/* terminate string */
    while (fgets(line, BUFSIZ, fp)) {
	
	/* always print non # (route) lines */
	if (*(cp = line) != '#') {
	    pathdata = 1; /* we have seen path data */
	    /* deal with trailing #comments */
	    if ( comment != 0 ) {
		putchar('\n');
		comment = 0; /* no more comments */
	    }
	    fputs(line, stdout);
	    continue;
	}
	
	/* skip the '#' */
	++cp;
	
	/* print out #<space>, #<tab> and #\n lines always */
	if (*cp == ' ' || *cp == '\t' || *cp == '\n') {
	    /* deal with #comment white spacing */
	    if ( pathdata == 0 && comment == 0 ) {
		/* white space before #comment set */
		putchar('\n');
		/* we have seen #comment lines */
		comment = 1;
	    }
	    fputs(line, stdout);
	    continue;
	    /* turn of #comment white spacing if needed */
	} else if ( pathdata == 0 && comment != 0 ) {
	    putchar('\n');
	    comment = 0; /* no more comments */
	}
	
	/* note if it is another #N line */
	if (*cp == 'N' && ctr++) {
	    /* a new entry, so stop reading */
	    break;
	}
	
	/* skip the x in #x, saving x in the process */
	c = *cp;
	if (*cp != '\n' && *cp != '\0') {
	    ++cp;
	}
	
	/* skip white space after #x for later use */
	while (*cp == ' ' || *cp == '\t') {
	    ++cp;
	}
	
	/* determine the name of the #X line */
	switch (c) {
	case 'N':
	    tp = "System name:";
	    break;
	case 'S':
	    tp = "System type:";
	    break;
	case 'F':
	    tp = "Arpa forwarder:";
	    break;
	case 'O':
	    tp = "Organization:";
	    break;
	case 'C':
	    tp = "Contact person:";
	    break;
	case 'E':
	    tp = "Email Address:";
	    break;
	case 'T':
	    tp = "Telephone:";
	    break;
	case 'P':
	    tp = "Postal Address:";
	    break;
	case 'L':
	    tp = "Long/Lat:";
	    break;
	case 'R':
	    tp = "Remarks:";
	    break;
	case 'U':
	    tp = "News links:";
	    break;
	case 'W':
	    tp = "Author & date:";
	    break;
	case '\t': /* line starts at #<tab>, special case */
	case '\n': /* line just as a #, special case */
	    tp = 0;
	    break;
	default: /* unknown #x line */
	    unknown[0] = c;
	    tp = unknown;
	    break;
	}
	
	/* print the #X line name and contents */
	printf("%-16.16s %s", tp, cp);
    }
    fclose(fp);
}

/*
 * get a file and install it in the who database
 */
getfile(filename)
    char *filename;			/* the file to add */
{
    register char *cp;		/* pointer */
    register int namelen;	/* length of sitename */
    static int input=0;		/* 1 ==> already read input */
    char *malloc();		/* storage allocator */
    int linelen;		/* the length of the current line */
    long pos = 0;		/* current file position */
    position pp;		/* the variable length record to save */
    
    /* try to open the new file */
    if (input == 0 && strcmp(filename, "-") == 0) {
	fp = stdin;
	input = 1;
	filename = "[stdin]";
    } else if (input == 1 && strcmp(filename, "-") == 0) {
	fprintf(stderr,
		"%s: already processed standard input\n", cmdname);
	return;
    } else if ((fp = fopen(filename, "r")) == (FILE *)NULL) {
	fprintf(stderr, "%s: Can't open %s\n", cmdname, filename);
	return;
    }
    
    /*
     * build up a new database entry skelliten
     */
    fileinfo.dptr = (char *)&pp;
    fileinfo.dsize = sizeof(pp.pos) + strlen(filename) + 1;	/* real size */
    strcpy(pp.name, filename);
    
    /*
     * for each entry, note the position in the file
     */
    pos = 0; /* we start at the beginning */
    while (fgets(line, BUFSIZ, fp)) { /* one line at a time */
	char *p;		/* start of filename */
	char *q;		/* after filename */
	char *r;		/* pointer */
	
	/* watch for a file entry */
	if (strncmp(line, "file", 4) == 0) {
	    /* skip over whitespace */
	    p = line + 4 + strspn(&line[4], " \t\n");
	    /* skip over the opening { */
	    if (*p != '{') {
		continue;	/* not a useful line */
	    }
	    /* skip whitespace to find the filename */
	    p += strspn(p+1, " \t\n") + 1;
	    if (*p == '\0') {
		continue;	/* not a useful line */
	    }
	    /* find the end of the filename */
	    q = p + strcspn(p, " \t\n}");
	    if (*q == '\0') {
		continue;	/* not a useful line */
	    }
	    /* skip whitespace */
	    r = q + strspn(q, " \t\n");
	    /* skip over the closing } */
	    if (*r != '}') {
		continue;	/* not a useful line */
	    }
	    /* verify end of line */
	    if (*(r+1) != '\n' || *(r+2) != '\0') {
		continue;	/* not a useful line */
	    }
	    /* form new fileinfo module */
	    strncpy(pp.name, p, q-p);
	    pp.name[q-p] = '\0';
	    fileinfo.dsize = sizeof(pp.pos) + q-p + 1;
	    pos = 0;	/* assume beginning of the filename */
	    continue;
	}
	
	/* watch for a new entry */
	if (strncmp(line, "#N", 2) == 0) {
	    
	    /*
	     * we have new entry, determine the name
	     *
	     * note that lines are of the form:
	     * #N sitename
	     * #N name1, name2, ...
	     */
	    cp = line + 2; /* skip over #N */
	    while (1) {
		/* skip white space or ',' */
		cp += strspn(cp, " \t,");
		/* if no more #N names stop processing line */
		if (*cp == '\n') {
		    break;
		}
		/* note size of name */
		sitename.dptr = cp; /* name start addr */
		cp += strcspn(cp, "\n, \t");
		namelen = cp - sitename.dptr; /* length */
		/* limit name length for sanity */
		sitename.dsize = (namelen > NLEN) ? NLEN : namelen;
		/* note the file position of the #N line */
		pp.pos = pos;
		
		/*
		 * store the file/position info with the
		 * sitename as the fetch key
		 */
		store(sitename, fileinfo);
		/* process other sitenames on the line */
	    }
	}
	/* note the new position */
	linelen = strlen(line);
	if (linelen >= BUFSIZ-2) {	/* avoid excessively bogus lines */
	    fprintf(stderr,
		    "%s: %s has a line >= %d chars\n",
		    cmdname, filename, BUFSIZ-2);
	    exit(1);
	}
	pos += (long)linelen;
    }
    
    /* cleanup */
    fclose(fp);
}

/*
 * show command usage, and die
 */
usage()
{
    fprintf(stderr, "usage: %s [-d dbmfile] -i mapfile ...\n", cmdname);
    fprintf(stderr, "usage: %s [-d dbmfile] [sitename ...]\n", cmdname);
    exit(-1);
}

/*
 * dbmtouch - be sure that the dbm files .pag and .dir exist
 */
void
dbmtouch(name,wr)
    char *name;				/* basename of the dbm file */
    int wr;				/* 1=>open for writing, 0=> reading */
{
    char *malloc();
    char *filename;			/* the .dir and .pag names*/
    int fd;				/* .dir or .pag file */

    /*
     * form the namespace for filename
     */
    filename = malloc(strlen(name) + 4 + 1);
    if (filename == NULL) {
	perror(cmdname);
	exit(1);
    }
    
    /*
     * be sure that the .pag name exists
     */
    sprintf(filename, "%s.pag", name);
    fd = open(filename, wr);
    if (fd < 0 && ! wr) {
	fprintf(stderr, "%s: can not open %s\n", cmdname, filename);
	exit(1);
    } else if (fd < 0 && (fd = creat(filename, 0664)) < 0) {
	fprintf(stderr, "%s: can not create or write %s\n", cmdname, filename);
	exit(1);
    }
    close(fd);
    
    /*
     * be sure that the .dir name exists
     */
    sprintf(filename, "%s.dir", name);
    fd = open(filename, wr);
    if (fd < 0 && ! wr) {
	fprintf(stderr, "%s: can not open %s\n", cmdname, filename);
	exit(1);
    } else if (fd < 0 && (fd = creat(filename, 0664)) < 0) {
	fprintf(stderr, "%s: can not create or write %s\n", cmdname, filename);
	exit(1);
    }
    close(fd);
}

/*
 * get_hostname - get our hostname for a no arg querry
 */
#ifdef UNIX_BSD
char *
get_hostname()
{
    char *hostname;			/* who we are */
    char *malloc();			/* memory allocator */

    /*
     * My man page says that 255 chars (plus nul byte) is the limit
     * on length of the local host name.  There appears to be no
     * #define for it in 4.2BSD.
     */
    hostname = malloc(NLEN+1+1);
    if (hostname == NULL) {
	fprintf(stderr, "%s: bad mallof of hostname\n", cmdname);
	exit(3);
    }
    if (gethostname(hostname, NLEN+1) < 0) {
	hostname = NULL;		/* unknown hostname */
    }
    return(hostname);
}
#else	/* not UNIX_BSD */
# ifdef UNIX_SYS5
char *
get_hostname()
{
    static struct utsname utsname;

    (void) uname(&utsname);
    /* is the sysname tag used for something interesting? */
    return(utsname.nodename);
}
#else	/* not UNIX_SYS5 */
char *
get_hostname()
{
    return NULL;
}
# endif	/* UNIX_SYS5 */
#endif	/* not UNIX_BSD */

#else /* HAVE_DBM */	/* in case they have no dbm */

main(argc, argv)
    int argc;				/* arg count */
    char *argv[];			/* ars */
{
    fprintf(stderr, "%s: %s was not configured with DBM\n",
	    argv[0], argv[0]);
    exit(1);
}

#endif /* HAVE_DBM */

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.