#include "config.h" #include "conf.h" #include "err.h" #include "strutil.h" #include #include #include #include #include RCSID("$Id: conf.c,v 1.2 2000/02/22 22:50:33 shmit Exp $"); /* Granularity to use when dynamically allocating storage. */ const int MALLOC_GRANULARITY = 4; /* TODO: GC configuration and disklist. */ config_t configuration[] = { { MANAGER, STROPT, 0, -1 }, { LOGDIR, STROPT, 0, -1 }, { INFOLOG, STROPT, 0, -1 }, { ERRORLOG, STROPT, 0, -1 }, { HOSTLIST, STROPT, 0, -1 }, { TIMEOUT, NUMOPT, 0, -1 }, { RETRIES, NUMOPT, 0, -1 }, { SPOOLDIR, STROPT, 0, -1 }, { SPOOLSIZE, NUMOPT, 0, -1 }, { TAPEDEV, STROPT, 0, -1 }, { TAPESIZE, NUMOPT, 0, -1 }, { LABELSTR, STROPT, 0, -1 }, { PORTOPT, NUMOPT, 0, -1 }, { 0, 0, 0, 0 } }; dump_t *dumptypes = NULL; int numtypes = 0; static config_t * find_option(const char *name) { config_t *p = configuration; while (p->name) { if (!strcmp(name, p->name)) break; p++; } if (!p->name) return NULL; return p; } /* * I really hate this sort of code, but I really hate what I'd have * to do without it. */ const config_t * findopt(const char *name) { config_t *p; p = find_option(name); if (!p || p->numvalue == -1) return NULL; return p; } int read_config(const char *config_filen) { FILE *config_file; char buffer[MAXLINE]; int lineno = 0; config_file = fopen(config_filen, "r"); if (!config_file) { perror("Error: Couldn't open config file"); return -1; } while (fgets(buffer, sizeof(buffer), config_file)) { config_t *optptr; char *index; char option[MAXLINE], optarg[MAXLINE]; lineno++; index = getword(buffer, option); if (!index) continue; index = getword(index, optarg); if (!index) { fprintf(stderr, "Error: option `%s' has no argument" " on line %d.\n", option, lineno); return -1; } optptr = find_option(option); if (!optptr) { fprintf(stderr, "Error: option `%s' on line %d" " doesn't exist.\n", option, lineno); return -1; } switch (optptr->type) { case STROPT: index = malloc(sizeof(char)*strlen(optarg)); if (!index) { perror("Error: couldn't malloc"); return -1; } strcpy(index, optarg); optptr->strvalue = index; optptr->numvalue = 0; break; case NUMOPT: optptr->numvalue = strtol(optarg, &index, 10); if (*index) { fprintf(stderr, "Error: value `%s' on line %d is not" " a number.\n", optarg, lineno); return -1; } break; } } fclose(config_file); return 0; } /* * Find a dumptype with a given name. */ const dump_t * find_dumptype(const char *name) { int i; for (i = 0; i < numtypes; i++) { if (!strncmp(dumptypes[i].d_name, name, sizeof(dumptypes[i].d_name))) return &dumptypes[i]; } return NULL; } /* * Read the dumptypes out of the configuration file. */ int read_dumptypes(const char *filen) { FILE *list; char buffer[MAXLINE]; list = fopen(filen, "r"); if (!list) { err("Couldn't open dumptypes `%s': %s.\n", filen, strerror(errno)); return -1; } dumptypes = malloc(sizeof(dump_t) * MALLOC_GRANULARITY); if (!dumptypes) { err("Couldn't allocate enough space for dumptypes table: %s.\n", strerror(errno)); return -1; } while (fgets(buffer, sizeof(buffer), list)) { char *index; index = getword(buffer, dumptypes[numtypes].d_name); if (!index) continue; index = getword(index, dumptypes[numtypes].d_cmdline); if (!index) { err("Dumptype `%s' has no command line.", dumptypes[numtypes].d_name); free(dumptypes); return -1; } index = getword(index, dumptypes[numtypes].d_estline); if (!index) { dumptypes[numtypes].d_estline[0] = '\0'; dumptypes[numtypes].d_regexp[0] = '\0'; } else { index = getword(buffer, dumptypes[numtypes].d_regexp); if (!index) { err("Dumptype `%s' has an estimate line," " but not a corresponding regexp.", dumptypes[numtypes].d_name); free(dumptypes); return -1; } } /* Allocate more buffer space, if it's needed. */ if ((++numtypes % MALLOC_GRANULARITY) == 0) { dumptypes = realloc(dumptypes, sizeof(dump_t) * (numtypes + MALLOC_GRANULARITY)); if (!dumptypes) { err("Couldn't allocate enough space for" " dumptypes table: %s.\n", strerror(errno)); free(dumptypes); return -1; } } } fclose(list); /* Free up unused memory. */ /* * TODO: find out if this should actually barf the entire process. * it really shouldn't fail, so I think it's a non-issue, but it * should be thought about anyway. */ dumptypes = realloc(dumptypes, sizeof(dump_t) * numtypes); if (!dumptypes) { err("Couldn't free unused space in dumptypes table: %s.\n", strerror(errno)); free(dumptypes); return -1; } return 0; } /* * TODO: decide if non-fatal errors (like invalid dump types) should * barf everything. */ disklist_t * read_disklist(const char *filen) { FILE *list; disklist_t *dl = NULL; char buffer[MAXLINE]; list = fopen(filen, "r"); if (!list) { err("Couldn't open disklist `%s': %s.\n", filen, strerror(errno)); return NULL; } while (fgets(buffer, sizeof(buffer), list)) { char vol[MAXLINE], type[MAXLINE], comp[MAXLINE], auth[MAXLINE]; char *index; disklist_t *p; index = getword(buffer, vol); if (!index) continue; index = getword(index, type); if (!index) { err("Volume `%s' has no dump type.\n", vol); return NULL; } index = getword(index, comp); if (!index) { strcpy(comp, DC_UNCOMP); strcpy(auth, DA_NONE); } else { index = getword(index, auth); if (!index) strcpy(auth, DA_NONE); } p = malloc(sizeof(disklist_t)); if (!p) { err("Couldn't malloc space for disklist node: %s.\n", strerror(errno)); return NULL; } p->next = dl; strncpy(p->disk.vol, vol, sizeof(p->disk.vol)); p->disk.type = find_dumptype(type); if (!p->disk.type) { err("Dump type `%s' isn't defined in dumptypes.\n", type); free(p); return NULL; } /* Extract the compression options. */ if (!strcmp(comp, DC_UNCOMP)) p->disk.comp = UNCOMP; else if (!strcmp(comp, DC_COMP)) p->disk.comp = COMP; else if (!strcmp(comp, DC_COMP9)) p->disk.comp = COMP9; else if (!strcmp(comp, DC_COMPFAST)) p->disk.comp = COMPFAST; else { err("Error: compression type %s isn't supported.\n", comp); free(p); return NULL; } /* Extract method of authentication. */ if (!strcmp(auth, DA_NONE)) p->disk.auth = NOAUTH; else if (!strcmp(auth, DA_RSH)) p->disk.auth = RSH; else { err("Error: auth type %s isn't supported.\n", auth); free(p); return NULL; } dl = p; } fclose(list); return dl; }