--- rc_file.c 2003/06/18 14:35:29 1.1
+++ rc_file.c 2003/06/26 18:45:14 1.2
@@ -27,10 +27,17 @@
** rc_file.c: Run-command processor ISO C source file
*/
-#include <string.h> /* For string copy and such data ops */
-#include <stdlib.h> /* For memory ops */
-
-#include "rc.h" /* Public Rc interface */
+#include <string.h> /* For string copy and such data ops */
+#include <stdlib.h> /* For memory ops */
+#include <fcntl.h> /* For reading rc files */
+#include <unistd.h> /* For reading rc files */
+#include <ctype.h> /* For isspace(3) */
+#include <pwd.h> /* For getpwuid(3) */
+
+#include "rc.h" /* Public Rc interface */
+#include "rc_const.h" /* For configuration defaults */
+#include "rc_config.h" /* Option definitions */
+#include "rc_pcre.h" /* For section parsing */
/************************************************
@@ -41,8 +48,8 @@
{
rc_file_t *pRcfile = NULL;
- pRcfile = (rc_file_t *)calloc(1, sizeof(rc_file_t)); /* Allocate and clear */
- if (!pRcfile) /* Ensure storage */
+ pRcfile = (rc_file_t *)calloc(1, sizeof(rc_file_t)); /* Allocate and clear */
+ if (!pRcfile) /* Ensure storage */
RC_THROW(RC_ERR_MEM);
if (szName) {
@@ -52,26 +59,282 @@
else
pRcfile->m_szName = NULL;
- /* Default values */
- pRcfile->m_nSecs = -1;
- pRcfile->m_ppSecvec = NULL;
+ /* Start section array with one empty allocated tail item */
+ pRcfile->m_nSecs = 0;
+ pRcfile->m_ppSecvec = malloc(sizeof(rc_section_t *));
+ *pRcfile->m_ppSecvec = NULL;
return(pRcfile);
}
/****************************************************
+* rcfileParse(rc_file_t *) *
+* Parse rcfile contents, initialize any sections *
+****************************************************/
+rc_return_t rcfileParse(rc_file_t *pRcf)
+{
+ rc_script_t *pScript = NULL;
+ char *szLocex = NULL;
+ char *sBuf = NULL;
+ int nFdrc = -1;
+ int nRet = 0;
+
+ if (pRcf->m_nSecs > 0)
+ RC_THROW(RC_ERR_USE); /* Only virgin rcfiles can be parsed */
+
+ /* Build the location path name */
+ if (!configGetval(RC_LOC_VAL)) /* Config should have */
+ RC_THROW(RC_ERR_INT); /* given a locs default */
+ else { /* Only enter block with valid string, strdup can't handle NULL */
+ if (*(configGetval(RC_LOC_VAL) + strlen(configGetval(RC_LOC_VAL)) - sizeof (char)) != '/') {
+ szLocex = malloc(strlen(configGetval(RC_LOC_VAL)) + \
+ sizeof (char) + \
+ strlen("rc.") + \
+ strlen(pRcf->m_szName) + \
+ sizeof (char));
+ strcpy(szLocex, configGetval(RC_LOC_VAL));
+ strcat(szLocex, "/");
+ strcat(szLocex, "rc."); /* FIXME: Make the prefix configurable */
+ strcat(szLocex, pRcf->m_szName);
+ }
+ else {
+ szLocex = malloc(strlen(configGetval(RC_LOC_VAL)) + \
+ strlen("rc.") + \
+ strlen(pRcf->m_szName) + \
+ sizeof (char));
+ strcpy(szLocex, configGetval(RC_LOC_VAL));
+ strcat(szLocex, "rc."); /* FIXME: Make the prefix configurable */
+ strcat(szLocex, pRcf->m_szName);
+ }
+ }
+
+ /* Open the rc file unconditionally */
+ if ((nFdrc = open(szLocex, O_RDONLY)) == -1)
+ RC_THROW(RC_ERR_RCF);
+
+ /* Read data from the rcfile into a temporary script */
+ pScript = scriptNew();
+ sBuf = (char *)calloc(1, RC_READ_BUFSIZE);
+ while ((nRet = read(nFdrc, sBuf, RC_READ_BUFSIZE)) > 0)
+ scriptAppend(pScript, sBuf, nRet);
+
+ if (nRet == -1) /* Handle read errors */
+ RC_THROW(RC_ERR_IO);
+
+ { /* Extract sections from script, and neatly place in rcfile */
+ rc_section_t *pSec = NULL;
+ char *piSecname = NULL;
+ int nLabsize = 0;
+ int nPribytes = 0;
+ char *piSubtemp = NULL; /* To find priority and userid in substrings */
+ char *piBlocend = NULL; /* Misnomer used to control section looping */
+ char *piStart = NULL;
+ char *piEnd = NULL;
+ char *piSep = NULL;
+ char *szUser = NULL;
+ char *szName = NULL;
+ char *szTemp = NULL; /* Holds temporarily the pri and user strings */
+ struct passwd *pPwd = NULL;
+ long nPri = 0;
+ long nUid = 0;
+ int nUserbytes = 0;
+ int nTmp = 0;
+ int nOffset = 0;
+ int nFound = 0;
+ int nVecsize = 0;
+ int nSubstrings = 0;
+ int *pnVec = NULL;
+ const char *kszErr = NULL;
+ const int kiRegopt = PCRE_DOTALL | PCRE_MULTILINE;
+ /*const int kiRegopt = PCRE_DOTALL | PCRE_MULTILINE | PCRE_UNGREEDY;*/
+
+ pcre *pRegex = NULL; /* Perl Compatible Regular Expression */
+ pcre_extra *pExtra = NULL; /* Used for studying an expression */
+
+ if ((pRegex = pcre_compile(configGetval(RC_DEF_VAL), kiRegopt, &kszErr, &nOffset, NULL)) == NULL)
+ RC_THROW(RC_ERR_SYS);
+
+ pExtra = pcre_study(pRegex, 0, &kszErr); /* Study the FSM */
+ if (kszErr) { /* Variable contains a string reference in case of errors */
+ free(pRegex);
+ RC_THROW(RC_ERR_SYS);
+ }
+
+ if (pcre_fullinfo(pRegex, pExtra, PCRE_INFO_CAPTURECOUNT, &nSubstrings))
+ RC_THROW(RC_ERR_SYS);
+
+ /***********************************************************************/
+ /* Reminder: PCRE writes vectors to help identify substrings. */
+ /* That means that in the following code we can */
+ /* execute a compiled PCRE regex (ab)(\s)(.*)$ */
+ /* */
+ /* piBlocend + pnVec[0] = 'start of whole matched string' */
+ /* piBlocend + pnVec[1] = 'end of whole matched string' */
+ /* piBlocend + pnVec[2] = 'start of first substring (ab)' */
+ /* piBlocend + pnVec[3] = 'end of first substring (ab)' */
+ /* piBlocend + pnVec[4] = 'start of second substring (\s)' */
+ /* piBlocend + pnVec[5] = 'end of second substring (\s)' */
+ /* piBlocend + pnVec[6] = 'start of third substring (.*)' */
+ /* piBlocend + pnVec[7] = 'end of third substring (.*)' */
+ /***********************************************************************/
+
+ /* Use multiples of six, because PCRE needs 2x multiples of three */
+ nVecsize = 6 * (nSubstrings > 0 ? nSubstrings : 1);
+ nVecsize *= RC_GOOD_MEASURE; /* Add redundancy factor for error margin */
+ /* pAwesome += RC_GOOD_VIBRATIONS;*/ /* Add good vibes for super action */
+
+ /* Filter the rc file for the section label, do it here the first time */
+ pnVec = calloc(nVecsize, sizeof(int)); /* 2/3 vec 1/3 scrapinfo */
+ nFound = pcre_exec(pRegex, pExtra, *pScript,\
+ strlen(*pScript), 0, 0, pnVec, nVecsize);
+
+ piBlocend = *pScript; /* Start piBlocend pointing to the script object */
+ while (nFound > 1) { /* Loop as long as we have more sections */
+ piSecname = piBlocend + *(pnVec + 2);
+ nLabsize = *(pnVec + 3) - *(pnVec + 2);
+
+ /* Handle the section name and body */
+ piStart = piBlocend + *(pnVec + 6);
+ piEnd = piBlocend + *(pnVec + 7);
+ szName = malloc((nLabsize + 1) * sizeof (char));
+ strncpy(szName, piSecname, nLabsize);
+ *(szName + nLabsize * sizeof (char)) = '\0';
+ pSec = sectionNew(szName);
+ free(szName); /* Get rid of the temporary, actually */
+ szName = NULL; /* just for making a new section string */
+ sectionSetndata(pSec, piStart, piEnd - piStart);
+
+ /* Handle the section parent */
+ sectionSetparent(pSec, pRcf->m_szName);
+
+ /* FIXME: Implement --ParseSectionParam for extra gravy */
+ /* Handle the section priority */
+ piStart = piBlocend + *(pnVec + 4);
+ piEnd = piBlocend + *(pnVec + 5);
+ nPribytes = piEnd - piStart;
+ szTemp = malloc(nPribytes + sizeof (char));
+ strncpy(szTemp, piStart, nPribytes);
+ *(szTemp + nPribytes) = '\0';
+ piSubtemp = strstr(szTemp, RC_DEF_PRG);
+ if (piSubtemp) { /* Priority pattern found */
+ for (nTmp = (int)piSubtemp + strlen(RC_DEF_PRG); \
+ isspace(*(char *)nTmp); nTmp += sizeof (char)); /* Strip */
+ nPri = strtol((char *)nTmp, &piSep, 10);
+ if ((char *)nTmp == piSep) /* No priority number follows */
+ RC_THROW(RC_ERR_USE); /* which is an error */
+ else
+ sectionSetpri(pSec, nPri); /* Found a priority value */
+ }
+ else /* Fallback to default value */
+ sectionSetpri(pSec, RC_DEF_PRI);
+
+ /* Handle the section userid */
+ piSubtemp = strstr(szTemp, RC_DEF_UIG);
+ if (piSubtemp) { /* Userid pattern found */
+ for (nTmp = (int)piSubtemp + strlen(RC_DEF_UIG); \
+ isspace(*(char *)nTmp); nTmp += sizeof (char)); /* Strip */
+ nUid = strtol((char *)nTmp, &piSep, 10);
+ if ((char *)nTmp == piSep) /* No userid number follows */
+ {
+ nUserbytes = strspn((strcspn(piSep, " \t\n") * sizeof (char) + piSep), " \t\n");
+ nUserbytes = (strlen(piSep) - nUserbytes) * sizeof (char);
+ szUser = malloc(nUserbytes + sizeof (char));
+ if (!szUser)
+ RC_THROW(RC_ERR_MEM);
+ strncpy(szUser, (const char *)nTmp, nUserbytes);
+ *(szUser + nUserbytes) = '\0';
+ strtok(szUser, " \t\n");
+ pPwd = getpwnam(szUser);
+ if (pPwd) {
+ sectionSetuid(pSec, pPwd->pw_uid); /* Set to given */
+ sectionSetlogin(pSec, szUser); /* uid and login */
+ }
+ else
+ sectionSetuid(pSec, RC_DEF_UID); /* Set to default */
+ free(szUser);
+ }
+ else {
+ pPwd = getpwuid(nUid);
+ if (pPwd) {
+ sectionSetuid(pSec, nUid); /* Found a value */
+ sectionSetlogin(pSec, pPwd->pw_name); /* uid and login */
+ }
+ else
+ sectionSetuid(pSec, RC_DEF_UID); /* Set to default */
+ }
+ }
+ else /* Fallback to default value */
+ sectionSetuid(pSec, RC_DEF_UID);
+
+ /* Cleanup */
+ free(szTemp);
+ szTemp = NULL;
+
+ /* Copy a new section to that found in the script object */
+ pRcf->m_ppSecvec = realloc(pRcf->m_ppSecvec, sizeof(rc_section_t *) \
+ * (pRcf->m_nSecs + 2));
+ pRcf->m_ppSecvec[pRcf->m_nSecs] = sectionCopy(pSec);
+ pRcf->m_ppSecvec[pRcf->m_nSecs + 1] = NULL;
+ pRcf->m_nSecs++;
+
+ /* Clean up our temporary section */
+ sectionDelete(pSec);
+ pSec = NULL;
+
+ /* Find end of section block */
+ piBlocend += *(pnVec + 1);
+
+ /* Try to match another section */
+ nFound = pcre_exec(pRegex, pExtra, piBlocend,\
+ strlen(piBlocend), 0, 0, pnVec, nVecsize);
+ }
+
+ /* Handle errors */
+ if (nFound == 1) /* User gave no klammern */
+ RC_THROW(RC_ERR_USE); /* so complain about it */
+ else if (nFound < PCRE_ERROR_NOMATCH) /* Generic problem so */
+ RC_THROW(RC_ERR_SYS); /* return an error */
+ }
+
+ /* Deallocate and clean */
+ scriptDelete(pScript);
+ pScript = NULL;
+ free(szLocex);
+ szLocex = NULL;
+ free(sBuf);
+ sBuf = NULL;
+ close(nFdrc);
+
+ return(RC_OK);
+}
+
+/****************************************************
+* rcfileGetsec(rc_file_t *, const char *) *
+* Get a section from the rcfile, and return it *
+****************************************************/
+rc_section_t *rcfileGetsec(rc_file_t *pRcf, const char *szSec)
+{
+ int nIter = 0;
+
+ /* Return the section if it is found */
+ for (nIter = 0; nIter < pRcf->m_nSecs; nIter++) {
+ if (!strcmp(pRcf->m_ppSecvec[nIter]->m_szName, szSec))
+ return(pRcf->m_ppSecvec[nIter]);
+ }
+
+ return NULL;
+}
+
+/****************************************************
* rcfileAppendsec(rc_file_t *, rc_section_t *) *
* Append a section to this rcfile *
****************************************************/
rc_return_t rcfileAppendsec(rc_file_t *pRcfile, rc_section_t *pInsec)
{
- assert(pRcfile); /* Rcfile parameter must be valid */
- if (!pInsec) /* Check sanity */
- return(RC_THROW(RC_ERR_USE));
-
- /* When appending to a brand new rcfile, reset the object key (m_nSecs) */
- if (pRcfile->m_nSecs == -1)
- pRcfile->m_nSecs = 0;
+ assert(pRcfile && pInsec); /* Parameters must be valid */
+
+ /* Grow the number of sections */
+ pRcfile->m_nSecs++;
/* First make our vector larger to hold one more section */
pRcfile->m_ppSecvec = realloc(pRcfile->m_ppSecvec, sizeof(rc_section_t *) \
@@ -83,6 +346,13 @@
pRcfile->m_ppSecvec[pRcfile->m_nSecs]->m_nPri = pInsec->m_nPri;
pRcfile->m_ppSecvec[pRcfile->m_nSecs]->m_nUid = pInsec->m_nUid;
+ /* Deep copy of parent */
+ if (pInsec->m_szParent) {
+ pRcfile->m_ppSecvec[pRcfile->m_nSecs]->m_szParent = \
+ malloc((strlen(pInsec->m_szParent) + sizeof(char)) * sizeof(char));
+ strcpy(pRcfile->m_ppSecvec[pRcfile->m_nSecs]->m_szParent, pInsec->m_szParent);
+ }
+
/* Deep copy of user name */
if (pInsec->m_szLogin) {
pRcfile->m_ppSecvec[pRcfile->m_nSecs]->m_szLogin = \
@@ -91,14 +361,8 @@
}
/* Deep copy of section text */
- if (pInsec->m_szData) {
- pRcfile->m_ppSecvec[pRcfile->m_nSecs]->m_szData = \
- malloc((strlen(pInsec->m_szData) + sizeof(char)) * sizeof(char));
- strcpy(pRcfile->m_ppSecvec[pRcfile->m_nSecs]->m_szData, pInsec->m_szData);
- }
-
- /* Finally increment section count */
- pRcfile->m_nSecs++;
+ if (scriptGetdata(pInsec->m_pData))
+ scriptSetdata(pRcfile->m_ppSecvec[pRcfile->m_nSecs]->m_pData, pInsec->m_pData);
return(RC_THROW(RC_OK));
}
@@ -156,26 +420,24 @@
{
int nSecs = pRcfile->m_nSecs;
+ assert(pRcfile); /* Stupidity check */
+
/* Cleanup our junk */
- if (pRcfile) {
- pRcfile->m_nSecs = 0; /* Blank the section count */
- if (pRcfile->m_szName) { /* Destroy the rc name */
- free(pRcfile->m_szName);
- pRcfile->m_szName = NULL;
- }
- while (nSecs-- > 0) { /* Destroy the section vector */
- if (pRcfile->m_ppSecvec[nSecs]) {
- sectionDelete(pRcfile->m_ppSecvec[nSecs]);
- pRcfile->m_ppSecvec[nSecs] = NULL;
- }
+ pRcfile->m_nSecs = 0; /* Blank the section count */
+ if (pRcfile->m_szName) { /* Destroy the rc name */
+ free(pRcfile->m_szName);
+ pRcfile->m_szName = NULL;
+ }
+ while (--nSecs >= 0) { /* Destroy the section vector */
+ if (pRcfile->m_ppSecvec[nSecs]) {
+ sectionDelete(pRcfile->m_ppSecvec[nSecs]);
+ pRcfile->m_ppSecvec[nSecs] = NULL;
}
- free(pRcfile->m_ppSecvec);
- pRcfile->m_ppSecvec = NULL;
- free(pRcfile);
- pRcfile = NULL;
}
- else /* Dumbass passed an empty rcfile object */
- assert(FALSE);
+ free(pRcfile->m_ppSecvec);
+ pRcfile->m_ppSecvec = NULL;
+ free(pRcfile);
+ pRcfile = NULL;
return(RC_THROW(RC_OK));
}
|