/* OSSP rc - Run-command processor ** Copyright (c) 2002 Ralf S. Engelschall ** Copyright (c) 2002 Cable & Wireless Deutschland GmbH ** Copyright (c) 2002 The OSSP Project ** ** This file is part of OSSP rc, a portable Run-command processor ** which can be found at http://www.ossp.org/pkg/lib/rc/ ** ** Permission to use, copy, modify, and distribute this software for ** any purpose with or without fee is hereby granted, provided that ** the above copyright notice and this permission notice appear in all ** copies. ** ** THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED ** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF ** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ** IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR ** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF ** USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, ** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ** OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ** SUCH DAMAGE. ** ** rc_sect.c: Run-command processor ISO C source file */ #include /* For string copy and such data ops */ #include /* For memory ops */ #include /* For mktemp(3) */ #include /* For open(2) */ #include "rc.h" /* Public Rc interface */ /************************************************ * sectionNew(const char *) * * Construct a section * ************************************************/ rc_section_t *sectionNew(const char *szName) { rc_section_t *pSec = NULL; /* Among other things, they make great coffee at Cable & Wireless */ /* This code would probably have more bugs if the coffee was not as good */ pSec = (rc_section_t *)calloc(1, sizeof(rc_section_t)); if (pSec) { pSec->m_szName = malloc((strlen(szName) + 1) * sizeof(char)); strcpy(pSec->m_szName, szName); } else RC_THROW(RC_ERR_MEM); return(pSec); } /************************************************ * sectionCopy(rc_section_t *) * * Opaque copy constructor * ************************************************/ rc_section_t *sectionCopy(rc_section_t *pOrigsec) { rc_section_t *pSec = NULL; /* Today is a rain and no coffee day */ pSec = (rc_section_t *)malloc(sizeof(rc_section_t)); pSec->m_nPri = pOrigsec->m_nPri; pSec->m_nUid = pOrigsec->m_nUid; pSec->m_Bytes = pOrigsec->m_Bytes; /* Deep copy of user name */ if (pOrigsec->m_szLogin) { pSec->m_szLogin = malloc((strlen(pOrigsec->m_szLogin) + sizeof(char))\ * sizeof(char)); strcpy(pSec->m_szLogin, pOrigsec->m_szLogin); } /* Deep copy of section text */ if (pOrigsec->m_szData) { pSec->m_szData = malloc((strlen(pOrigsec->m_szData) + sizeof(char))\ * sizeof(char)); strcpy(pSec->m_szData, pOrigsec->m_szData); } if (!pSec) RC_THROW(RC_ERR_MEM); return(pSec); } /************************************************ * sectionGetXXX(rc_section_t *) * * Accessor methods * ************************************************/ const int sectionGetpri(rc_section_t *pSec) { /* Priority of section, used to order sections during exec|eval|print */ if (pSec) return(pSec->m_nPri); else RC_THROW(RC_ERR_USE); return(0); /* Not reached */ } const int sectionGetuid(rc_section_t *pSec) { /* Userid of section, used with setuid during exec or eval */ if (pSec) return(pSec->m_nUid); else RC_THROW(RC_ERR_USE); return(0); /* Not reached */ } const char *sectionGetlogin(rc_section_t *pSec) { /* User name of section, used for display during print */ if (pSec) return(pSec->m_szLogin); else RC_THROW(RC_ERR_USE); return(0); /* Not reached */ } const char *sectionGetdata(rc_section_t *pSec) { /* Data of section, this is the script body of the particular section */ if (pSec && pSec->m_szData) return(pSec->m_szData); else RC_THROW(RC_ERR_USE); return(0); /* Not reached */ } size_t sectionGetlen(rc_section_t *pSec) { /* Data length of section, length of a script body of a particular section */ if (pSec) return(pSec->m_Bytes); else RC_THROW(RC_ERR_USE); return(0); /* Not reached */ } /************************************************ * sectionSetXXX(rc_section_t *) * * Accessor methods * ************************************************/ rc_return_t sectionSetpri(rc_section_t *pSec, long nPriority) { /* Priority of section, used to order sections during exec|eval|print */ if (pSec) { pSec->m_nPri = nPriority; return(RC_THROW(RC_OK)); } return(RC_THROW(RC_ERR_USE)); } rc_return_t sectionSetuid(rc_section_t *pSec, long nUserid) { /* Userid of section, used with setuid during exec or eval */ if (pSec) { pSec->m_nUid = nUserid; return(RC_THROW(RC_OK)); } return(RC_THROW(RC_ERR_USE)); } rc_return_t sectionSetlogin(rc_section_t *pSec, const char *szLogin) { /* User name of section, used for display during print */ if (pSec) { pSec->m_szLogin = malloc((strlen(szLogin) + 1) * sizeof (char)); strcpy(pSec->m_szLogin, szLogin); return(RC_THROW(RC_OK)); } return(RC_THROW(RC_ERR_USE)); } rc_return_t sectionSetdata(rc_section_t *pSec, const char *kszScript) { /* Data of section, this is the script body of the particular section */ if (pSec) { pSec->m_Bytes = (strlen(kszScript) + sizeof(char)) * sizeof(char); if (pSec->m_szData) { /* The section data is already in use */ free(pSec->m_szData); pSec->m_szData = malloc(pSec->m_Bytes); strcpy(pSec->m_szData, kszScript); } else { /* Set the data the usual way */ pSec->m_szData = malloc(pSec->m_Bytes); strcpy(pSec->m_szData, kszScript); } return(RC_THROW(RC_OK)); } return(RC_THROW(RC_ERR_USE)); } rc_return_t sectionSetndata(rc_section_t *pSec, const char *kszScript, size_t Len) { /* Data of section, this is the script body of the particular section */ if (pSec) { pSec->m_Bytes = Len * sizeof(char) + sizeof(char); /* Set size */ if (pSec->m_szData) { /* The section data is already in use */ free(pSec->m_szData); pSec->m_szData = malloc(pSec->m_Bytes); strncpy(pSec->m_szData, kszScript, Len); *(pSec->m_szData + Len) = NULL; /* Terminate outgoing */ } else { /* Set the data the usual way */ pSec->m_szData = malloc(pSec->m_Bytes); strncpy(pSec->m_szData, kszScript, Len); *(pSec->m_szData + Len) = NULL; /* Terminate outgoing */ } return(RC_THROW(RC_OK)); } return(RC_THROW(RC_ERR_USE)); } /************************************************ * sectionDump(rc_section_t *) * * Print a section to standard out * ************************************************/ rc_return_t sectionDump(rc_section_t *pSec) { const char *szLogin = NULL; if (pSec) { if ((szLogin = sectionGetlogin(pSec)) != NULL) fprintf(stdout, "#su %s\n", szLogin); fprintf(stdout, "%s", sectionGetdata(pSec)); return(RC_THROW(RC_OK)); } else return(RC_THROW(RC_ERR_USE)); } /************************************************ * sectionWrite(rc_section_t *, const char *) * * Print a section to a file * ************************************************/ rc_return_t sectionWrite(rc_section_t *pSec, const char *szPath) { int nFdtmp = open(szPath, O_WRONLY | O_CREAT, 0600); FILE *pStream = NULL; /* Initial sanity checks */ if (!pSec || nFdtmp < 0) return(RC_THROW(RC_ERR_USE)); else pStream = fdopen(nFdtmp, "w"); if (pStream) { fprintf(pStream, "#su %s\n", sectionGetlogin(pSec)); fprintf(pStream, "%s", sectionGetdata(pSec)); fclose(pStream); return(RC_THROW(RC_OK)); } else return(RC_THROW(RC_ERR_USE)); } /************************************************ * sectionDelete(rc_section_t *) * * Destruct a section * ************************************************/ rc_return_t sectionDelete(rc_section_t *pSec) { /* Cleanup our junk */ if (pSec) { if (pSec->m_szData) free(pSec->m_szData); if (pSec->m_szName) free(pSec->m_szName); if (pSec->m_szLogin) free(pSec->m_szLogin); free(pSec); } else /* Dumbass passed an empty section object */ assert(FALSE); return(RC_THROW(RC_OK)); }