home *** CD-ROM | disk | FTP | other *** search
/ back2roots/padua / padua.7z / padua / uucp / auucp+-1.02 / fuucp_plus_src.lzh / uuwho.c < prev   
Encoding:
C/C++ Source or Header  |  1990-11-21  |  13.9 KB  |  583 lines

  1. /* @(#)uuwho.c    1.13 12/18/88 21:28:55 */
  2. /*
  3.  * uuwho:
  4.  *    store/retrieve uucp map info in dbm format
  5.  *
  6.  * uuwho uses a dbm file with pointers into the real map files,
  7.  * hence initialization MUST be done any time a map file has changed.
  8.  *
  9.  * usage:
  10.  *   initialize:  uuwho -i [-d dbmfile] mapfile ...
  11.  *   retrieve  :  uuwho [-d dbmfile] [sitename ...]
  12.  *
  13.  * NOTE: this program requires DBM
  14.  *
  15.  * Based on a program written by someone in the public domain,
  16.  * which was then ported to System V by Gordon Moffett, which 
  17.  * was then improved by Landon Noll, which was then re-written
  18.  * again to fit into the smail system.
  19.  */
  20.  
  21. #include <stdio.h>
  22. #ifndef AMIGA
  23. #include "defs.h"
  24. #endif
  25.  
  26. #define HAVE_DBM
  27. #define UNIX_BSD
  28. #define UULIB "UULib\0UULIB:"
  29.  
  30. void *memcpy(void *, void *, int);
  31.  
  32. #define memcpy __builtin_memcpy
  33. #define VERDATE " 1.00 (26 Aug 90) "
  34.  
  35. static char *version20 = "$VER: uuwho" VERDATE "\n\r";
  36.  
  37. #ifdef HAVE_DBM
  38. #ifdef UNIX_SYS5
  39. #include <sys/utsname.h>
  40. #endif /* UNIX_SYS5 */
  41. #undef NULL        /* dbm.h often defines NULL */
  42. #include "work:unixlib/dbm/dbm.h"
  43. #undef NULL        /* in case dbm.h does not define NULL */
  44. #define NULL 0
  45.  
  46. #define NLEN    255    /* max sitename length */
  47. #define W_DBM "uuwho" /* database basename in SMAIL_LIB_DIR */
  48.  
  49. char *cmdname;        /* same as argv[0] */
  50.  
  51. /* variable length record stored in who database */
  52. typedef struct {
  53.     long    pos;
  54.     char    name[NLEN+1];    /* NLEN+1 is max size, is often smaller */
  55. } position;
  56.  
  57. datum fileinfo;
  58. datum sitename;
  59. void dbmtouch();    /* be sure that the .dir and .pag files exist */
  60. void printmap();    /* print a map form using the location form dbm */
  61. char *get_hostname();    /* get our histname */
  62. char line[BUFSIZ + 1];
  63. FILE *fp;
  64.  
  65. extern char *strcpy();
  66. extern int errno;    /* last system error */
  67.  
  68. main(argc, argv)
  69.     int argc;
  70.     char *argv[];
  71. {
  72.     char *fbasename=W_DBM;    /* database basename */
  73.     char *fname;        /* database filename */
  74.     char *hostname=NULL;    /* != NULL ==> only print hostname */
  75.     char *malloc();        /* mem allocator */
  76.     char *realloc();        /* mem expander */
  77.     int opt;            /* flag char */
  78.     int namelen;        /* length of sitename */
  79.     int newdbm = 0;        /* 1 ==> new database creation is requested */
  80.     position *p;        /* the fetched record */
  81.     extern char *optarg;    /* the arg of a flag */
  82.     extern int optind;        /* the first non flag */
  83.     
  84.     /*
  85.      * parse args
  86.      */
  87.     cmdname = argv[0];
  88.     while ((opt = getopt(argc,argv,"id:")) != EOF) {
  89.     switch (opt) {
  90.     case 'i':    /* new database being formed */
  91.         newdbm = 1;
  92.         break;
  93.     case 'd':
  94.         fbasename = optarg;
  95.         break;
  96.     case '?':
  97.         usage();
  98.         break;
  99.     }
  100.     }
  101.     if (newdbm == 1 && optind >= argc) {
  102.     usage();            /* -i flag must have args */
  103.     } else if (newdbm == 0 && optind >= argc) {
  104.     /* looking now for the hostname, get it */
  105.     hostname = get_hostname();
  106.     }
  107.     
  108.     /*
  109.      * open the database
  110.      */
  111. #ifndef AMIGA
  112.     if (fbasename[0] == '/' || fbasename[0] == '.') {
  113.     fname = fbasename;
  114.     } else {
  115.     fname = malloc(strlen(SMAIL_LIB_DIR)+1+strlen(fbasename)+1);
  116.     if (fname == NULL) {
  117.         perror(cmdname);
  118.         exit(1);
  119.     }
  120.     sprintf(fname, "%s/%s", SMAIL_LIB_DIR, fbasename);
  121.     }
  122. #else
  123.     {
  124.       char *MakeConfigPath();
  125.       fname = MakeConfigPath(UULIB, fbasename);
  126.     }
  127. #endif
  128.  
  129.     dbmtouch(fname,newdbm);
  130.     if (dbminit(fname) < 0) {
  131.     fprintf(stderr, "%s: dbminit(%s) failed\n", cmdname, fname);
  132.     exit(2);
  133.     }
  134.     
  135.     /*
  136.      * process each map or site
  137.      */
  138.     do {
  139.     
  140.     /*
  141.      * if we are initializing a database, just load each file
  142.      */
  143.     if (newdbm) {
  144.         getfile(argv[optind]); /* add entries to database */
  145.         
  146.         
  147.         /*
  148.          * we are not loading but rather doing a querry, so look it up
  149.          */
  150.     }
  151.         else
  152.         {
  153.         /*
  154.          * try to fetch something from the database
  155.          */
  156.         sitename.dptr = (hostname) ? hostname : argv[optind];
  157.         namelen = strlen(sitename.dptr);
  158.         sitename.dsize = namelen > NLEN ? NLEN : namelen;
  159.         fileinfo = fetch(sitename);
  160.     
  161.         /*
  162.          * did we fetch something from the database?  If so, process it
  163.          */
  164.         if (fileinfo.dptr == (char *)NULL) {
  165.         /* no entry found, complain */
  166.         fprintf(stderr, "no site entry for %s\n", sitename.dptr);
  167.         }
  168.             else
  169.             {
  170.                 p = (position *)malloc(sizeof(position));
  171.                 if(p != (position *)NULL)
  172.                 {
  173.                   memcpy(p, fileinfo.dptr, sizeof(position)); /* align */
  174.           printmap(p);
  175.                 }
  176.                 else
  177.                 {
  178.                   fprintf(stderr, "Out of mem\n");
  179.                   exit(-1);
  180.                 }
  181.         }
  182.     }
  183.     } while (++optind < argc);
  184.     
  185.     /* end of the show */
  186.     exit(0);
  187. }
  188.  
  189. /*
  190.  * printmap - print a map file
  191.  */
  192. void
  193. printmap(p)
  194.     position *p;        /* the fetched record */
  195. {
  196.     int comment;        /* 1 ==> within a #comment set */
  197.     int pathdata;        /* 1 ==> have seen path data */
  198.     int ctr = 0;        /* >0 ==> we have a new #N record */
  199.     char *cp;            /* pointer */
  200.     char *tp;            /* pointer */
  201.     char c;            /* the char we are looking at */
  202.     char unknown[2];        /* unknown #x line name */
  203.     
  204.     /*
  205.      * open the file
  206.      */
  207.     if ((fp = fopen(p->name, "r")) == (FILE *)NULL) {
  208.     fprintf(stderr, "%s: Can't open data file %s\n",
  209.         cmdname, p->name);
  210.     return;
  211.     }
  212.     
  213.     /* seek to the starting location in the file */
  214.     fseek(fp, p->pos, 0);
  215.     
  216.     /*
  217.      * process the entry one line at a time
  218.      */
  219.     pathdata = 0;    /* no path data seen yet */
  220.     comment = 0;    /* not in a #comment set */
  221.     unknown[1] = '\0';    /* terminate string */
  222.     while (fgets(line, BUFSIZ, fp)) {
  223.     
  224.     /* always print non # (route) lines */
  225.     if (*(cp = line) != '#') {
  226.         pathdata = 1; /* we have seen path data */
  227.         /* deal with trailing #comments */
  228.         if ( comment != 0 ) {
  229.         putchar('\n');
  230.         comment = 0; /* no more comments */
  231.         }
  232.         fputs(line, stdout);
  233.         continue;
  234.     }
  235.     
  236.     /* skip the '#' */
  237.     ++cp;
  238.     
  239.     /* print out #<space>, #<tab> and #\n lines always */
  240.     if (*cp == ' ' || *cp == '\t' || *cp == '\n') {
  241.         /* deal with #comment white spacing */
  242.         if ( pathdata == 0 && comment == 0 ) {
  243.         /* white space before #comment set */
  244.         putchar('\n');
  245.         /* we have seen #comment lines */
  246.         comment = 1;
  247.         }
  248.         fputs(line, stdout);
  249.         continue;
  250.         /* turn of #comment white spacing if needed */
  251.     } else if ( pathdata == 0 && comment != 0 ) {
  252.         putchar('\n');
  253.         comment = 0; /* no more comments */
  254.     }
  255.     
  256.     /* note if it is another #N line */
  257.     if (*cp == 'N' && ctr++) {
  258.         /* a new entry, so stop reading */
  259.         break;
  260.     }
  261.     
  262.     /* skip the x in #x, saving x in the process */
  263.     c = *cp;
  264.     if (*cp != '\n' && *cp != '\0') {
  265.         ++cp;
  266.     }
  267.     
  268.     /* skip white space after #x for later use */
  269.     while (*cp == ' ' || *cp == '\t') {
  270.         ++cp;
  271.     }
  272.     
  273.     /* determine the name of the #X line */
  274.     switch (c) {
  275.     case 'N':
  276.         tp = "System name:";
  277.         break;
  278.     case 'S':
  279.         tp = "System type:";
  280.         break;
  281.     case 'F':
  282.         tp = "Arpa forwarder:";
  283.         break;
  284.     case 'O':
  285.         tp = "Organization:";
  286.         break;
  287.     case 'C':
  288.         tp = "Contact person:";
  289.         break;
  290.     case 'E':
  291.         tp = "Email Address:";
  292.         break;
  293.     case 'T':
  294.         tp = "Telephone:";
  295.         break;
  296.     case 'P':
  297.         tp = "Postal Address:";
  298.         break;
  299.     case 'L':
  300.         tp = "Long/Lat:";
  301.         break;
  302.     case 'R':
  303.         tp = "Remarks:";
  304.         break;
  305.     case 'U':
  306.         tp = "News links:";
  307.         break;
  308.     case 'W':
  309.         tp = "Author & date:";
  310.         break;
  311.     case '\t': /* line starts at #<tab>, special case */
  312.     case '\n': /* line just as a #, special case */
  313.         tp = 0;
  314.         break;
  315.     default: /* unknown #x line */
  316.         unknown[0] = c;
  317.         tp = unknown;
  318.         break;
  319.     }
  320.     
  321.     /* print the #X line name and contents */
  322.     printf("%-16.16s %s", tp, cp);
  323.     }
  324.     fclose(fp);
  325. }
  326.  
  327. /*
  328.  * get a file and install it in the who database
  329.  */
  330. getfile(filename)
  331.     char *filename;            /* the file to add */
  332. {
  333.     register char *cp;        /* pointer */
  334.     register int namelen;    /* length of sitename */
  335.     static int input=0;        /* 1 ==> already read input */
  336.     char *malloc();        /* storage allocator */
  337.     int linelen;        /* the length of the current line */
  338.     long pos = 0;        /* current file position */
  339.     position pp;        /* the variable length record to save */
  340.     
  341.     /* try to open the new file */
  342.     if (input == 0 && strcmp(filename, "-") == 0) {
  343.     fp = stdin;
  344.     input = 1;
  345.     filename = "[stdin]";
  346.     } else if (input == 1 && strcmp(filename, "-") == 0) {
  347.     fprintf(stderr,
  348.         "%s: already processed standard input\n", cmdname);
  349.     return;
  350.     } else if ((fp = fopen(filename, "r")) == (FILE *)NULL) {
  351.     fprintf(stderr, "%s: Can't open %s\n", cmdname, filename);
  352.     return;
  353.     }
  354.     
  355.     /*
  356.      * build up a new database entry skelliten
  357.      */
  358.     fileinfo.dptr = (char *)&pp;
  359.     fileinfo.dsize = sizeof(pp.pos) + strlen(filename) + 1;    /* real size */
  360.     strcpy(pp.name, filename);
  361.     
  362.     /*
  363.      * for each entry, note the position in the file
  364.      */
  365.     pos = 0; /* we start at the beginning */
  366.     while (fgets(line, BUFSIZ, fp)) { /* one line at a time */
  367.     char *p;        /* start of filename */
  368.     char *q;        /* after filename */
  369.     char *r;        /* pointer */
  370.     
  371.     /* watch for a file entry */
  372.     if (strncmp(line, "file", 4) == 0) {
  373.         /* skip over whitespace */
  374.         p = line + 4 + strspn(&line[4], " \t\n");
  375.         /* skip over the opening { */
  376.         if (*p != '{') {
  377.         continue;    /* not a useful line */
  378.         }
  379.         /* skip whitespace to find the filename */
  380.         p += strspn(p+1, " \t\n") + 1;
  381.         if (*p == '\0') {
  382.         continue;    /* not a useful line */
  383.         }
  384.         /* find the end of the filename */
  385.         q = p + strcspn(p, " \t\n}");
  386.         if (*q == '\0') {
  387.         continue;    /* not a useful line */
  388.         }
  389.         /* skip whitespace */
  390.         r = q + strspn(q, " \t\n");
  391.         /* skip over the closing } */
  392.         if (*r != '}') {
  393.         continue;    /* not a useful line */
  394.         }
  395.         /* verify end of line */
  396.         if (*(r+1) != '\n' || *(r+2) != '\0') {
  397.         continue;    /* not a useful line */
  398.         }
  399.         /* form new fileinfo module */
  400.         strncpy(pp.name, p, q-p);
  401.         pp.name[q-p] = '\0';
  402.         fileinfo.dsize = sizeof(pp.pos) + q-p + 1;
  403.         pos = 0;    /* assume beginning of the filename */
  404.         continue;
  405.     }
  406.     
  407.     /* watch for a new entry */
  408.     if (strncmp(line, "#N", 2) == 0) {
  409.         
  410.         /*
  411.          * we have new entry, determine the name
  412.          *
  413.          * note that lines are of the form:
  414.          * #N sitename
  415.          * #N name1, name2, ...
  416.          */
  417.         cp = line + 2; /* skip over #N */
  418.         while (1) {
  419.         /* skip white space or ',' */
  420.         cp += strspn(cp, " \t,");
  421.         /* if no more #N names stop processing line */
  422.         if (*cp == '\n') {
  423.             break;
  424.         }
  425.         /* note size of name */
  426.         sitename.dptr = cp; /* name start addr */
  427.         cp += strcspn(cp, "\n, \t");
  428.         namelen = cp - sitename.dptr; /* length */
  429.         /* limit name length for sanity */
  430.         sitename.dsize = (namelen > NLEN) ? NLEN : namelen;
  431.         /* note the file position of the #N line */
  432.         pp.pos = pos;
  433.         
  434.         /*
  435.          * store the file/position info with the
  436.          * sitename as the fetch key
  437.          */
  438.         store(sitename, fileinfo);
  439.         /* process other sitenames on the line */
  440.         }
  441.     }
  442.     /* note the new position */
  443.     linelen = strlen(line);
  444.     if (linelen >= BUFSIZ-2) {    /* avoid excessively bogus lines */
  445.         fprintf(stderr,
  446.             "%s: %s has a line >= %d chars\n",
  447.             cmdname, filename, BUFSIZ-2);
  448.         exit(1);
  449.     }
  450.     pos += (long)linelen;
  451.     }
  452.     
  453.     /* cleanup */
  454.     fclose(fp);
  455. }
  456.  
  457. /*
  458.  * show command usage, and die
  459.  */
  460. usage()
  461. {
  462.     fprintf(stderr, "AmigaUUCP Plus: uuwho" VERDATE "\n");
  463.     fprintf(stderr, "Written by Ingo Feulner\n\n");
  464.     fprintf(stderr, "usage: %s [-d dbmfile] -i mapfile ...\n", cmdname);
  465.     fprintf(stderr, "usage: %s [-d dbmfile] [sitename ...]\n", cmdname);
  466.     exit(-1);
  467. }
  468.  
  469. /*
  470.  * dbmtouch - be sure that the dbm files .pag and .dir exist
  471.  */
  472. void
  473. dbmtouch(name,wr)
  474.     char *name;                /* basename of the dbm file */
  475.     int wr;                /* 1=>open for writing, 0=> reading */
  476. {
  477.     char *filename;            /* the .dir and .pag names*/
  478.     int fd;                /* .dir or .pag file */
  479.  
  480.     /*
  481.      * form the namespace for filename
  482.      */
  483.     filename = malloc(strlen(name) + 4 + 1);
  484.     if (filename == NULL) {
  485.     perror(cmdname);
  486.     exit(1);
  487.     }
  488.     
  489.     /*
  490.      * be sure that the .pag name exists
  491.      */
  492.     sprintf(filename, "%s.pag", name);
  493.     fd = open(filename, wr);
  494.     if (fd < 0 && ! wr) {
  495.     fprintf(stderr, "%s: can not open %s\n", cmdname, filename);
  496.     exit(1);
  497.     } else if (fd < 0 && (fd = creat(filename, 0664)) < 0) {
  498.     fprintf(stderr, "%s: can not create or write %s\n", cmdname, filename);
  499.     exit(1);
  500.     }
  501.     close(fd);
  502.     
  503.     /*
  504.      * be sure that the .dir name exists
  505.      */
  506.     sprintf(filename, "%s.dir", name);
  507.     fd = open(filename, wr);
  508.     if (fd < 0 && ! wr) {
  509.     fprintf(stderr, "%s: can not open %s\n", cmdname, filename);
  510.     exit(1);
  511.     } else if (fd < 0 && (fd = creat(filename, 0664)) < 0) {
  512.     fprintf(stderr, "%s: can not create or write %s\n", cmdname, filename);
  513.     exit(1);
  514.     }
  515.     close(fd);
  516. }
  517.  
  518. /*
  519.  * get_hostname - get our hostname for a no arg querry
  520.  */
  521. #ifdef UNIX_BSD
  522. char *
  523. get_hostname()
  524. {
  525.     char *hostname;            /* who we are */
  526.     char *malloc();            /* memory allocator */
  527.  
  528.     /*
  529.      * My man page says that 255 chars (plus nul byte) is the limit
  530.      * on length of the local host name.  There appears to be no
  531.      * #define for it in 4.2BSD.
  532.      */
  533.     hostname = malloc(NLEN+1+1);
  534.     if (hostname == NULL) {
  535.     fprintf(stderr, "%s: bad mallof of hostname\n", cmdname);
  536.     exit(3);
  537.     }
  538. #ifndef AMIGA
  539.     if (gethostname(hostname, NLEN+1) < 0) {
  540.     hostname = NULL;        /* unknown hostname */
  541.     }
  542. #else
  543.     {
  544.       char *FindConfig();
  545.  
  546.       hostname = FindConfig("NodeName");
  547.     }
  548. #endif
  549.     return(hostname);
  550. }
  551. #else    /* not UNIX_BSD */
  552. # ifdef UNIX_SYS5
  553. char *
  554. get_hostname()
  555. {
  556.     static struct utsname utsname;
  557.  
  558.     (void) uname(&utsname);
  559.     /* is the sysname tag used for something interesting? */
  560.     return(utsname.nodename);
  561. }
  562. #else    /* not UNIX_SYS5 */
  563. char *
  564. get_hostname()
  565. {
  566.     return NULL;
  567. }
  568. # endif    /* UNIX_SYS5 */
  569. #endif    /* not UNIX_BSD */
  570.  
  571. #else /* HAVE_DBM */    /* in case they have no dbm */
  572.  
  573. main(argc, argv)
  574.     int argc;                /* arg count */
  575.     char *argv[];            /* ars */
  576. {
  577.     fprintf(stderr, "%s: %s was not configured with DBM\n",
  578.         argv[0], argv[0]);
  579.     exit(1);
  580. }
  581.  
  582. #endif /* HAVE_DBM */
  583.