home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume19 / rkive / part03 / setup.c < prev   
Encoding:
C/C++ Source or Header  |  1989-06-29  |  15.8 KB  |  605 lines

  1. /*
  2. **
  3. ** This software is Copyright (c) 1989 by Kent Landfield.
  4. **
  5. ** Permission is hereby granted to copy, distribute or otherwise 
  6. ** use any part of this package as long as you do not try to make 
  7. ** money from it or pretend that you wrote it.  This copyright 
  8. ** notice must be maintained in any copy made.
  9. **
  10. **
  11. **  History:
  12. **    Creation: Tue Feb 21 08:52:35 CST 1989 due to necessity.
  13. **                                                               
  14. */
  15. #ifndef lint
  16. static char SID[] = "@(#)setup.c    1.1 6/1/89";
  17. #endif
  18.  
  19. #include <sys/types.h>
  20. #include <sys/stat.h>
  21. #include <stdio.h>
  22. #include <ctype.h>
  23. #include <pwd.h>
  24. #include <grp.h>
  25. #include <dirent.h>
  26. #include "cfg.h"
  27.  
  28. #define GAG(b) ((void) fprintf(errfp,"%s invalid variable, ignoring.\n",b))
  29.  
  30. char spooldir[MAXNAMLEN]     = { SPOOLDIR };
  31. char problems_dir[MAXNAMLEN] = { PROBLEMS_DIR };
  32.  
  33. int default_owner = OWNER;
  34. int default_group = GROUP;
  35. int default_modes = MODES;
  36. int default_type = ARTICLE_NUMBER;
  37. int default_patch_type = HISTORICAL;
  38.  
  39. /*
  40. ** compress -
  41. ** Used to  determine whether or not articles should be compressed 
  42. ** to save space. The command to execute is stored in compress.
  43. */
  44. char compress[MAXNAMLEN] = { '\0' };
  45.  
  46. /*
  47. ** mail -
  48. ** If specified, all actions logged are mailed to the list of users 
  49. ** specified.  The user names are a comma seperated list. 
  50. */
  51. char mail[MAXNAMLEN] = { '\0' };
  52.  
  53. /*
  54. ** log -
  55. ** The location of the master log in which all actions are logged. 
  56. ** If not specified, all logged events are printed on stdout.
  57. */
  58. char log[MAXNAMLEN] = { '\0' };
  59.  
  60. /*
  61. ** log_format -
  62. ** The format of each individual log file record. The format is
  63. ** then filled with information contained in the headers.
  64. */
  65. char log_format[BUFSIZ] = { '\0' };
  66.  
  67. /*
  68. ** index -
  69. ** The location of the master index.
  70. */
  71. char index[MAXNAMLEN] = { '\0' };
  72.  
  73. /*
  74. ** index_format -
  75. ** The format of each individual master index record. The format 
  76. ** is then filled with information contained in the headers.
  77. */
  78. char index_format[BUFSIZ] = { '\0' };
  79.  
  80. char *config_file;
  81. FILE *config;
  82.  
  83. struct stat stbuf;
  84. struct passwd *pwent;
  85.  
  86. char *strstrip();
  87. char *strchr();
  88. char *strcpy();
  89. void exit();
  90. struct passwd *getpwnam();
  91.  
  92. struct restricted_dirs {
  93.     char   *dirstr;            /* path of restricted directory */
  94. };
  95.  
  96. static struct restricted_dirs base_dirs[] = {
  97. {  "/"               },
  98. {  "/etc"            },
  99. {  "/dev"            },
  100. {  "/dev/dsk"        },
  101. {  "/dev/rdsk"       },
  102. {  "/lib"            },
  103. {  "/stand"          },
  104. {  "/usr/adm"        },
  105. {  "/usr/spool/uucp" },
  106. {  NULL              },
  107. };
  108.  
  109. setup_defaults()
  110. {
  111.     char *sp;
  112.     char *buf;
  113.     char buffer[BUFSIZ];
  114.     char mode_str[128];
  115.  
  116.     char *sav_format();
  117.     char *get_compress();
  118.     char *get_users();
  119.     FILE *efopen();
  120.  
  121.     config = efopen(config_file,"r");
  122.  
  123.     num = -1; /* initialize group structure index */
  124.     
  125.     while (fgets(buffer, sizeof buffer, config) != NULL) {
  126.         /* ignore comments and blank lines */
  127.         if (*buffer == '#' || *buffer == '\n') 
  128.             continue;
  129.  
  130.         buf = buffer;
  131.  
  132.         /* strip leading spaces and tabs */
  133.     while(*buf == ' ' || *buf == '\t')
  134.              ++buf;
  135.  
  136.         *(buf+(strlen(buf)-1))  = '\0'; /* remove newline */
  137.  
  138.         /* if embedded comments, truncate at the comment */
  139.         if ((sp = strchr(buf,'#')) != NULL)
  140.              *sp = '\0';
  141.     
  142.         /* check to see if newsgroup entry */
  143.  
  144.         if (*buf == '$' && *(buf+1) == '$') {
  145.             if (++num >= NUM_NEWSGROUPS)
  146.                error("Maximum number of newsgroups exceeded!!\n", 
  147.                     "Please increase the NUM_NEWSGROUPS define...");
  148.  
  149.             sp = buf+2;
  150.             while (*sp && !isspace(*sp))
  151.         ++sp;
  152.             *sp = '\0';
  153.  
  154.             group[num].owner     = default_owner;
  155.             group[num].group     = default_group;
  156.             group[num].modes     = default_modes;
  157.             group[num].type      = default_type;
  158.             group[num].patch_type = default_patch_type;
  159.             (void) strcpy (group[num].ng_name, strstrip(buf+2));
  160.             group[num].location[0]  = '\0';
  161.             group[num].mail_list[0] = '\0';
  162.             group[num].logfile[0]   = '\0';
  163.             group[num].index[0]     = '\0';
  164.             group[num].logformat[0] = '\0';
  165.             group[num].indformat[0] = '\0';
  166.             group[num].compress[0]  = '\0';
  167.         }
  168.  
  169.         else if ((sp = strchr(buf,'=')) != NULL) {
  170.             sp++;
  171.                     /* Global assignment */
  172.             while (*sp == ' ' || *sp == '\t')
  173.                 sp++;
  174.  
  175.             if (!*sp)        /* is something still there ? */
  176.         continue;
  177.  
  178.             switch(*buf) {
  179.                case 'C': (void) strcpy(compress, get_compress(buf, sp));
  180.                          break;
  181.                case 'G': default_group = get_group(buf, sp);
  182.                          break;
  183.                case 'I': if (strncmp(buf, "INDEX_FORMAT", 12) == 0)
  184.                             (void) strcpy(index_format, sav_format(sp));
  185.                          else if (strncmp(buf, "INDEX", 3) == 0)
  186.                             (void) strcpy(index, strstrip(sp));
  187.                          else
  188.                             GAG(buf);
  189.                          break;
  190.                case 'L': if (strncmp(buf, "LOG_FORMAT", 10) == 0)
  191.                             (void) strcpy(log_format, sav_format(sp));
  192.                          else if (strncmp(buf, "LOG", 3) == 0)
  193.                             (void) strcpy(log, strstrip(sp));
  194.                          else
  195.                             GAG(buf);
  196.                          break;
  197.                case 'M': if (strncmp(buf, "MAIL",4) == 0) 
  198.                              (void) strcpy(mail,get_users(sp));
  199.                          else if (strncmp(buf, "MODE",4) == 0) 
  200.                              default_modes = correct_modes(sp, mode_str);
  201.                          else
  202.                              error(buf, "invalid global assignment");
  203.                          break;
  204.                case 'O': default_owner = get_owner(buf, sp);
  205.                          break;
  206.                case 'P': if (strncmp(buf, "PROBLEMS", 8) == 0)
  207.                            (void) strcpy(problems_dir, strstrip(sp));
  208.                          else 
  209.                            default_patch_type = get_patch_type("Global",buf,sp);
  210.                          break;
  211.                case 'S': get_spooldir(buf, sp);
  212.                          break;
  213.                case 'T': default_type = get_archive_type("Global", buf, sp);
  214.                          break;
  215.                default : error("invalid global assignment:", buf);
  216.             }
  217.         }
  218.         else if ((sp = strchr(buf,':')) != NULL) {
  219.             sp++;
  220.                 /* group variable assignment */
  221.             while (*sp == ' ' || *sp == '\t')
  222.                 sp++;
  223.  
  224.             if (!*sp)        /* is something still there ? */
  225.         continue;
  226.  
  227.             switch(*buf) {
  228.                case 'B': if (strncmp(buf, "BASEDIR",7) == 0) 
  229.                             get_archive_basedir(sp);
  230.                          break;
  231.                case 'C': (void)strcpy(group[num].compress,get_compress(buf,sp));
  232.                          break;
  233.                case 'G': group[num].group = get_group(buf, sp);
  234.                          break;
  235.                case 'I': if (strncmp(buf, "INDEX_FORMAT", 12) == 0)
  236.                             (void) strcpy(group[num].indformat,sav_format(sp));
  237.                          else if (strncmp(buf, "INDEX", 3) == 0)
  238.                              (void) strcpy(group[num].index, strstrip(sp));
  239.                          else
  240.                              GAG(buf);
  241.                          break;
  242.                case 'L': if (strncmp(buf, "LOG_FORMAT", 10) == 0)
  243.                             (void) strcpy(group[num].logformat, sav_format(sp));
  244.                          else if (strncmp(buf, "LOG", 3) == 0)
  245.                             (void) strcpy(group[num].logfile, strstrip(sp));
  246.                          else
  247.                             GAG(buf);
  248.                          break;
  249.                case 'M': if (strncmp(buf, "MAIL",4) == 0)
  250.                             (void) strcpy(group[num].mail_list, get_users(sp));
  251.                          else if (strncmp(buf, "MODE",4) == 0) 
  252.                              group[num].modes = correct_modes(sp, mode_str);
  253.                          else 
  254.                              GAG(buf);
  255.                          break;
  256.                case 'O': group[num].owner = get_owner(buf, sp);
  257.                          break;
  258.                case 'P': group[num].patch_type = get_patch_type(group[num].ng_name,buf,sp);
  259.                          break;
  260.                case 'T': group[num].type = get_archive_type(group[num].ng_name, buf, sp);
  261.                          break;
  262.                default : error("invalid group assignment:", buf);
  263.             }
  264.         }
  265.         else /* no idea what it is */
  266.             error("unknown line type", buf);
  267.     }
  268.     (void) fclose(config);
  269. }
  270.  
  271. error(msg1,msg2)
  272.    char *msg1;
  273.    char *msg2;
  274. {
  275.     (void) fprintf(errfp,"%s: %s %s\n",progname,msg1, msg2);
  276.     exit(1);
  277. }
  278.  
  279. /*
  280. ** valid_base_directory
  281. **
  282. ** Assure the directory specified in the configuration file 
  283. ** as the base directory for a newsgroup archive is not found 
  284. ** in the table of restricted base directories. 
  285. **
  286. ** This kind of checking is almost insulting to me as an 
  287. ** administrator but, enough people asked me to put it in 
  288. ** so "this duds for you"..
  289. */
  290.  
  291. int valid_base_directory(argstr)
  292.     char *argstr;
  293.  {
  294.     register char *rp;
  295.     register char *dp;
  296.     char wpath[MAXNAMLEN];
  297.     char lastchar;
  298.     struct restricted_dirs *pt;
  299.  
  300.     /* 
  301.     ** First check to see if the base directory is any
  302.     ** character other than a slash. We need to assure
  303.     ** that "../../../etc" or ./etc is not allowed.  We
  304.     ** need a valid absolute path with which to do relative
  305.     ** path addressing. (Have I confused myself yet ?)
  306.     */
  307.  
  308.     if (*argstr != '/') 
  309.             return(FALSE);
  310.  
  311.     /* 
  312.     ** Strip the string of duplicate '/'s.
  313.     ** Also check to assure that the path specified
  314.     ** does not contain the '..' sequence.
  315.     */
  316.  
  317.     dp = argstr;
  318.     rp = wpath;
  319.     lastchar = ' ';
  320.  
  321.     while (*dp) {
  322.        if (*dp != '/' || lastchar != '/') {
  323.            lastchar = *dp;
  324.            *rp++ = *dp;
  325.        }
  326.        if (*dp == '.' && lastchar == '.') {
  327.            if ((*(dp+1) == '/') || (*(dp+1) == '\0'))
  328.                return(FALSE);
  329.        }
  330.        ++dp;
  331.     }
  332.     *rp = '\0';
  333.  
  334.     /* 
  335.     ** strip the string of trailing '/'s so
  336.     ** I can use the simple checking below.
  337.     */
  338.  
  339.     dp = wpath+(strlen(wpath)-1);
  340.     while(*dp == '/' && dp > wpath)
  341.         *dp = '\0';
  342.  
  343.     /* 
  344.     ** check if they match 
  345.     */
  346.  
  347.     pt = &base_dirs[0];
  348.     while ((pt->dirstr) != NULL) {
  349.  
  350.         if (strcmp(wpath, pt->dirstr) == 0) 
  351.             return(FALSE);
  352.  
  353.         pt++;
  354.     }
  355.     return(TRUE);
  356. }
  357.  
  358. get_archive_basedir(s)
  359. char *s;
  360. {
  361.     (void) strcpy(group[num].location, strstrip(s));
  362.  
  363.     if (!valid_base_directory(group[num].location))
  364.         error(group[num].ng_name," - Invalid archive base directory!");
  365. }
  366.  
  367. int correct_modes(s,mode_string)
  368. char *s;
  369. char *mode_string;
  370. {
  371.     register int c;
  372.     register int i;
  373.  
  374.     i = 0;
  375.     (void) sscanf(s, "%s", mode_string);
  376.     while ((c = *mode_string++) >= '0' && c <= '7')
  377.         i = (i << 3) + (c - '0');
  378.     mode_string--;
  379.     return(i);
  380. }
  381.  
  382. char *get_compress(buffer,cmd)
  383. char *buffer;
  384. char *cmd;
  385. {
  386.     static char *rp;
  387.  
  388.     if (!valid_variable(buffer, "COMPRESS", 8))
  389.         return(NULL);
  390.     
  391.     rp = strstrip(cmd);
  392.  
  393.     /* need to assure the user has specified */
  394.     /* a valid executable path.              */
  395.  
  396.     if (stat(rp, &stbuf) != 0) 
  397.         error("Can't find specified COMPRESS -", rp);
  398.  
  399.     return(rp);
  400. }
  401.         
  402.  
  403. int get_group(buffer, valstr)
  404. char *buffer;
  405. char *valstr;
  406. {
  407.     char *wp;
  408.     struct group *grent;
  409.     struct group *getgrnam();
  410.  
  411.     if (!valid_variable(buffer, "GROUP", 5))
  412.         return(default_group);
  413.     
  414.     /* group specified by names but */
  415.     /* needs to be numbers          */
  416.  
  417.     wp = strstrip(valstr);
  418.  
  419.     if ((grent = getgrnam(wp)) == NULL)
  420.          error("Invalid system group:",wp);
  421.     return(grent->gr_gid);
  422. }
  423.  
  424.  
  425. int get_owner(buffer, valstr)
  426. char *buffer;
  427. char *valstr;
  428. {
  429.     char *wp;
  430.  
  431.     if (!valid_variable(buffer, "OWNER", 5))
  432.         return(default_owner);
  433.     
  434.     /* owner specified by names but */
  435.     /* needs to be numbers          */
  436.  
  437.     wp = strstrip(valstr);
  438.  
  439.     if ((pwent = getpwnam(wp)) == NULL)
  440.          error("Invalid user:",wp);
  441.     return(pwent->pw_uid);
  442. }
  443.  
  444. int get_archive_type(ngname, buffer, s)
  445. char *ngname;
  446. char *buffer;
  447. char *s;
  448. {
  449.     int return_type;
  450.  
  451.     if (!valid_variable(buffer, "TYPE", 4))
  452.         return(default_type);
  453.     
  454.     if (strcmp(s, "Archive-Name") == 0) 
  455.         return_type = ARCHIVE_NAME;
  456.     else if (strcmp(s, "Volume-Issue") == 0) 
  457.         return_type = VOLUME_ISSUE;
  458.     else if (strcmp(s, "Article-Number") == 0) 
  459.         return_type = ARTICLE_NUMBER;
  460.     else {
  461.         (void) fprintf(errfp,"%s: %s: %s %s\n", progname,
  462.                    ngname, "Invalid Archive Type:", s);
  463.         (void) fprintf(errfp,"\tTYPE Must be %s, %s or %s\n",
  464.                    "Archive-Name", "Volume-Issue", "Article-Number");
  465.         exit(1);
  466.     }
  467.  
  468.     return(return_type);
  469. }
  470.  
  471. int valid_variable(buffer, variable, length)
  472. char *buffer;
  473. char *variable;
  474. int length;
  475. {
  476.     if (strncmp(buffer, variable, length) != 0) {
  477.         GAG(buffer);
  478.         return(FALSE);
  479.     }
  480.     return(TRUE);
  481. }
  482.  
  483.  
  484. get_spooldir(buffer,s)
  485. char *buffer;
  486. char *s;
  487. {
  488.     static char *rp;
  489.  
  490.     if (!valid_variable(buffer, "SPOOLDIR", 8))
  491.         (void) strcpy(spooldir, SPOOLDIR);
  492.  
  493.     else {
  494.         rp = strstrip(s);
  495.  
  496.         /* need to assure the user has specified */
  497.         /* a valid directory path for the base   */
  498.         /* directory for the news subsystem..    */
  499.     
  500.         if (stat(rp, &stbuf) != 0) 
  501.             error("Can't find SPOOLDIR -", rp);
  502.     
  503.         (void) strcpy(spooldir, rp);
  504.     }
  505. }
  506.  
  507. char *get_users(s)
  508. char *s;
  509. {
  510.     char *strcat();
  511.  
  512.     static char users[512];
  513.     char tmp_users[512];
  514.     char *list, *name;
  515.     char *cp, *dp;
  516.     register int i;
  517.  
  518.     /* prepare the string for saving by stripping any spaces */
  519.  
  520.     for (i = 0; i < sizeof users; i++)
  521.        users[i] = '\0';
  522.  
  523.     cp = s;
  524.     dp = users;
  525.     while (*cp) {
  526.           if (*cp != ' ' && *cp != '\t')
  527.               *dp++ = *cp;
  528.           ++cp;
  529.     }
  530.       
  531.     /* need to check the specified user list */
  532.     /* to assure that all users are valid    */
  533.  
  534.     (void) strcpy(tmp_users, users);
  535.     *users = NULL;
  536.  
  537.     name = tmp_users;
  538.  
  539.     while (name != NULL) {
  540.         /* is there additional users specified ? */
  541.     if ((list = strchr(name,',')) != NULL) {
  542.              list++;
  543.              *(list-1) = '\0';
  544.         }
  545.  
  546.         /* check if user is found in passwd file */
  547.         if ((pwent = getpwnam(name)) != NULL) {
  548.             if (*users != NULL) {
  549.                 (void) strcat(users, ",");
  550.                 (void) strcat(users, name);
  551.             }
  552.             else 
  553.                 (void) strcpy(users, name);
  554.         }
  555.         else 
  556.             error("Invalid user:",name);
  557.         name = list;
  558.     }
  559.     return(users);
  560. }
  561.  
  562. /*
  563. ** get a specified format from the buffer
  564. **    Must allow for spaces and tabs so they
  565. **      need to be passed intact in the format.
  566. */
  567. char *sav_format(s)
  568.     char *s;
  569. {
  570.     static char *cp;
  571.     char *dp;
  572.     
  573.     if ((cp = strchr(s,'"')) != NULL && 
  574.         (dp = strchr(++cp,'"')) != NULL) {
  575.         *dp = '\0';
  576.     }
  577.     else
  578.         cp = NULL;
  579.     return(cp);
  580. }
  581.  
  582. int get_patch_type(ngname,buffer, s)
  583. char *ngname;
  584. char *buffer;
  585. char *s;
  586. {
  587.     int return_type;
  588.  
  589.     if (!valid_variable(buffer, "PATCHES", 7))
  590.         return(default_type);
  591.     
  592.     if (strcmp(s, "Package") == 0) 
  593.         return_type = PACKAGE;
  594.     else if (strcmp(s, "Historical") == 0) 
  595.         return_type = HISTORICAL;
  596.     else {
  597.         (void) fprintf(errfp,"%s: %s: %s %s\n", progname,
  598.                    ngname, "Invalid Patches Type:", s);
  599.         (void) fprintf(errfp,"\tTYPE Must be %s, or %s\n",
  600.                    "Historical", "Package");
  601.         exit(1);
  602.     }
  603.     return(return_type);
  604. }
  605.