#ifdef HAVE_CONFIG_H # include "config.h" #endif #include #include #include #include #include "fi.h" #include "pclt.h" #include "configfile.h" #define CONFIGFILE_LINELEN 2000 #define CONFIGFILE_ERROR_TNO (-1) #define CONFIGFILE_ERROR_TSYS 1 #define CONFIGFILE_ERROR_TSYN 2 static void configfile_setzeroerror(void) { configfile_error.cf_lineno=0; configfile_error.cf_type=CONFIGFILE_ERROR_TNO; configfile_error.cf_msg[0]=(char)0x0; } static void configfile_setsyserror(msg) const char *msg; { configfile_error.cf_type=CONFIGFILE_ERROR_TSYS; (void)strncpy(configfile_error.cf_msg, msg, CONFIGFILE_ERROR_MSGLEN); configfile_error.cf_msg[CONFIGFILE_ERROR_MSGLEN]=(char)0x0; } static void configfile_setsynerror(msg) const char *msg; { configfile_error.cf_type=CONFIGFILE_ERROR_TSYN; (void)strncpy(configfile_error.cf_msg, msg, CONFIGFILE_ERROR_MSGLEN); configfile_error.cf_msg[CONFIGFILE_ERROR_MSGLEN]=(char)0x0; } static void configfile_psynerror(void) { (void)fprintf(stderr, "line %d: %s\n", configfile_error.cf_lineno, configfile_error.cf_msg); } void configfile_psyserror(void) { (void)fprintf(stderr, "%s: %s\n", configfile_error.cf_msg, strerror(errno)); } static int configfile_readline(fp, linebuff) FILE *fp; char *linebuff; { char *p; if (feof(fp)) { return (1); } while ((p=fgets(linebuff, CONFIGFILE_LINELEN, fp))!=NULL) { configfile_error.cf_lineno++; if (!(*p==';' || *p=='#' || *p==' ' || *p=='\t' || *p=='\n')) break; } if (!p) { if (!feof(fp)) { configfile_setsyserror("configfile_readline()"); return (-1); } return (1); } p[CONFIGFILE_LINELEN-1]=(char)0x0; p[strlen(p)-1]=(char)0x0; return (0); } static void configfile_splitline(line, word, arg) char *line, **word, **arg; { int i, len=strlen(line); for (i=0; ipcl_luid = euid->pcl_ruid = 0; euid->pcl_type = PCLEUID_S; configfile_cutstreid(&s); if ('0' <= *s && *s <= '9') { for ( ; *s; ++s) { if (*s < '0' || '9' < *s) break; euid->pcl_luid = euid->pcl_luid*10+(*s-'0'); } if (*s == (char)0x0) { euid->pcl_type = PCLEUID_S; return (0); } else if (*s == '-') { ++s; if (*s == (char)0x0) { euid->pcl_type = PCLEUID_L; return (0); } else { for ( ; *s; ++s) { if (*s < '0' || '9' < *s) return (-1); euid->pcl_ruid = euid->pcl_ruid*10+(*s-'0'); } euid->pcl_type = PCLEUID_LR; return (0); } return (-1); } return (-1); } else if ('-' == *s) { euid->pcl_type = PCLEUID_R; for (++s; *s; ++s) { if (*s < '0' || '9' < *s) return (-1); euid->pcl_ruid = euid->pcl_ruid*10+(*s-'0'); } return (0); } return (-1); } static int configfile_strtoegid(s, egid) const char *s; PCLEGID *egid; { egid->pcl_lgid = egid->pcl_rgid = 0; egid->pcl_type = PCLEGID_S; configfile_cutstreid(&s); if ('0' <= *s && *s <= '9') { for ( ; *s; ++s) { if (*s < '0' || '9' < *s) break; egid->pcl_lgid = egid->pcl_lgid*10+(*s-'0'); } if (*s == (char)0x0) { egid->pcl_type = PCLEGID_S; return (0); } else if (*s == '-') { ++s; if (*s == (char)0x0) { egid->pcl_type = PCLEGID_L; return (0); } else { for ( ; *s; ++s) { if (*s < '0' || '9' < *s) return (-1); egid->pcl_rgid = egid->pcl_rgid*10+(*s-'0'); } egid->pcl_type = PCLEGID_LR; return (0); } return (-1); } return (-1); } else if ('-' == *s) { egid->pcl_type = PCLEGID_R; for (++s; *s; ++s) { if (*s < '0' || '9' < *s) return (-1); egid->pcl_rgid = egid->pcl_rgid*10+(*s-'0'); } return (0); } return (-1); } static int configfile_readpclentbody(fp, pclent, linebuff) FILE *fp; PCLENT *pclent; char *linebuff; { PCLEUID euid; PCLEGID egid; const char *word, *arg; int type, st, errval; while (!feof(fp)) { if ((st=configfile_readline(fp, linebuff))!=0) { if (st < 0) return (-1); break; } if (linebuff[0]=='+' || linebuff[0]=='@') { break; } configfile_splitline(linebuff, &word, &arg); if (strncmp(word, "name", 5)==0) { if (!pclent_addname(pclent, arg)) { configfile_setsyserror("pclent_name_add()"); return (-1); } #if ENABLE_REGEX } else if (strncmp(word, "namere", 7)==0) { if (!pclent_addename(pclent, arg, &errval)) { if (errval==REG_ESPACE) { configfile_setsyserror( "pclent_addename()"); } else { configfile_setsynerror( "invalid regular expression"); } return (-1); } #endif } else if (strncmp(word, "gid", 4)==0) { if (configfile_strtoegid(arg, &egid)!=0) { configfile_setsynerror("bad gid"); return (-1); } if (!pclent_addegid(pclent, &egid)) { configfile_setsyserror("pclent_egid_add()"); return (-1); } } else if (strncmp(word, "uid", 4)==0) { if (configfile_strtoeuid(arg, &euid)!=0) { configfile_setsynerror("bad uid"); return (-1); } if (!pclent_addeuid(pclent, &euid)) { configfile_setsyserror("pclent_euid_add()"); return (-1); } } else if (strncmp(word, "type", 5)==0) { if (configfile_strtotype(arg, &type)!=0) { configfile_setsynerror("bad type"); return (-1); } pclent_settype(pclent, type); } else { configfile_setsynerror("bad keyword"); return (-1); } } return (0); } static int configfile_readpclenthead(fp, pclent, linebuff) FILE *fp; PCLENT *pclent; char *linebuff; { const char *word, *arg; int n, i; configfile_splitline(linebuff, &word, &arg); if (word[0]!='+') { configfile_setsynerror("'+' (entry) is expected"); return (-1); } PCL_SET(pclent->pcl_marks, PCL_MMATCH); for (++word; *word; ++word) { switch (*word) { case 'F': PCL_SET(pclent->pcl_opt, FI_MFULL); break; case 'C': PCL_SET(pclent->pcl_opt, FI_MCHANGE); break; case 'N': PCL_UNSET(pclent->pcl_marks, PCL_MMATCH); break; case 'i': PCL_SET(pclent->pcl_opt, FI_MINO); break; case 'm': PCL_SET(pclent->pcl_opt, FI_MMODE); break; case 'l': PCL_SET(pclent->pcl_opt, FI_MNLINK); break; case 'u': PCL_SET(pclent->pcl_opt, FI_MUID); break; case 'g': PCL_SET(pclent->pcl_opt, FI_MGID); break; case 't': PCL_SET(pclent->pcl_opt, FI_MCTIME); break; case 's': PCL_SET(pclent->pcl_opt, FI_MSIZE); break; case 'f': PCL_SET(pclent->pcl_opt, FI_MFLAGS); break; case 'c': PCL_SET(pclent->pcl_opt, FI_MSHA); break; case ' ': case '\t': break; default: configfile_setsynerror("bad mask"); return (-1); } } for ( ; *arg; ++arg) { switch (*arg) { case 'I': PCL_SET(pclent->pcl_marks, PCL_MINH); break; case 'S': PCL_SET(pclent->pcl_marks, PCL_MSTOP); break; case ' ': case '\t': break; default: configfile_setsynerror("bad options"); return (-1); } } return (0); } static int configfile_readpclbody(fp, pclent, pcl, linebuff) FILE *fp; PCLENT *pclent; PCL *pcl; char *linebuff; { if (configfile_readline(fp, linebuff) < 0) { return (-1); } while (!feof(fp)) { pclent_clear(pclent); if (linebuff[0]=='@') return (0); if (configfile_readpclenthead(fp, pclent, linebuff)!=0) { return (-1); } if (configfile_readpclentbody(fp, pclent, linebuff)!=0) { return (-1); } if (!pcl_add(pcl, pclent)) { configfile_setsyserror("pcl_add()"); return (-1); } } return (0); } static int configfile_readpclhead(fp, pcl, line, pathbuff) FILE *fp; PCL *pcl; char *line, *pathbuff; { const char *word, *arg; configfile_splitline(line, &word, &arg); if (word[0]!='@') { configfile_setsynerror("'@' (node) is expected"); return (-1); } ++word; if (strncmp(word, "POST", 5)==0) { pcl->pcl_inh=PCL_IPOST; } else if (strncmp(word, "PRE", 4)==0) { pcl->pcl_inh=PCL_IPRE; } else if (strncmp(word, "NO", 3)==0) { pcl->pcl_inh=PCL_INO; } else { configfile_setsynerror("bad inheritance"); return (-1); } (void)strncpy(pathbuff, arg, PATH_MAX); if (pathbuff[0]!='/') { configfile_setsynerror("invalid path"); return (-1); } return (0); } void configfile_perror(void) { switch (configfile_error.cf_type) { case CONFIGFILE_ERROR_TSYN: configfile_psynerror(); break; case CONFIGFILE_ERROR_TSYS: configfile_psyserror(); break; case CONFIGFILE_ERROR_TNO: default: break; } } int configfile_read(filename, pclt) const char *filename; PCLT *pclt; { char pathbuff[PATH_MAX], linebuff[CONFIGFILE_LINELEN+1]; FILE *fp; PCL *pcl; PCLENT *pclent; configfile_setzeroerror(); if (!(fp=fopen(filename, "r"))) { configfile_setsyserror(filename); goto fail1; } if (!(pclent=pclent_init())) { configfile_setsyserror("pclent_init()"); goto fail2; } if (configfile_readline(fp, linebuff) < 0) { goto fail3; } while (!feof(fp)) { if (!(pcl=pcl_init())) { configfile_setsyserror("pcl_init()"); goto fail3; } if (configfile_readpclhead(fp, pcl, linebuff, pathbuff)!=0) { goto fail4; } if (configfile_readpclbody(fp, pclent, pcl, linebuff)!=0) { goto fail4; } if (!pclt_add(pclt, pathbuff, pcl)) { configfile_setsyserror("pclt_add()"); goto fail4; } } if (!pclt->ft_root->ft_data) { if (!(pcl=pcl_init())) { configfile_setsyserror("pcl_init()"); goto fail3; } if (!pclt_add(pclt, "/", pcl)) { configfile_setsyserror("pclt_add()"); goto fail4; } } if (pclt_merge(pclt)!=0) { configfile_setsyserror("pclt_merge()"); goto fail3; } pclent_close(pclent); (void)fclose(fp); return (0); fail4: pcl_close(pcl); fail3: pclent_close(pclent); fail2: (void)fclose(fp); fail1: return (-1); }