home *** CD-ROM | disk | FTP | other *** search
/ Jason Aller Floppy Collection / 125.img / PRO-C4.ZIP / BENCH1.ZIP / BENCH / LOGINMOD.C < prev    next >
Encoding:
C/C++ Source or Header  |  1990-05-28  |  19.8 KB  |  1,032 lines

  1. /* ---( bench/loginmod.c )------------------------ */
  2. /* Pro-C - Copyright (C) 1988, 1989 Vestronix Inc. */
  3. /* Modification to this source is not supported    */
  4. /* by Vestronix Inc.                               */
  5. /*            All Rights Reserved                  */
  6. /* ----------------------------------------------- */
  7. /* Written   JZ      Jan-87                        */
  8. /* Modified  Nig   30-Jan-90                       */
  9. /* ----------------------------------------------- */
  10. /* %W%  (%H% %T%) */
  11.  
  12. /*
  13.  *  Modifications
  14.  *
  15.  *  30-Jan-90  Nig - Rearranged the Change Password setup
  16. */
  17.  
  18. #include <stdio.h>
  19. #include <bench.h>
  20. #include <errno.h>
  21. #include <proc.io>
  22. #include <fileio.h>
  23. #include <dllist.h>
  24. #include <field.h>
  25. #include <passwd.h>
  26.  
  27. # include <time.h>
  28.  
  29. # define TRUE 1
  30. # define FALSE 0
  31.  
  32. # define MYVER "2.0"
  33. # define MAXLOCKTRYS 10
  34.  
  35. /*
  36.  * GLOBAL DEFINES
  37. */
  38.  
  39. #define USER 0
  40. #define MODULE 1
  41.  
  42. PERMS pperms[] =
  43. {
  44.     {    'a',    PERM_ADD            },
  45.     {    'c',    PERM_CHANGE        },
  46.     {    'd',    PERM_DELETE        },
  47.     {    'i',    PERM_INQUIRE    },
  48.     {    0,        0                    }
  49. };
  50.  
  51. extern int  ichar; /* Global INPUT_W Return Value - 0 for CR */
  52. static int keymatch = USER;
  53.  
  54. int uhand;
  55. int mhand;
  56. USER_ENT tmpuser;
  57. MOD_ENT tmpmod;
  58. USER_ENT *tmpuptr;
  59. MOD_ENT *tmpmptr;
  60. char buffer[80];
  61. char pwdfile[128];
  62. char pwdtmpf[128];
  63. char pswdfile_path[128];
  64. int tempfd;
  65.  
  66. char userfield_mask[] = "xxxxxxxxxxxxxx";
  67.  
  68. FIELD userfield = {
  69.     0, 
  70.     0,
  71.     1,
  72.     NULL, 
  73.     userfield_mask,
  74.     0,
  75.     NAMELEN,
  76.     F_TEXT,
  77.     REVVID,
  78.     NORMAL,
  79.     BLANK_FIELD,
  80.     NULL,
  81.     text_input,
  82.     NULL,
  83.     NULL
  84. };
  85.  
  86. char modfield_mask[] = "BQQQQQQQQQQQQQ";
  87.  
  88. FIELD modfield = {
  89.     0, 
  90.     0,
  91.     1,
  92.     NULL,
  93.     modfield_mask,
  94.     0,
  95.     MODLEN,
  96.     F_TEXT,
  97.     REVVID,
  98.     NORMAL,
  99.     BLANK_FIELD,
  100.     NULL,
  101.     text_input,
  102.     NULL,
  103.     NULL
  104. };
  105.  
  106. char pwdfield_mask[] = "!!!!!!!!";
  107.  
  108. FIELD pwdfield = {
  109.     0, 
  110.     0,
  111.     1,
  112.     NULL,
  113.     pwdfield_mask,
  114.     0,
  115.     PWDLEN,
  116.     F_TEXT,
  117.     REVVID,
  118.     NORMAL,
  119.     BLANK_FIELD,
  120.     NULL,
  121.     text_input,
  122.     NULL,
  123.     NULL
  124. };
  125.  
  126.  
  127. unsigned int checkperms(prjname, argc, argv, user, password)
  128. char *prjname;
  129. int argc;
  130. char *argv[];
  131. char *user;
  132. char *password;
  133. {
  134.     unsigned int newperms = PERM_INIT;
  135.     char *module;
  136.     int retry;
  137.     int chgflag = FALSE;
  138.     int i,j;
  139.  
  140.     setvars(prjname);
  141.  
  142.     module = basename(argv[0]);        /* Figure out module name from argv[0] */
  143.  
  144.     /* 
  145.      * Input user info if not already passed to program 
  146.      *
  147.      * -cp indicates the user wants to change his password
  148.     */
  149.     if ((argc == 1) || ((argc == 2) && (!strcmp("-cp", argv[1])))) 
  150.     {
  151.         if (argc == 2) 
  152.             chgflag = TRUE;
  153.         input_pwd(user, password);
  154.     }
  155.     else 
  156.     {
  157.         strcpy(user, argv[1]);
  158.         strcpy(password, argv[2]);
  159.         decrypt(password, PASSKEY);
  160.     }
  161.  
  162.     if (chgflag) 
  163.     {
  164.         newperms = readfile();
  165.         if (newperms == PERM_NOTMPFILE || newperms == PERM_LOCKED) 
  166.         {
  167.             errmsg("Password change cannot be made now.  Try again later.");
  168.             chgflag = FALSE;
  169.             newperms = PERM_INIT;
  170.         }
  171.     }
  172.  
  173.     do 
  174.     {
  175.         newperms = passwd(pwdfile, user, password, module);
  176.  
  177.         retry = FALSE;
  178.         /* validate user's password and determine perms in this module */
  179.         if (chgflag)         /* use list operations */
  180.         {
  181.             strcpy(tmpuser.user, user);
  182.             strcpy(tmpuser.pwd, password);
  183.             if ((newperms == PERM_INIT) && (tmpuptr = (USER_ENT *)dll_find(uhand, &tmpuser))) 
  184.             {
  185.                 if (!strcmp(tmpuser.pwd, tmpuptr->pwd)) 
  186.                 {
  187.                     newperms = PERM_EXISTS;
  188.                     strcpy(tmpmod.mod, module);
  189.                     for (tmpmptr = (MOD_ENT *)dll_find(mhand, &tmpmod);
  190.                          tmpmptr != (MOD_ENT *)0 && (!strcmp(tmpmptr->mod, tmpmod.mod));
  191.                           tmpmptr = (MOD_ENT *)dll_next(mhand)) 
  192.                     {
  193.                         if (!strcmp(tmpuser.user, tmpmptr->user)) 
  194.                         {
  195.                             for (j = 0; tmpmptr->perm[j]; j++) 
  196.                             {
  197.                                 for (i = 0; pperms[i].code; i++)
  198.                                     if (pperms[i].code == tmpmptr->perm[j]) 
  199.                                         newperms |= pperms[i].perms;
  200.                             }
  201.                         }
  202.                     }
  203.                 }
  204.             }
  205.         }
  206.         switch (newperms) 
  207.         {
  208.         case PERM_NOFILE:
  209.             if (chgflag) 
  210.             {
  211.                 unlink(pwdtmpf);
  212.                 close(tempfd);
  213.             }
  214.  
  215.         case PERM_NOACC:
  216.             errmsg("Password file \"%s\" is not readable!  See system administrator.", pwdfile);
  217.             break;
  218.  
  219.         case PERM_INVFILE:
  220.             errmsg("Password file \"%s\" is invalid.  See system administrator.", pwdfile);
  221.             break;
  222.  
  223.         default:
  224.             if (newperms <= PERM_NONE) 
  225.             {
  226.                 if ((retry = warning(99, "Incorrect Login.\nTry Again ?")))
  227.                     input_pwd(user, password);
  228.                 else 
  229.                 {
  230.                     if (chgflag) 
  231.                     {
  232.                         unlink(pwdtmpf);
  233.                         close(tempfd);
  234.                     }
  235.                 }
  236.             }
  237.         }
  238.     }
  239.     while (retry);
  240.  
  241.     if (chgflag)
  242.     {
  243.         chg_win(tmpuser.user, tmpuser.pwd);
  244.         dll_del(uhand);
  245.         dll_add(uhand, &tmpuser, ADD_SORT);
  246.         writefile();
  247.         strcpy(password, tmpuser.pwd);
  248.         decrypt(password, PASSKEY);
  249.     }
  250.  
  251.     encrypt(password, PASSKEY);
  252.     return(newperms);
  253. }
  254.  
  255.  
  256. /* Remove the . extension from a filename */
  257. char *basename(name)
  258. char *name;
  259. {
  260.     int i,j;
  261.     int len = strlen(name);
  262.  
  263.     buffer[79]=0;
  264.     for (i = len, j = 79; ((i > 0) && (j > 0)); i--, j--) 
  265.     {
  266.         if (name[i - 1] == '/' || name[i - 1] == '\\' || name[i - 1] == ':')
  267.             break;
  268.         if (name[i - 1] == '.')
  269.             buffer[j - 1] = 0;
  270.         else
  271.             buffer[j - 1] = name[i - 1];
  272.     }
  273.  
  274. #ifdef MSDOS
  275.     strlwr(buffer + j);
  276. #endif
  277.  
  278.     return(buffer + j);
  279. }
  280.  
  281.  
  282. /* Create a window to input user name and password */
  283. void input_pwd(user, password)
  284. char *user;
  285. char *password;
  286. {
  287.     create_w(8, 20, 8, 40);
  288.     border_w(0, NORMAL);
  289.     disp_w(2, 3, NORMAL, "This Module Is Password Protected.");
  290.     disp_w(3, 3, NORMAL, "Please Enter Your Password Below.");
  291.     disp_w(5, 3, NORMAL, "User Name:");
  292.     disp_w(6, 3, NORMAL, "Password:");
  293.  
  294.     userfield.frow = 5;
  295.     userfield.fcol = 20;
  296.     userfield.fhelp= 12;
  297.     userfield.fbuff = tmpuser.user;
  298.     *userfield.fbuff = 0;
  299.     input_wx(&userfield, K_ESC, 0);
  300.     if (ichar == K_ESC)
  301.     {
  302.         *user = '\0';
  303.         delete_w();
  304.         return;
  305.     }
  306.     strcpy(user, userfield.fbuff);
  307.     
  308.     pwdfield.frow = 6;
  309.     pwdfield.fcol = 20;
  310.     pwdfield.fhelp = 13;
  311.     pwdfield.fbuff = password;
  312.     *pwdfield.fbuff = 0;
  313.     input_wx(&pwdfield, 0);
  314.  
  315.     delete_w();
  316. }
  317.  
  318.  
  319. /* 
  320.  * Create window to input new password
  321. */
  322. void chg_win(user, password)
  323. char *user;
  324. char *password;
  325. {
  326.     char password2[PWDARLEN];
  327.     int conspwd = FALSE;
  328.  
  329.     create_w(10, 19, 6, 44);
  330.     border_w(0, NORMAL);
  331.     disp_w(2, 3, NORMAL, "Input New Password for");
  332.     disp_w(2, 26, NORMAL, user);
  333.     disp_w(4, 3, NORMAL, "Password:");
  334.     disp_w(5, 3, NORMAL, "Password:");
  335.  
  336.     /* 
  337.      * Input 2 passwords until they are consistent. Passwords are not 
  338.      *    shown on the screen.
  339.     */
  340.     while (ichar != K_ESC && !conspwd) 
  341.     {
  342.         pwdfield.frow = 4;
  343.         pwdfield.fcol = 20;
  344.         pwdfield.fhelp = 14;
  345.         pwdfield.fbuff = password;
  346.         *password = 0;
  347.         while (!*password) 
  348.             input_wx(&pwdfield, K_ESC, 0);
  349.         if (ichar != K_ESC) 
  350.         {
  351.             encrypt(password, PASSKEY);
  352.             pwdfield.frow = 5;
  353.             pwdfield.fcol = 20;
  354.             pwdfield.fhelp = 1;
  355.             pwdfield.fbuff = password2;
  356.             *password2 = 0;
  357.             while (!*password2) 
  358.                 input_wx(&pwdfield, K_ESC, 0);
  359.             encrypt(password2, PASSKEY);
  360.         }
  361.         if (ichar != K_ESC) 
  362.         {
  363.             conspwd = (!bytecmp(password, password2, PWDLEN));
  364.             if (!conspwd)
  365.                 errmsg("Passwords were not consistent.  Please re-enter.");
  366.         }
  367.     }
  368.  
  369.     delete_w();
  370. }
  371.  
  372.  
  373. /* 
  374.  * Parse through password file to validate user and password and obtain
  375.  * the user's coded permissions in module
  376. */
  377. unsigned int passwd(file, user, pswd, module)
  378. char *file;
  379. char *user;
  380. char *pswd;
  381. char *module;
  382. {
  383.     FILE *fp;
  384.     unsigned int perms = PERM_INIT;
  385.     char *ptr;
  386.     int c;
  387.     int pswd_ok = FALSE;
  388.  
  389.     if (!access(file, 04)) 
  390.     {
  391.         if (fp = fopen(file, "r"))
  392.         {
  393.             if (validfile(fp)) 
  394.             {
  395.                 for (;;)
  396.                 {
  397.                     /* investigate the first non-space on the line */
  398.                     c = eatspace(fp);
  399.         
  400.                     /* end of file */
  401.                     if (c == EOF && feof(fp))
  402.                         break;
  403.         
  404.                     /* is this a comment or empty line ? */
  405.                     if (c == '#' || c == '\n')
  406.                         eatline(fp);
  407.  
  408.                     /* should be a good line */
  409.                     else
  410.                     {
  411.                         ptr = parsename(fp);
  412.                         switch (strlen(ptr) == 1 && eatspace(fp) == ':' ? ptr[0] : '#')
  413.                         {
  414.                             case '0':
  415.                                 if (pswd_ok)
  416.                                     eatline(fp);
  417.                                 else
  418.                                     pswd_ok = parseuser(fp, user, pswd);
  419.                                 break;
  420.  
  421.                             case '1':
  422.                                 if (pswd_ok)
  423.                                     perms |= parseperms(fp, user, module);
  424.                                 else
  425.                                     eatline(fp);
  426.                                 break;
  427.  
  428.                             default:
  429.                                 eatline(fp);
  430.                                 break;
  431.                         }
  432.                     }
  433.                 }
  434.  
  435.                 if (!pswd_ok)
  436.                     perms |= PERM_NONE;
  437.             }
  438.             else
  439.                 perms = PERM_INVFILE;
  440.             fclose(fp);
  441.         }
  442.         else
  443.             perms = PERM_NOACC;
  444.     }
  445.     else 
  446.     {
  447.         if (errno == ENOENT)
  448.             perms = PERM_NOFILE;
  449.         else
  450.             perms = PERM_NOACC;
  451.     }
  452.  
  453.     return(perms);
  454. }
  455.  
  456.  
  457. /* 
  458.  * Parse the string in the filestream only allowing name characters
  459.  * ie. only alpha, numeric, or '_' characters allowed
  460.  * Returns pointer to static buffer where name is stored.
  461. */
  462. char *parsename(fp)
  463. FILE *fp;
  464. {
  465.     int len, c;
  466.  
  467.     eatspace(fp);
  468.  
  469.     len = 0;
  470.     c = getc(fp);
  471.     while ( isalnum(c) || c == '_') 
  472.     {
  473.         if (len < sizeof(buffer) - 1)
  474.             buffer[len++] = (char) c;
  475.         c = getc(fp);
  476.     }
  477.     buffer[len] = 0;
  478.  
  479.     if (c != EOF || !feof(fp)) 
  480.         ungetc(c, fp);
  481.  
  482.     return(buffer);
  483. }
  484.  
  485.  
  486. /* 
  487.  * Parse the password in the filestream
  488. */
  489. char *parsepwd(fp)
  490. FILE *fp;
  491. {
  492.     int len;
  493.  
  494.     for( len = 0; len < PWDLEN; buffer[len++] = getc(fp) );
  495.  
  496.     return(buffer);
  497. }
  498.  
  499. /* 
  500.  * Parse the string in the filestream up to the next ':', newline or 
  501.  *    end-of-file.  Returns pointer to static buffer in which string is 
  502.  * stored.
  503. */
  504. char *parsestr(fp)
  505. FILE *fp;
  506. {
  507.     int len, pos, c;
  508.  
  509.     eatspace(fp);
  510.  
  511.     len = pos = 0;
  512.     while ((c = getc(fp)), (c != ':' && c != '\n' && (c != EOF || !feof(fp))))
  513.         if (len < sizeof(buffer) - 1)
  514.         {
  515.             buffer[len++] = (char) c;
  516.             if (c != ' ' && c != '\t')
  517.                 pos = len;
  518.         }
  519.     buffer[pos] = 0;
  520.  
  521.     if (c != EOF || !feof(fp))
  522.         ungetc(c, fp);
  523.  
  524.     return(buffer);
  525. }
  526.  
  527.  
  528. /* 
  529.  * Advance the filestream pointer to the next non-space character
  530. */
  531. int eatspace(fp)
  532. FILE *fp;
  533. {
  534.     int c;
  535.  
  536.     while ((c = getc(fp)) == ' ' || c == '\t')
  537.         ;
  538.  
  539.     if (c != EOF || !feof(fp))
  540.         ungetc(c, fp);
  541.  
  542.     return(c);
  543. }
  544.  
  545. /* 
  546.  * Advance the filestream pointer to the next line    
  547. */
  548. int eatline(fp)
  549. FILE *fp;
  550. {
  551.     int c;
  552.  
  553.     while ((c = getc(fp)), c != '\n' && (c != EOF || !feof(fp)))
  554.         ;
  555.  
  556.     return(c);
  557. }
  558.  
  559.  
  560. /* 
  561.  * Parse a user line in the password file returning TRUE if the input
  562.  *    user and password match those in the password file line.
  563. */
  564. int parseuser(fp, user, pswd)
  565. FILE *fp;
  566. char *user;
  567. char *pswd;
  568. {
  569.     char *tmp;
  570.     char pout[PWDARLEN];
  571.     int pswd_ok = FALSE;
  572.  
  573.     getc(fp);
  574.     tmp = parsename(fp);
  575.     if (tmp && *tmp && eatspace(fp) == ':' && !strcmp(user, tmp))
  576.     {
  577.         getc(fp);
  578.         tmp = parsepwd(fp);
  579.         decrypt(tmp, PASSKEY);
  580.         strcpy(pout, tmp);
  581.  
  582.         if (tmp && *tmp)
  583.             pswd_ok = (strcmp(pswd, pout) == 0);
  584.  
  585.         getc(fp);
  586.         tmp = parsestr(fp);
  587.     }
  588.  
  589.     eatline(fp);
  590.  
  591.     return(pswd_ok);
  592. }
  593.  
  594.  
  595. /* 
  596.  * Parse a module line in the password file.
  597.  * If the user and module given match those found in the line, the coded
  598.  * permissions are returned.  Otherwise, the code for PERM_EXISTS is 
  599.  * returned.
  600.  */
  601. unsigned int parseperms(fp, user, module)
  602. FILE *fp;
  603. char *user;
  604. char *module;
  605. {
  606.     char *tmp, *ptr;
  607.     int c, i;
  608.     unsigned int tmpperms, perms = PERM_EXISTS;
  609.  
  610.     getc(fp);
  611.     tmp = parsename(fp);    
  612.     /* Only continue if modules match */
  613.     if (tmp && *tmp && eatspace(fp) == ':' && !strcmp(module, tmp))
  614.     {
  615.         getc(fp);
  616.         tmp = parsestr(fp);
  617.         if (tmp && *tmp && eatspace(fp) == ':')
  618.         {
  619.             getc(fp);
  620.             tmpperms = PERM_EXISTS;
  621.             /* Read in perms, convert them to an int, and store for later */
  622.             for (ptr = tmp; *ptr; ptr++)
  623.             {
  624.                 c = *ptr;
  625.                 c = isupper(c) ? tolower(c) : c;
  626.                 for (i = 0; pperms[i].code; i++) 
  627.                     if (pperms[i].code == (char) c)
  628.                         tmpperms |= pperms[i].perms;
  629.             }
  630.             for (;;)        /* Parse through all associated users */
  631.             {
  632.                 tmp = parsename(fp);
  633.                 if (!tmp || !*tmp)
  634.                     break;
  635.                 else if (!strcmp(user, tmp)) 
  636.                 /* Continue only if user names match */
  637.                 {
  638.                     perms = tmpperms;
  639.                     break;
  640.                 }
  641.                 if (eatspace(fp) == ',')
  642.                     getc(fp);
  643.                 else
  644.                     break;
  645.             }
  646.         }
  647.     }
  648.  
  649.     eatline(fp);
  650.  
  651.     return(perms);
  652. }
  653.  
  654.  
  655. /* 
  656.  * Read the password file into 2 lists - a user list and a module list 
  657. */
  658. int readfile() 
  659. {
  660.     FILE *fp;
  661.     int c;
  662.     char *ptr;
  663.     int stat = PERM_INIT;
  664.     int i;
  665.  
  666.     tempfd = TCRT_FILE(pwdtmpf);
  667.     for (i = 0; i < MAXLOCKTRYS && tempfd < 0 && errno == EEXIST; i++)
  668.         tempfd = TCRT_FILE(pwdtmpf);
  669.     if (tempfd < 0) 
  670.     {
  671.         if (errno == EEXIST) 
  672.             stat = PERM_LOCKED;
  673.         else 
  674.             stat = PERM_NOTMPFILE;
  675.     }
  676.     else 
  677.     {
  678.         if (!access(pwdfile, 06)) 
  679.         {
  680.             if (fp = fopen(pwdfile, "r"))
  681.             {
  682.                 if (validfile(fp)) 
  683.                 {
  684.                     zerorec(tmpuser.user, NAMEARLEN);
  685.                     zerorec(tmpuser.pwd, PWDARLEN);
  686.                     zerorec(tmpmod.mod, MODARLEN);
  687.                     zerorec(tmpmod.perm, PERMARLEN);
  688.                     zerorec(tmpmod.user, NAMEARLEN);
  689.     
  690.                     uhand = dll_open(usercmp, sizeof(USER_ENT));
  691.                     mhand = dll_open(modcmp, sizeof(MOD_ENT));
  692.     
  693.                     for (;;)
  694.                     {
  695.                         /* investigate the first non-space on the line */
  696.                         c = eatspace(fp);
  697.             
  698.                         /* end of file */
  699.                         if (c == EOF && feof(fp))
  700.                             break;
  701.     
  702.                         /* is this a comment or empty line ? */
  703.                         if (c == '#' || c == '\n')
  704.                             eatline(fp);
  705.     
  706.                         /* should be a good line */
  707.                         else
  708.                         {
  709.                             ptr = parsename(fp);
  710.                             switch (strlen(ptr) == 1 && eatspace(fp) == ':' ? ptr[0] : '#')
  711.                             {
  712.                                 case '0':    
  713.                                     getc(fp);
  714.                                     strcpy(tmpuser.user, parsename(fp));
  715.                                     if (strlen(tmpuser.user) && eatspace(fp) == ':') 
  716.                                     {
  717.                                         getc(fp);
  718.                                         strcpy(tmpuser.pwd, parsepwd(fp));
  719.                                         if (strlen(tmpuser.pwd))
  720.                                             dll_add(uhand, &tmpuser, ADD_SORT);
  721.                                     }
  722.                                     eatline(fp);
  723.                                     break;
  724.     
  725.                                 case '1':    
  726.                                     getc(fp);
  727.                                     strcpy(tmpmod.mod, parsename(fp));
  728.                                     if (strlen(tmpmod.mod) && eatspace(fp) == ':')
  729.                                     {
  730.                                         getc(fp);
  731.                                         strcpy(tmpmod.perm, parsename(fp));
  732.                                         if (strlen(tmpmod.perm) && eatspace(fp) == ':')
  733.                                         {
  734.                                             getc(fp);
  735.                                             strcpy(tmpmod.user, parsename(fp));
  736.                                             if (strlen(tmpmod.user)) 
  737.                                             {
  738.                                                 tmpmod.writeflag = FALSE;
  739.                                                 dll_add(mhand, &tmpmod, ADD_SORT);
  740.                                                 while (eatspace(fp) == ',') 
  741.                                                 {
  742.                                                     getc(fp);
  743.                                                     strcpy(tmpmod.user, parsename(fp));
  744.                                                     if (strlen(tmpmod.user)) 
  745.                                                     {
  746.                                                         tmpmod.writeflag = FALSE;
  747.                                                         dll_add(mhand, &tmpmod, ADD_SORT);
  748.                                                     }
  749.                                                 }
  750.                                             }
  751.                                         }
  752.                                     }
  753.                                     eatline(fp);
  754.                                     break;
  755.                             }
  756.                         }
  757.                     }
  758.                 }
  759.                 else 
  760.                     stat = PERM_INVFILE;
  761.                 fclose(fp);
  762.             }
  763.             else 
  764.                 stat = PERM_NOACC;
  765.         }
  766.         else 
  767.         {
  768.             if (errno == ENOENT)
  769.                 stat = PERM_NOFILE;
  770.             else
  771.                 stat = PERM_NOACC;
  772.         }
  773.         if (stat != PERM_INIT && stat != PERM_NOFILE) 
  774.         {
  775.             unlink(pwdtmpf);
  776.             close(tempfd);
  777.         }
  778.     }
  779.  
  780.     return(stat);
  781. }
  782.  
  783.  
  784. /* 
  785.  * Determines whether the password file is valid - based on a CRC check 
  786. */
  787. int validfile(fp)
  788. FILE *fp;
  789. {
  790. #ifdef CRC
  791.     int c;
  792.     char *crcstr;
  793.     long oldcrc;
  794.     long newcrc;
  795.     int valid = FALSE;
  796.     long datstart = 0L;
  797.  
  798.     /*
  799.      * Read the header information and ignore it for the crc check.
  800.      * The old crc is found on the first line that isn't a comment.
  801.     */
  802.     crcstr = alloc(sizeof(long) + 1);
  803.     /* investigate the first non-space on the line */
  804.     c = eatspace(fp);
  805.  
  806.     /* is this a comment or empty line ? */
  807.     while (c == '#' || c == '\n') {
  808.         eatline(fp);
  809.         c = eatspace(fp);
  810.     }
  811.     
  812.     /* end of file */
  813.     if (c == EOF && feof(fp))
  814.         valid = FALSE;
  815.     else
  816.     {
  817.         /* should be a good line - contains the old crc */
  818.         strcpy(crcstr, parsestr(fp));
  819.         datstart = ftell(fp);
  820.         oldcrc = atol(crcstr);
  821.  
  822.         /*
  823.          * The crc calculation ignores the header since it is composed of 
  824.          * comments but takes the remainder of the file into account.
  825.          */
  826.         newcrc = crc_calc(fp);
  827.     
  828.         if (oldcrc == newcrc)
  829.             valid = TRUE;
  830.         fflush(fp);
  831.         rewind(fp);
  832.         fseek(fp, datstart, 0);
  833.     }
  834.     return(valid);
  835. #else
  836.     return(TRUE);
  837. #endif
  838. }
  839.  
  840. /* 
  841.  * Write out the password file 
  842. */
  843. int writefile()
  844. {
  845.     FILE *fp;
  846.     int stat = IOGOOD;
  847.  
  848.     if (fp = fdopen(tempfd, "r+"))
  849.     {
  850. #ifdef CRC
  851.         writelist(fp);
  852.         fflush(fp);
  853.         rewind(fp);
  854. #endif
  855.         writehdr(fp);
  856.         writelist(fp);
  857.         fclose(fp);
  858.         unlink(pwdfile);
  859.         renfile(pwdtmpf, pwdfile);
  860.         chmod(pwdfile, 0666);
  861.     }
  862.     else 
  863.     {
  864.         errmsg("Couldn't open file for writing.");
  865.         stat = IOERROR;
  866.     }
  867.     return(stat);
  868. }
  869.         
  870. /* 
  871.  * Write the lists into the password file 
  872. */
  873. void writelist(fp) 
  874. FILE *fp;
  875. {
  876.     fprintf(fp, "\n# Users: <0>:<user-name>:<password>\n\n");
  877.     writeusers(fp);
  878.     fprintf(fp, "\n# Modules: <1>:<module-name>:<permissions>:[<name>[,<name>[...]]]\n\n"); 
  879.     writemods(fp);
  880.  
  881. }
  882.  
  883. /* 
  884.  * Write the password file header 
  885. */
  886. void writehdr(fp)
  887. FILE *fp;
  888. {
  889.     unsigned long crc;
  890.     unsigned long curtime;
  891.  
  892. #ifdef CRC
  893.     crc = crc_calc(fp);
  894.     fflush(fp);
  895.     rewind(fp);
  896. #endif
  897.     fprintf(fp, "# Version %s\n", MYVER);
  898.     time(&curtime);
  899.     fprintf(fp, "# Last Modified: %s\n", asctime(localtime(&curtime)));
  900. #ifdef CRC
  901.     l_to_a(buffer, crc, 10);
  902.     fprintf(fp, "%s\n\n", buffer);
  903. #endif
  904. }
  905.  
  906. /* 
  907.  * Write out the user list
  908. */
  909. void writeusers(fp)
  910. FILE *fp;
  911. {
  912.     for (tmpuptr = (USER_ENT *)dll_seek(uhand, 0, SEEK_SET); tmpuptr != (USER_ENT *)0; tmpuptr = (USER_ENT *)dll_next(uhand))
  913.     {
  914.         fprintf(fp, "0:%s:%s\n", tmpuptr->user, tmpuptr->pwd);
  915.     }
  916. }
  917.  
  918. /* 
  919.  * Write out the module list
  920. */
  921. void writemods(fp)
  922. FILE *fp;
  923. {
  924.     MOD_ENT *curwrptr;
  925.     struct dll_entry *curpos;
  926.  
  927.     for (curwrptr = (MOD_ENT *)dll_seek(mhand, 0, SEEK_SET); curwrptr != (MOD_ENT *)0; curwrptr = (MOD_ENT *)dll_next(mhand)) 
  928.     {
  929.         curwrptr->writeflag = FALSE;
  930.     }
  931.  
  932.     /* 
  933.      * Write multiple users with the same perms in a module on the same line 
  934.     */
  935.     for (curwrptr = (MOD_ENT *)dll_seek(mhand, 0, SEEK_SET); curwrptr != (MOD_ENT *)0; curwrptr = (MOD_ENT *)dll_next(mhand)) 
  936.     {
  937.         if (curwrptr->writeflag == FALSE) 
  938.         {
  939.             fprintf(fp, "1:%s:%s:%s", curwrptr->mod, curwrptr->perm, curwrptr->user);
  940.             curwrptr->writeflag = TRUE;
  941.             curpos = dll_getpos(mhand);
  942.             tmpmptr = (MOD_ENT *)dll_next(mhand);
  943.             while (tmpmptr != NULL && (!strcmp(tmpmptr->mod, curwrptr->mod))) {
  944.                 if (!cmpperms(curwrptr->perm, tmpmptr->perm)) 
  945.                 {
  946.                     tmpmptr->writeflag = TRUE;
  947.                     fprintf(fp, ",%s", tmpmptr->user);
  948.                 }
  949.                 tmpmptr = (MOD_ENT *)dll_next(mhand);
  950.             }
  951.             dll_setpos(mhand, curpos);
  952.             putc('\n', fp);
  953.             fflush(fp);
  954.         }
  955.     }
  956. }
  957.  
  958.  
  959. void setvars(prjname)
  960. char *prjname;
  961. {
  962.     search_path(prjname, pswdfile_path, ".pas");
  963.  
  964.     strcpy(pwdfile, pswdfile_path);    /* Build name of password file */
  965.     strcat(pwdfile, ".pas");
  966.     strcpy(pwdtmpf, pswdfile_path);    /* Build name of temporary password file */
  967.     strcat(pwdtmpf, ".tmp");
  968. }
  969.  
  970. /* 
  971.  * User list compare function 
  972. */
  973. int usercmp(u1, u2)
  974. USER_ENT *u1, *u2;
  975. {
  976.     return(strcmp(u1->user, u2->user));
  977. }
  978.  
  979. /* 
  980.  * Module list compare function 
  981. */
  982. int modcmp(m1, m2)
  983. MOD_ENT *m1, *m2;
  984. {
  985.     return(strcmp(m1->mod, m2->mod));
  986. }
  987.  
  988. /* 
  989.  * compare perms - strings are equivalent as long as the same perms
  990.  * occur in each string regardless of their order
  991. */
  992. int cmpperms(perm1, perm2)
  993. char *perm1;
  994. char *perm2;
  995. {
  996.     char *pos1;
  997.     char *pos2;
  998.     int pfound = FALSE;
  999.     int match = FALSE;
  1000.  
  1001.     pos1 = perm1;
  1002.     pos2 = perm2;
  1003.     if (strlen(perm1) == strlen(perm2)) 
  1004.     {
  1005.         if (!strcmp(perm1, perm2))
  1006.             match = TRUE;
  1007.         else 
  1008.         {
  1009.             /* check that every perm found in the first string also occurs
  1010.              * in the second string
  1011.              */
  1012.             while (*pos1) {
  1013.                 while (!pfound && *pos2) {
  1014.                     if (*pos1 == *pos2)
  1015.                         pfound = TRUE;
  1016.                     pos2++;
  1017.                 }
  1018.                 if (!pfound)
  1019.                     break;
  1020.                 else
  1021.                     pfound = FALSE;
  1022.                 pos1++;
  1023.                 pos2 = perm2;
  1024.             }
  1025.             if (!(*pos1))
  1026.                 match = TRUE;
  1027.         }
  1028.     }
  1029.     return(!match);
  1030. }
  1031.  
  1032.