home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 3 / 3339 / mkpasswd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-05-17  |  8.0 KB  |  381 lines

  1. /*
  2.  * Copyright 1990, John F. Haugh II
  3.  * All rights reserved.
  4.  *
  5.  * Permission is granted to copy and create derivative works for any
  6.  * non-commercial purpose, provided this copyright notice is preserved
  7.  * in all copies of source code, or included in human readable form
  8.  * and conspicuously displayed on all copies of object code or
  9.  * distribution media.
  10.  */
  11.  
  12. #include "config.h"
  13. #include <stdio.h>
  14. #include <fcntl.h>
  15. #include "pwd.h"
  16. #ifdef    BSD
  17. #include <strings.h>
  18. #define    strchr    index
  19. #define    strrchr    rindex
  20. #else
  21. #include <string.h>
  22. #endif
  23.  
  24. #if !defined(DBM) && !defined(NDBM)
  25. What you are trying to do?  You have to have a DBM of some kind ...
  26. #endif
  27.  
  28. #ifdef    DBM
  29. #include <dbm.h>
  30. #endif
  31. #ifdef    NDBM
  32. #include <ndbm.h>
  33. #include <grp.h>
  34. #include "shadow.h"
  35.  
  36. DBM    *pw_dbm;
  37. DBM    *gr_dbm;
  38. DBM    *sp_dbm;
  39. DBM    *sgr_dbm;
  40. #endif
  41.  
  42. #ifndef    lint
  43. static    char    sccsid[] = "@(#)mkpasswd.c    3.4    11:29:08    12/19/90";
  44. static    char    copyright[] = "Copyright 1990, John F. Haugh II";
  45. #endif
  46.  
  47. char    *CANT_OPEN =    "%s: cannot open file %s\n";
  48. char    *CANT_OVERWRITE = "%s: cannot overwrite file %s\n";
  49. char    *CANT_CREATE =    "%s: cannot create %s\n";
  50. char    *DBM_OPEN_ERR =    "%s: cannot open DBM files for %s\n";
  51. char    *PARSE_ERR =    "%s: error parsing line\n\"%s\"\n";
  52. char    *LINE_TOO_LONG = "%s: the beginning with \"%.16s ...\" is too long\n";
  53. char    *ADD_REC =    "adding record for name \"%s\"\n";
  54. char    *ADD_REC_ERR =    "%s: error adding record for \"%s\"\n";
  55. char    *INFO =        "added %d entries, longest was %d\n";
  56. #ifdef    NDBM
  57. char    *USAGE =    "Usage: %s [ -vf ] [ -p|g|sp|sg ] file\n";
  58. #else
  59. char    *USAGE =    "Usage: %s [ -vf ] file\n";
  60. #endif
  61.  
  62. char    *Progname;
  63. int    vflg = 0;
  64. int    fflg = 0;
  65. #ifdef    NDBM
  66. int    gflg = 0;
  67. int    sflg = 0;
  68. int    pflg = 0;
  69. #endif
  70.  
  71. void    usage();
  72.  
  73. extern    char    *malloc();
  74. extern    struct    passwd    *sgetpwent();
  75. #ifdef    NDBM
  76. extern    struct    group    *sgetgrent();
  77. extern    struct    spwd    *sgetspent();
  78. extern    struct    sgrp    *sgetsgent();
  79. #endif
  80.  
  81. /*
  82.  * mkpasswd - create DBM files for /etc/passwd-like input file
  83.  *
  84.  * mkpasswd takes an an argument the name of a file in /etc/passwd format
  85.  * and creates a DBM file keyed by user ID and name.  The output files have
  86.  * the same name as the input file, with .dir and .pag appended.
  87.  *
  88.  * if NDBM is defined this command will also create look-aside files for
  89.  * /etc/group, /etc/shadow, and /etc/gshadow.
  90.  */
  91.  
  92. int
  93. main (argc, argv)
  94. int    argc;
  95. char    **argv;
  96. {
  97.     extern    int    optind;
  98.     extern    char    *optarg;
  99.     FILE    *fp;            /* File pointer for input file        */
  100.     char    *file;            /* Name of input file                 */
  101.     char    *dir;            /* Name of .dir file                  */
  102.     char    *pag;            /* Name of .pag file                  */
  103.     char    *cp;            /* Temporary character pointer        */
  104.     int    flag;            /* Flag for command line option       */
  105.     int    fd;            /* File descriptor of open DBM file   */
  106.     int    cnt = 0;        /* Number of entries in database      */
  107.     int    longest = 0;        /* Longest entry in database          */
  108.     int    len;            /* Length of input line               */
  109.     int    errors = 0;        /* Count of errors processing file    */
  110.     char    buf[BUFSIZ*8];        /* Input line from file               */
  111.     struct    passwd    *passwd;    /* Pointer to password file entry     */
  112. #ifdef    NDBM
  113.     struct    group    *group;        /* Pointer to group file entry        */
  114.     struct    spwd    *shadow;    /* Pointer to shadow passwd entry     */
  115.     struct    sgrp    *gshadow;    /* Pointer to shadow group entry      */
  116.     DBM    *dbm;            /* Pointer to new NDBM files          */
  117. #endif
  118.  
  119.     /*
  120.      * Figure out what my name is.  I will use this later ...
  121.      */
  122.  
  123.     if (Progname = strrchr (argv[0], '/'))
  124.         Progname++;
  125.     else
  126.         Progname = argv[0];
  127.  
  128.     /*
  129.      * Figure out what the flags might be ...
  130.      */
  131.  
  132. #ifdef    NDBM
  133.     while ((flag = getopt (argc, argv, "fvpgs")) != EOF)
  134. #else
  135.     while ((flag = getopt (argc, argv, "fv")) != EOF)
  136. #endif
  137.     {
  138.         switch (flag) {
  139.             case 'v':
  140.                 vflg++;
  141.                 break;
  142.             case 'f':
  143.                 fflg++;
  144.                 break;
  145. #ifdef    NDBM
  146.             case 'g':
  147.                 gflg++;
  148.                 if (pflg)
  149.                     usage ();
  150.  
  151.                 break;
  152.             case 's':
  153.                 sflg++;
  154.                 break;
  155.             case 'p':
  156.                 pflg++;
  157.                 if (gflg)
  158.                     usage ();
  159.  
  160.                 break;
  161. #endif
  162.             default:
  163.                 usage ();
  164.         }
  165.     }
  166.  
  167.     /*
  168.      * Backwards compatibility fix for -p flag ...
  169.      */
  170.  
  171.     if (! sflg && ! gflg)
  172.         pflg++;
  173.  
  174.     /*
  175.      * The last and only remaining argument must be the file name
  176.      */
  177.  
  178.     if (argc - 1 != optind)
  179.         usage ();
  180.  
  181.     file = argv[optind];
  182.  
  183.     if (! (fp = fopen (file, "r"))) {
  184.         fprintf (stderr, CANT_OPEN, Progname, file);
  185.         exit (1);
  186.     }
  187.  
  188.     /*
  189.      * Make the filenames for the two DBM files.
  190.      */
  191.  
  192.     dir = malloc (strlen (file) + 5);    /* space for .dir file */
  193.     strcat (strcpy (dir, file), ".dir");
  194.  
  195.     pag = malloc (strlen (file) + 5);    /* space for .pag file */
  196.     strcat (strcpy (pag, file), ".pag");
  197.  
  198.     /*
  199.      * Remove existing files if requested.
  200.      */
  201.  
  202.     if (fflg) {
  203.         (void) unlink (dir);
  204.         (void) unlink (pag);
  205.     }
  206.  
  207.     /*
  208.      * Create the two DBM files - it is an error for these files
  209.      * to have existed already.
  210.      */
  211.  
  212.     if (access (dir, 0) == 0) {
  213.         fprintf (stderr, CANT_OVERWRITE, Progname, dir);
  214.         exit (1);
  215.     }
  216.     if (access (pag, 0) == 0) {
  217.         fprintf (stderr, CANT_OVERWRITE, Progname, pag);
  218.         exit (1);
  219.     }
  220.  
  221. #ifdef    NDBM
  222.     if (sflg)
  223.         umask (077);
  224.     else
  225. #endif
  226.     umask (0);
  227. #ifdef    DBM
  228.     if ((fd = open (dir, O_RDWR|O_CREAT|O_EXCL, 0644)) == -1) {
  229.         fprintf (stderr, CANT_CREATE, Progname, dir);
  230.         exit (1);
  231.     } else
  232.         close (fd);
  233.  
  234.     if ((fd = open (pag, O_RDWR|O_CREAT|O_EXCL, 0644)) == -1) {
  235.         fprintf (stderr, CANT_CREATE, Progname, pag);
  236.         unlink (dir);
  237.         exit (1);
  238.     } else
  239.         close (fd);
  240. #endif
  241.  
  242.     /*
  243.      * Now the DBM database gets initialized
  244.      */
  245.  
  246. #ifdef    DBM
  247.     if (dbminit (file) == -1) {
  248.         fprintf (stderr, DBM_OPEN_ERR, Progname, file);
  249.         exit (1);
  250.     }
  251. #endif
  252. #ifdef    NDBM
  253.     if (! (dbm = dbm_open (file, O_RDWR|O_CREAT, 0644))) {
  254.         fprintf (stderr, DBM_OPEN_ERR, Progname, file);
  255.         exit (1);
  256.     }
  257.     if (gflg) {
  258.         if (sflg)
  259.             sgr_dbm = dbm;
  260.         else
  261.             gr_dbm = dbm;
  262.     } else {
  263.         if (sflg)
  264.             sp_dbm = dbm;
  265.         else
  266.             pw_dbm = dbm;
  267.     }
  268. #endif
  269.  
  270.     /*
  271.      * Read every line in the password file and convert it into a
  272.      * data structure to be put in the DBM database files.
  273.      */
  274.  
  275. #ifdef    NDBM
  276.     while (fgetsx (buf, BUFSIZ, fp) != NULL)
  277. #else
  278.     while (fgets (buf, BUFSIZ, fp) != NULL)
  279. #endif
  280.     {
  281.  
  282.         /*
  283.          * Get the next line and strip off the trailing newline
  284.          * character.
  285.          */
  286.  
  287.         buf[sizeof buf - 1] = '\0';
  288.         if (! (cp = strchr (buf, '\n'))) {
  289.             fprintf (stderr, LINE_TOO_LONG, Progname, buf);
  290.             exit (1);
  291.         }
  292.         *cp = '\0';
  293.         len = strlen (buf);
  294.  
  295.         /*
  296.          * Parse the password file line into a (struct passwd).
  297.          * Erroneous lines cause error messages, but that's
  298.          * all.  YP lines are ignored completely.
  299.          */
  300.  
  301.         if (buf[0] == '-' || buf[0] == '+')
  302.             continue;
  303.  
  304. #ifdef    DBM
  305.         if (! (passwd = sgetpwent (buf)))
  306. #endif
  307. #ifdef    NDBM
  308.         if (! (((! sflg && pflg) && (passwd = sgetpwent (buf)))
  309.             || ((sflg && pflg) && (shadow = sgetspent (buf)))
  310.             || ((! sflg && gflg) && (group = sgetgrent (buf)))
  311.             || ((sflg && gflg) && (gshadow = sgetsgent (buf)))))
  312. #endif
  313.         {
  314.             fprintf (stderr, PARSE_ERR, Progname, buf);
  315.             errors++;
  316.             continue;
  317.         }
  318. #ifdef    DBM
  319.         if (vflg)
  320.             printf (ADD_REC, passwd->pw_name);
  321.  
  322.         if (! pw_dbm_update (passwd))
  323.             fprintf (stderr, ADD_REC_ERR,
  324.                 Progname, passwd->pw_name);
  325. #endif
  326. #ifdef    NDBM
  327.         if (vflg) {
  328.             if (!sflg && pflg) printf (ADD_REC, passwd->pw_name);
  329.             if (sflg && pflg) printf (ADD_REC, shadow->sp_namp);
  330.             if (!sflg && gflg) printf (ADD_REC, group->gr_name);
  331.             if (sflg && gflg) printf (ADD_REC, gshadow->sg_name);
  332.         }
  333.         if (! sflg && pflg && ! pw_dbm_update (passwd))
  334.             fprintf (stderr, ADD_REC_ERR,
  335.                 Progname, passwd->pw_name);
  336.  
  337.         if (sflg && pflg && ! sp_dbm_update (shadow))
  338.             fprintf (stderr, ADD_REC_ERR,
  339.                 Progname, shadow->sp_namp);
  340.  
  341.         if (! sflg && gflg && ! gr_dbm_update (group))
  342.             fprintf (stderr, ADD_REC_ERR,
  343.                 Progname, group->gr_name);
  344.  
  345.         if (sflg && gflg && ! sgr_dbm_update (gshadow))
  346.             fprintf (stderr, ADD_REC_ERR,
  347.                 Progname, gshadow->sg_name);
  348. #endif
  349.  
  350.         /*
  351.          * Update the longest record and record count
  352.          */
  353.  
  354.         if (len > longest)
  355.             longest = len;
  356.         cnt++;
  357.     }
  358.  
  359.     /*
  360.      * Tell the user how things went ...
  361.      */
  362.  
  363.     if (vflg)
  364.         printf (INFO, cnt, longest);
  365.  
  366.     exit (errors);
  367.     /*NOTREACHED*/
  368. }
  369.  
  370. /*
  371.  * usage - print error message and exit
  372.  */
  373.  
  374. void
  375. usage ()
  376. {
  377.     fprintf (stderr, USAGE, Progname);
  378.     exit (1);
  379.     /*NOTREACHED*/
  380. }
  381.