home *** CD-ROM | disk | FTP | other *** search
- /*
- **
- ** This software is Copyright (c) 1989 by Kent Landfield.
- **
- ** Permission is hereby granted to copy, distribute or otherwise
- ** use any part of this package as long as you do not try to make
- ** money from it or pretend that you wrote it. This copyright
- ** notice must be maintained in any copy made.
- **
- **
- ** History:
- ** Creation: Tue Feb 21 08:52:35 CST 1989 due to necessity.
- **
- */
- #ifndef lint
- static char SID[] = "@(#)setup.c 1.1 6/1/89";
- #endif
-
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <stdio.h>
- #include <ctype.h>
- #include <pwd.h>
- #include <grp.h>
- #include <dirent.h>
- #include "cfg.h"
-
- #define GAG(b) ((void) fprintf(errfp,"%s invalid variable, ignoring.\n",b))
-
- char spooldir[MAXNAMLEN] = { SPOOLDIR };
- char problems_dir[MAXNAMLEN] = { PROBLEMS_DIR };
-
- int default_owner = OWNER;
- int default_group = GROUP;
- int default_modes = MODES;
- int default_type = ARTICLE_NUMBER;
- int default_patch_type = HISTORICAL;
-
- /*
- ** compress -
- ** Used to determine whether or not articles should be compressed
- ** to save space. The command to execute is stored in compress.
- */
- char compress[MAXNAMLEN] = { '\0' };
-
- /*
- ** mail -
- ** If specified, all actions logged are mailed to the list of users
- ** specified. The user names are a comma seperated list.
- */
- char mail[MAXNAMLEN] = { '\0' };
-
- /*
- ** log -
- ** The location of the master log in which all actions are logged.
- ** If not specified, all logged events are printed on stdout.
- */
- char log[MAXNAMLEN] = { '\0' };
-
- /*
- ** log_format -
- ** The format of each individual log file record. The format is
- ** then filled with information contained in the headers.
- */
- char log_format[BUFSIZ] = { '\0' };
-
- /*
- ** index -
- ** The location of the master index.
- */
- char index[MAXNAMLEN] = { '\0' };
-
- /*
- ** index_format -
- ** The format of each individual master index record. The format
- ** is then filled with information contained in the headers.
- */
- char index_format[BUFSIZ] = { '\0' };
-
- char *config_file;
- FILE *config;
-
- struct stat stbuf;
- struct passwd *pwent;
-
- char *strstrip();
- char *strchr();
- char *strcpy();
- void exit();
- struct passwd *getpwnam();
-
- struct restricted_dirs {
- char *dirstr; /* path of restricted directory */
- };
-
- static struct restricted_dirs base_dirs[] = {
- { "/" },
- { "/etc" },
- { "/dev" },
- { "/dev/dsk" },
- { "/dev/rdsk" },
- { "/lib" },
- { "/stand" },
- { "/usr/adm" },
- { "/usr/spool/uucp" },
- { NULL },
- };
-
- setup_defaults()
- {
- char *sp;
- char *buf;
- char buffer[BUFSIZ];
- char mode_str[128];
-
- char *sav_format();
- char *get_compress();
- char *get_users();
- FILE *efopen();
-
- config = efopen(config_file,"r");
-
- num = -1; /* initialize group structure index */
-
- while (fgets(buffer, sizeof buffer, config) != NULL) {
- /* ignore comments and blank lines */
- if (*buffer == '#' || *buffer == '\n')
- continue;
-
- buf = buffer;
-
- /* strip leading spaces and tabs */
- while(*buf == ' ' || *buf == '\t')
- ++buf;
-
- *(buf+(strlen(buf)-1)) = '\0'; /* remove newline */
-
- /* if embedded comments, truncate at the comment */
- if ((sp = strchr(buf,'#')) != NULL)
- *sp = '\0';
-
- /* check to see if newsgroup entry */
-
- if (*buf == '$' && *(buf+1) == '$') {
- if (++num >= NUM_NEWSGROUPS)
- error("Maximum number of newsgroups exceeded!!\n",
- "Please increase the NUM_NEWSGROUPS define...");
-
- sp = buf+2;
- while (*sp && !isspace(*sp))
- ++sp;
- *sp = '\0';
-
- group[num].owner = default_owner;
- group[num].group = default_group;
- group[num].modes = default_modes;
- group[num].type = default_type;
- group[num].patch_type = default_patch_type;
- (void) strcpy (group[num].ng_name, strstrip(buf+2));
- group[num].location[0] = '\0';
- group[num].mail_list[0] = '\0';
- group[num].logfile[0] = '\0';
- group[num].index[0] = '\0';
- group[num].logformat[0] = '\0';
- group[num].indformat[0] = '\0';
- group[num].compress[0] = '\0';
- }
-
- else if ((sp = strchr(buf,'=')) != NULL) {
- sp++;
- /* Global assignment */
- while (*sp == ' ' || *sp == '\t')
- sp++;
-
- if (!*sp) /* is something still there ? */
- continue;
-
- switch(*buf) {
- case 'C': (void) strcpy(compress, get_compress(buf, sp));
- break;
- case 'G': default_group = get_group(buf, sp);
- break;
- case 'I': if (strncmp(buf, "INDEX_FORMAT", 12) == 0)
- (void) strcpy(index_format, sav_format(sp));
- else if (strncmp(buf, "INDEX", 3) == 0)
- (void) strcpy(index, strstrip(sp));
- else
- GAG(buf);
- break;
- case 'L': if (strncmp(buf, "LOG_FORMAT", 10) == 0)
- (void) strcpy(log_format, sav_format(sp));
- else if (strncmp(buf, "LOG", 3) == 0)
- (void) strcpy(log, strstrip(sp));
- else
- GAG(buf);
- break;
- case 'M': if (strncmp(buf, "MAIL",4) == 0)
- (void) strcpy(mail,get_users(sp));
- else if (strncmp(buf, "MODE",4) == 0)
- default_modes = correct_modes(sp, mode_str);
- else
- error(buf, "invalid global assignment");
- break;
- case 'O': default_owner = get_owner(buf, sp);
- break;
- case 'P': if (strncmp(buf, "PROBLEMS", 8) == 0)
- (void) strcpy(problems_dir, strstrip(sp));
- else
- default_patch_type = get_patch_type("Global",buf,sp);
- break;
- case 'S': get_spooldir(buf, sp);
- break;
- case 'T': default_type = get_archive_type("Global", buf, sp);
- break;
- default : error("invalid global assignment:", buf);
- }
- }
- else if ((sp = strchr(buf,':')) != NULL) {
- sp++;
- /* group variable assignment */
- while (*sp == ' ' || *sp == '\t')
- sp++;
-
- if (!*sp) /* is something still there ? */
- continue;
-
- switch(*buf) {
- case 'B': if (strncmp(buf, "BASEDIR",7) == 0)
- get_archive_basedir(sp);
- break;
- case 'C': (void)strcpy(group[num].compress,get_compress(buf,sp));
- break;
- case 'G': group[num].group = get_group(buf, sp);
- break;
- case 'I': if (strncmp(buf, "INDEX_FORMAT", 12) == 0)
- (void) strcpy(group[num].indformat,sav_format(sp));
- else if (strncmp(buf, "INDEX", 3) == 0)
- (void) strcpy(group[num].index, strstrip(sp));
- else
- GAG(buf);
- break;
- case 'L': if (strncmp(buf, "LOG_FORMAT", 10) == 0)
- (void) strcpy(group[num].logformat, sav_format(sp));
- else if (strncmp(buf, "LOG", 3) == 0)
- (void) strcpy(group[num].logfile, strstrip(sp));
- else
- GAG(buf);
- break;
- case 'M': if (strncmp(buf, "MAIL",4) == 0)
- (void) strcpy(group[num].mail_list, get_users(sp));
- else if (strncmp(buf, "MODE",4) == 0)
- group[num].modes = correct_modes(sp, mode_str);
- else
- GAG(buf);
- break;
- case 'O': group[num].owner = get_owner(buf, sp);
- break;
- case 'P': group[num].patch_type = get_patch_type(group[num].ng_name,buf,sp);
- break;
- case 'T': group[num].type = get_archive_type(group[num].ng_name, buf, sp);
- break;
- default : error("invalid group assignment:", buf);
- }
- }
- else /* no idea what it is */
- error("unknown line type", buf);
- }
- (void) fclose(config);
- }
-
- error(msg1,msg2)
- char *msg1;
- char *msg2;
- {
- (void) fprintf(errfp,"%s: %s %s\n",progname,msg1, msg2);
- exit(1);
- }
-
- /*
- ** valid_base_directory
- **
- ** Assure the directory specified in the configuration file
- ** as the base directory for a newsgroup archive is not found
- ** in the table of restricted base directories.
- **
- ** This kind of checking is almost insulting to me as an
- ** administrator but, enough people asked me to put it in
- ** so "this duds for you"..
- */
-
- int valid_base_directory(argstr)
- char *argstr;
- {
- register char *rp;
- register char *dp;
- char wpath[MAXNAMLEN];
- char lastchar;
- struct restricted_dirs *pt;
-
- /*
- ** First check to see if the base directory is any
- ** character other than a slash. We need to assure
- ** that "../../../etc" or ./etc is not allowed. We
- ** need a valid absolute path with which to do relative
- ** path addressing. (Have I confused myself yet ?)
- */
-
- if (*argstr != '/')
- return(FALSE);
-
- /*
- ** Strip the string of duplicate '/'s.
- ** Also check to assure that the path specified
- ** does not contain the '..' sequence.
- */
-
- dp = argstr;
- rp = wpath;
- lastchar = ' ';
-
- while (*dp) {
- if (*dp != '/' || lastchar != '/') {
- lastchar = *dp;
- *rp++ = *dp;
- }
- if (*dp == '.' && lastchar == '.') {
- if ((*(dp+1) == '/') || (*(dp+1) == '\0'))
- return(FALSE);
- }
- ++dp;
- }
- *rp = '\0';
-
- /*
- ** strip the string of trailing '/'s so
- ** I can use the simple checking below.
- */
-
- dp = wpath+(strlen(wpath)-1);
- while(*dp == '/' && dp > wpath)
- *dp = '\0';
-
- /*
- ** check if they match
- */
-
- pt = &base_dirs[0];
- while ((pt->dirstr) != NULL) {
-
- if (strcmp(wpath, pt->dirstr) == 0)
- return(FALSE);
-
- pt++;
- }
- return(TRUE);
- }
-
- get_archive_basedir(s)
- char *s;
- {
- (void) strcpy(group[num].location, strstrip(s));
-
- if (!valid_base_directory(group[num].location))
- error(group[num].ng_name," - Invalid archive base directory!");
- }
-
- int correct_modes(s,mode_string)
- char *s;
- char *mode_string;
- {
- register int c;
- register int i;
-
- i = 0;
- (void) sscanf(s, "%s", mode_string);
- while ((c = *mode_string++) >= '0' && c <= '7')
- i = (i << 3) + (c - '0');
- mode_string--;
- return(i);
- }
-
- char *get_compress(buffer,cmd)
- char *buffer;
- char *cmd;
- {
- static char *rp;
-
- if (!valid_variable(buffer, "COMPRESS", 8))
- return(NULL);
-
- rp = strstrip(cmd);
-
- /* need to assure the user has specified */
- /* a valid executable path. */
-
- if (stat(rp, &stbuf) != 0)
- error("Can't find specified COMPRESS -", rp);
-
- return(rp);
- }
-
-
- int get_group(buffer, valstr)
- char *buffer;
- char *valstr;
- {
- char *wp;
- struct group *grent;
- struct group *getgrnam();
-
- if (!valid_variable(buffer, "GROUP", 5))
- return(default_group);
-
- /* group specified by names but */
- /* needs to be numbers */
-
- wp = strstrip(valstr);
-
- if ((grent = getgrnam(wp)) == NULL)
- error("Invalid system group:",wp);
- return(grent->gr_gid);
- }
-
-
- int get_owner(buffer, valstr)
- char *buffer;
- char *valstr;
- {
- char *wp;
-
- if (!valid_variable(buffer, "OWNER", 5))
- return(default_owner);
-
- /* owner specified by names but */
- /* needs to be numbers */
-
- wp = strstrip(valstr);
-
- if ((pwent = getpwnam(wp)) == NULL)
- error("Invalid user:",wp);
- return(pwent->pw_uid);
- }
-
- int get_archive_type(ngname, buffer, s)
- char *ngname;
- char *buffer;
- char *s;
- {
- int return_type;
-
- if (!valid_variable(buffer, "TYPE", 4))
- return(default_type);
-
- if (strcmp(s, "Archive-Name") == 0)
- return_type = ARCHIVE_NAME;
- else if (strcmp(s, "Volume-Issue") == 0)
- return_type = VOLUME_ISSUE;
- else if (strcmp(s, "Article-Number") == 0)
- return_type = ARTICLE_NUMBER;
- else {
- (void) fprintf(errfp,"%s: %s: %s %s\n", progname,
- ngname, "Invalid Archive Type:", s);
- (void) fprintf(errfp,"\tTYPE Must be %s, %s or %s\n",
- "Archive-Name", "Volume-Issue", "Article-Number");
- exit(1);
- }
-
- return(return_type);
- }
-
- int valid_variable(buffer, variable, length)
- char *buffer;
- char *variable;
- int length;
- {
- if (strncmp(buffer, variable, length) != 0) {
- GAG(buffer);
- return(FALSE);
- }
- return(TRUE);
- }
-
-
- get_spooldir(buffer,s)
- char *buffer;
- char *s;
- {
- static char *rp;
-
- if (!valid_variable(buffer, "SPOOLDIR", 8))
- (void) strcpy(spooldir, SPOOLDIR);
-
- else {
- rp = strstrip(s);
-
- /* need to assure the user has specified */
- /* a valid directory path for the base */
- /* directory for the news subsystem.. */
-
- if (stat(rp, &stbuf) != 0)
- error("Can't find SPOOLDIR -", rp);
-
- (void) strcpy(spooldir, rp);
- }
- }
-
- char *get_users(s)
- char *s;
- {
- char *strcat();
-
- static char users[512];
- char tmp_users[512];
- char *list, *name;
- char *cp, *dp;
- register int i;
-
- /* prepare the string for saving by stripping any spaces */
-
- for (i = 0; i < sizeof users; i++)
- users[i] = '\0';
-
- cp = s;
- dp = users;
- while (*cp) {
- if (*cp != ' ' && *cp != '\t')
- *dp++ = *cp;
- ++cp;
- }
-
- /* need to check the specified user list */
- /* to assure that all users are valid */
-
- (void) strcpy(tmp_users, users);
- *users = NULL;
-
- name = tmp_users;
-
- while (name != NULL) {
- /* is there additional users specified ? */
- if ((list = strchr(name,',')) != NULL) {
- list++;
- *(list-1) = '\0';
- }
-
- /* check if user is found in passwd file */
- if ((pwent = getpwnam(name)) != NULL) {
- if (*users != NULL) {
- (void) strcat(users, ",");
- (void) strcat(users, name);
- }
- else
- (void) strcpy(users, name);
- }
- else
- error("Invalid user:",name);
- name = list;
- }
- return(users);
- }
-
- /*
- ** get a specified format from the buffer
- ** Must allow for spaces and tabs so they
- ** need to be passed intact in the format.
- */
- char *sav_format(s)
- char *s;
- {
- static char *cp;
- char *dp;
-
- if ((cp = strchr(s,'"')) != NULL &&
- (dp = strchr(++cp,'"')) != NULL) {
- *dp = '\0';
- }
- else
- cp = NULL;
- return(cp);
- }
-
- int get_patch_type(ngname,buffer, s)
- char *ngname;
- char *buffer;
- char *s;
- {
- int return_type;
-
- if (!valid_variable(buffer, "PATCHES", 7))
- return(default_type);
-
- if (strcmp(s, "Package") == 0)
- return_type = PACKAGE;
- else if (strcmp(s, "Historical") == 0)
- return_type = HISTORICAL;
- else {
- (void) fprintf(errfp,"%s: %s: %s %s\n", progname,
- ngname, "Invalid Patches Type:", s);
- (void) fprintf(errfp,"\tTYPE Must be %s, or %s\n",
- "Historical", "Package");
- exit(1);
- }
- return(return_type);
- }
-