diff options
Diffstat (limited to 'funtools/util/mainlib.c')
-rw-r--r-- | funtools/util/mainlib.c | 790 |
1 files changed, 0 insertions, 790 deletions
diff --git a/funtools/util/mainlib.c b/funtools/util/mainlib.c deleted file mode 100644 index fd3da89..0000000 --- a/funtools/util/mainlib.c +++ /dev/null @@ -1,790 +0,0 @@ -/* - * Copyright (c) 2004 Smithsonian Astrophysical Observatory - */ - -/* - * mainlib.c -- support for main routines called as library subroutines - * - */ - -#include <mainlib.h> - -extern char *optarg; -extern int optind; - -/* - * - * private routines - * - */ - -/* - *---------------------------------------------------------------------------- - * - * Routine: Pipe2Buf - * - * Purpose: read pipe til EOF and fill buffer with results - * - * Results: number of bytes read (and buffer in passed argument) - * - *---------------------------------------------------------------------------- - */ -#ifdef ANSI_FUNC -static int -Pipe2Buf(int fd, char **buf) -#else -static int Pipe2Buf(fd, buf) - int fd; - char **buf; -#endif -{ - int got; - int clen=0; - int blen=0; - - /* initial buffer size */ - blen = SZ_LINE*10; - *buf = xmalloc(blen); - - /* read til EOF and fill buffer */ - while( 1 ){ - /* reallocate as needed */ - if( (clen + SZ_LINE) >= blen ){ - blen += SZ_LINE*10; - *buf = xrealloc(*buf, blen); - } - /* read */ - got=read(fd, *buf+clen, SZ_LINE); - /* got data */ - if( got > 0 ){ - clen += got; - continue; - } - /* EOF */ - else if( got == 0 ){ - /* reallocate to actual size, but null terminate as a courtesy */ - blen = clen+1; - *buf = xrealloc(*buf, blen); - *(*buf+clen) = '\0'; - break; - } - /* error */ - else{ - xfree(*buf); - blen = -1; - break; - } - } - /* return the news */ - return blen; -} - -/* - *--------------------------------------------------------------------------- - * - * Routine: MainLibListAdd - * - * Purpose: add a member of an mainlib list - * - * Results: 1 on success, 0 for failure - * - *--------------------------------------------------------------------------- - */ -#ifdef ANSI_FUNC -static void -MainLibListAdd (MainLib ml, MainLibEntry mle) -#else -static void MainLibListAdd(ml, mle) - MainLib ml; - MainLibEntry mle; -#endif -{ - MainLibEntry cur; - - if( ml->head == NULL ){ - ml->head = mle; - } - else{ - for(cur=ml->head; cur->next!=NULL; cur=cur->next) - ; - cur->next = mle; - } -} - -/* - *--------------------------------------------------------------------------- - * - * Routine: MainLibListDel - * - * Purpose: remove a member of an mainlib list - * - * Results: 1 on success, 0 for failure - * - *--------------------------------------------------------------------------- - */ -#ifdef ANSI_FUNC -static void -MainLibListDel (MainLib ml, MainLibEntry mle) -#else -static void MainLibListDel(ml, mle) - MainLib ml; - MainLibEntry mle; -#endif -{ - MainLibEntry cur; - - /* remove from list of mainlibs */ - if( ml->head ){ - if( ml->head == mle ){ - ml->head = mle->next; - } - else{ - for(cur=ml->head; cur!=NULL; cur=cur->next){ - if( cur->next == mle ){ - cur->next = mle->next; - break; - } - } - } - } -} - -/* - * - * semi-public routines - * - */ - -/* - *--------------------------------------------------------------------------- - * - * Routine: MainLibLookup - * - * Purpose: lookup a mainlib procedure - * - * Results: MainLibEntry record on success, NULL on failure - * - *--------------------------------------------------------------------------- - */ -#ifdef ANSI_FUNC -MainLibEntry -MainLibLookup (MainLib ml, char *xclass, char *name) -#else -MainLibEntry MainLibLookup(ml, xclass, name) - MainLib ml; - char *xclass; - char *name; -#endif -{ - MainLibEntry cur; - - if( !ml || (!xclass && !name) ) return NULL; - - for(cur=ml->head; cur!=NULL; cur=cur->next){ - if( (!xclass || !strcmp(xclass, cur->xclass)) && - (!name || !strcmp(name, cur->name)) ){ - return cur; - } - } - return NULL; -} - -/* - * - * public routines - * - */ - -/* - *---------------------------------------------------------------------------- - * - * Routine: MainLibNew - * - * Purpose: create mainlib struct - * - * Returns: mainlib list handle or NULL - * - *---------------------------------------------------------------------------- - */ -#ifdef ANSI_FUNC -MainLib -MainLibNew (void) -#else -MainLib MainLibNew() -#endif -{ - MainLib ml; - - /* allocate struct */ - if( !(ml = (MainLib)xcalloc(1, sizeof(MainLibRec))) ) - return NULL; - return ml; -} - -/* - *---------------------------------------------------------------------------- - * - * Routine: MainLibAdd - * - * Purpose: add a mainlib name to allow external processes to be called - * as subroutines - * - * Returns: mainlib handle associated with this name or NULL - * - *---------------------------------------------------------------------------- - */ -#ifdef ANSI_FUNC -MainLibEntry -MainLibAdd (MainLib ml, char *xclass, char *name, MainLibProc proc, int type) -#else -MainLibEntry MainLibAdd(ml, xclass, name, proc, type) - MainLib ml; - char *xclass; - char *name; - MainLibProc proc; - int type; -#endif -{ - MainLibEntry mle; - - /* sanity check */ - if( !ml ) return NULL; - - /* allocate struct */ - if( !(mle = (MainLibEntry)xcalloc(1, sizeof(MainLibEntryRec))) ) return NULL; - /* fill in the blanks */ - mle->xclass = xstrdup(xclass); - mle->name = xstrdup(name); - mle->proc = proc; - mle->type = type; - /* add to list */ - MainLibListAdd(ml, mle); - return mle; -} - -/* - *---------------------------------------------------------------------------- - * - * Routine: MainLibProcess - * - * Purpose: call external processes as subroutines - * - * Results: number of bytes in return buffer (buffer in passed argument) - * - *---------------------------------------------------------------------------- - */ -#ifdef ANSI_FUNC -int MainLibProcess(MainLib ml, char *cmd, char **buf, char *mode) -#else -int MainLibProcess(ml, cmd, buf, mode) - MainLib ml; - char *cmd; - char **buf; - char *mode; -#endif -{ - int i, j; - int got; - int ncmd=0; - int ip=0; - int ifd=-1; - int ofd=-1; - int efd=-1; - int fillbuf=1; - int debug=0; - int use_ifd=0; - int use_ofd=0; - int use_efd=0; -#if HAVE_TCL - int use_tcl=0; -#endif - int nargs[MAINLIB_CMDS+1]; - int pipes[MAINLIB_CMDS+1][2]; - char *c, *s, *t; - char *undef=NULL; - char tbuf[SZ_LINE]; - char ibuf[SZ_LINE]; - char ibuf2[SZ_LINE]; - char *args[(MAINLIB_CMDS+1)*MAINLIB_ARGS]; - char *cmds[MAINLIB_CMDS+1]; -#if HAVE_TCL - void *tcl=NULL; -#endif - MainLibEntry mles[MAINLIB_CMDS+1]; - static int mainlibinit=0; - static int mainlib_debug=0; - static char *mainlib_path=NULL; - - /* sanity check */ - if( !ml ){ - gerror(stderr, "invalid or missing command list for mainlib\n"); - got = -1; - goto done; - } - - /* initialization */ - if( !mainlibinit ){ - if( (s = (char *)getenv("MAINLIB_DEBUG")) ) - mainlib_debug = istrue(s); - mainlib_path = (char *)getenv("PATH"); - mainlibinit = 1; - } - - /* clear arrays */ - memset(cmds, 0, sizeof(char *)*(MAINLIB_CMDS+1)); - memset(mles, 0, sizeof(MainLibEntry)*(MAINLIB_CMDS+1)); - memset(args, 0, sizeof(char *)*(MAINLIB_CMDS+1)*MAINLIB_ARGS); - - /* separate commands */ - c = xstrdup(cmd); - for(s=c; (t=strchr(s, '|'))!=NULL; s=t+1){ - if( ncmd >= MAINLIB_CMDS ){ - gerror(stderr, "max cmds exceeded (%d) for mainlib\n", ncmd); - got = -1; - goto done; - } - *t = '\0'; - cmds[++ncmd] = xstrdup(s); - } - /* get last command */ - cmds[++ncmd] = xstrdup(s); - if( c ) xfree(c); - - /* seed the debug flag (override with switch) */ - debug = mainlib_debug; - - /* check mode string */ - if( (t = xstrdup(mode)) ){ - if( keyword(t, "stdin", tbuf, SZ_LINE) ) ifd = atoi(tbuf); - if( keyword(t, "stdout", tbuf, SZ_LINE) ) ofd = atoi(tbuf); - if( keyword(t, "stderr", tbuf, SZ_LINE) ) efd = atoi(tbuf); - if( keyword(t, "undef", tbuf, SZ_LINE) ) undef = xstrdup(tbuf); - if( keyword(t, "fillbuf", tbuf, SZ_LINE) ) fillbuf = istrue(tbuf); - if( keyword(t, "debug", tbuf, SZ_LINE) ) debug = istrue(tbuf); -#if HAVE_TCL - if( keyword(t, "tcl", tbuf, SZ_LINE) ){ - sscanf(tbuf, "%p", &tcl); - use_tcl=1; - } -#endif - xfree(t); - } - /* make sure unef is defined */ - if( !undef ){ - undef = xstrdup("extn"); - } - - /* pipe for top level */ - pipe(pipes[0]); - - /* package up arguments for each command */ - for(i=1; i<=ncmd; i++){ - if( pipe(pipes[i]) < 0 ){ - gerror(stderr, "can't set up pipes for mainlib\n"); - got = -1; - goto done; - } - ip = 0; - /* make sure we have a command */ - if( !word(cmds[i], ibuf, &ip) ){ - gerror(stderr, "invalid or missing command for mainlib\n"); - got = -1; - goto done; - } - /* make sure its a valid command */ - nowhite(ibuf, ibuf2); - if( !(mles[i] = MainLibLookup(ml, NULL, ibuf2)) ){ - if( undef ){ - ip = 0; - while( word(undef, tbuf, &ip) ){ - if( !strcasecmp(tbuf, "error") ){ - break; - } -#if HAVE_TCL - else if( use_tcl && ml->tcllookup && ml->tcllookup(tcl, ibuf2) ){ - mles[i] = MainLibAdd(ml, cmds[i], ibuf2, NULL, MAINLIB_TCL); - break; - } -#endif - else if( (s=Find(ibuf2, "x", NULL, mainlib_path)) != NULL ){ - mles[i] = MainLibAdd(ml, s, ibuf2, NULL, MAINLIB_EXTN); - xfree(s); - break; - } - } - if( !mles[i] ){ - gerror(stderr, "can't locate procedure '%s' for mainlib\n", ibuf); - got = -1; - goto done; - } - } -#ifdef OLD - switch(mainlibundef){ - case MAINLIB_ERROR: - gerror(stderr, "can't locate procedure '%s' for mainlib\n", ibuf); - got = -1; - goto done; - case MAINLIB_EXTN: - if( (s=Find(ibuf2, "x", NULL, mainlib_path)) != NULL ){ - mles[i] = MainLibAdd(ml, s, ibuf2, NULL, MAINLIB_EXTN); - xfree(s); - } - else - gerror(stderr, "can't locate procedure '%s' for mainlib\n", ibuf); - break; - default: - gerror(stderr, "can't locate procedure '%s' for mainlib\n", ibuf); - got = -1; - goto done; - } -#endif - - } - - /* package up the arguments */ - ip = 0; - nargs[i] = 0; - while( word(cmds[i], ibuf, &ip) ){ - nowhite(ibuf, ibuf2); - if( *ibuf2 ){ - if( nargs[i] >= (MAINLIB_ARGS-1) ){ - gerror(stderr, "max args exceeded (%d) for mainlib\n", nargs[i]); - got = -1; - goto done; - } - args[i*MAINLIB_ARGS+nargs[i]] = xstrdup(ibuf2); - nargs[i]++; - args[i*MAINLIB_ARGS+nargs[i]] = NULL; - } - } - } - - /* execute all commands */ - for(i=1; i<=ncmd; i++){ - /* fork new process */ - if( (ml->pids[i] = fork()) == -1 ){ - gerror(stderr, "can't fork()\n"); - got = -1; - goto done; - } - /* child will call mainlib routine */ - if( ml->pids[i] == 0 ){ - /* reset optind in case its being used by child */ - optind = 1; - /* stdin for this new process is */ - if( i == 1 ){ - /* first process either reads stdin from specified ifd, - or else we leave it alone */ - if( ifd >= 0 ){ - if( ifd != 0 ){ - close(0); dup(ifd); - } - else{ - use_ifd = 1; - } - } - } - /* all other processes read stdin from previous process stdout */ - else{ - close(0); dup(pipes[i][0]); - } - /* set up stdout for this new process */ - if( i < ncmd ){ - close(1); dup(pipes[i+1][1]); - } - else{ - /* last process either writes stdout or to specified ofd */ - if( ofd >= 0 ){ - if( ofd != 1 ){ - close(1); dup(ofd); - } - else{ - use_ofd = 1; - } - } - /* or sends stdout to main process */ - else{ - close(1); dup(pipes[0][1]); - } - } - /* all processes redirect stderr, if required */ - if( efd >= 0 ){ - if( efd != 2 ){ - close(2); dup(efd); - } - else{ - use_efd = 1; - } - } - /* close all pipes */ - for(j=0; j<=ncmd; j++){ - close(pipes[j][0]); close(pipes[j][1]); - } - /* including user-specified pipes */ - if( (ifd >=0) && !use_ifd ) close(ifd); - if( (ofd >=0) && !use_ofd ) close(ofd); - if( (efd >=0) && !use_efd ) close(efd); - /* call specified subroutine */ - switch(mles[i]->type){ - case MAINLIB_ARGV: - if( debug ) - fprintf(stderr, "Executing MainLib: %s\n", args[i*MAINLIB_ARGS]); - mles[i]->proc(nargs[i], &args[i*MAINLIB_ARGS]); - break; - case MAINLIB_EXTN: - if( debug ) - fprintf(stderr, "Executing external program: %s\n", mles[i]->xclass); - if( mles[i]->xclass ) - execvp(mles[i]->xclass, (void *)&args[i*MAINLIB_ARGS]); - else - execvp(mles[i]->name, (void *)&args[i*MAINLIB_ARGS]); - break; -#if HAVE_TCL - case MAINLIB_TCL: - if( debug ) - fprintf(stderr, "Executing Tcl proc: %s\n", mles[i]->xclass); - if( use_tcl && ml->tcleval){ - ml->tcleval(tcl, mles[i]->xclass); - } - else{ - gerror(stderr, "Tcl support missing for mainlib\n"); - } - break; -#endif - default: - gerror(stderr, "unknown program type for mainlib\n"); - break; - } - _exit(0); - } - } - - /* close all pipes except the final input pipe */ - close(pipes[0][1]); - for(i=1; i<=ncmd; i++){ - close(pipes[i][0]); - close(pipes[i][1]); - } - - /* if not filling buffer, just return the pipe (user calls cleanup) */ - if( !fillbuf ){ - got = pipes[0][0]; - ml->npid = ncmd; - goto done2; - } - - /* wait for output from last process */ - got = Pipe2Buf(pipes[0][0], buf); - - /* and now close final input pipe */ - close(pipes[0][0]); - -done: - /* done with processing, wait for children to finish */ - MainLibProcessCleanup(ml); - -done2: - /* free up space */ - for(i=1; i<=ncmd; i++){ - for(j=0; j<nargs[i]; j++){ - if( args[i*MAINLIB_ARGS+j] ) xfree(args[i*MAINLIB_ARGS+j]); - } - if( cmds[i] ) xfree(cmds[i]); - } - if( undef ) xfree(undef); - - /* return: error (-1), number of bytes in buffer, or pipe fd */ - return got; -} - -/* - *--------------------------------------------------------------------------- - * - * Routine: MainLibProcessCleanup - * - * Purpose: cleanup after mainlib processing - * - * Results: 1 on success, 0 for failure - * - *--------------------------------------------------------------------------- - */ -#ifdef ANSI_FUNC -int -MainLibProcessCleanup (MainLib ml) -#else -int MainLibProcessCleanup(ml) - MainLib ml; -#endif -{ - int i; - int status; - - for(i=1; i<=ml->npid; i++){ - if( ml->pids[i] ){ -#if HAVE_MINGW32==0 - while( waitpid(ml->pids[i], &status, 0) < 0 ){ - if( errno != EINTR ) break; - } -#endif - ml->pids[i] = 0; - } - } - return 1; -} - -/* - *--------------------------------------------------------------------------- - * - * Routine: MainLibDel - * - * Purpose: delete a MainLibEntry record structure - * - * Results: 0 on success, -1 for failure - * - *--------------------------------------------------------------------------- - */ -#ifdef ANSI_FUNC -int -MainLibDel (MainLib ml, MainLibEntry mle) -#else -int MainLibDel(ml, mle) - MainLib ml; - MainLibEntry mle; -#endif -{ - - /* make sure we have something to do */ - if( !ml || !mle ) return -1; - - /* free up space */ - if( mle->xclass ) xfree(mle->xclass); - if( mle->name ) xfree(mle->name); - - /* remove from list of mainlibs */ - MainLibListDel(ml, mle); - - /* free up record struct */ - xfree((char *)mle); - - return 0; -} - -/* - *--------------------------------------------------------------------------- - * - * Routine: MainLibFree - * - * Purpose: free all members of this mainlib list - * - * Results: 1 on success, 0 for failure - * - *--------------------------------------------------------------------------- - */ -#ifdef ANSI_FUNC -int -MainLibFree (MainLib ml) -#else -int MainLibFree(ml) - MainLib ml; -#endif -{ - MainLibEntry mle, tmle; - - /* sanity check */ - if( !ml ) return 0; - - /* free all commands */ - for(mle=ml->head; mle!=NULL; ){ - tmle = mle->next; - MainLibDel(ml, mle); - mle = tmle; - } - -#if HAVE_DLFCN_H - /* release dynamic library */ - if( ml->dl ) dlclose(ml->dl); -#endif - - /* free global struct */ - xfree(ml); - return 1; -} - -/* - *---------------------------------------------------------------------------- - * - * Routine: MainLibLoad - * - * Purpose: load shared library and execute init function - * - * Results: 0=>OK, -1=> no shared obj, -2=>no init function - * - *---------------------------------------------------------------------------- - */ -#ifdef ANSI_FUNC -int MainLibLoad(char *name, char *shlib, void **ml, char **ermsg) -#else -int MainLibLoad(name, shlib, ml, ermsg) - char *name; - char *shlib; - void **ml; - char **ermsg; -#endif -{ -#if HAVE_DLFCN_H - char tbuf[SZ_LINE]; - MainLibInitCall irtn=NULL; - MainLib tml=NULL; - void *tdl=NULL; - - /* sanity checks */ - if( !name ){ - if( ermsg ) *ermsg = "no package name specified"; - return -3; - } - if( !ml ){ - if( ermsg ) *ermsg = "no return ml struct specified"; - return -3; - } - - /* get name of init call */ - snprintf(tbuf, SZ_LINE-1, "%sMainLibInit", name); - - /* load shared library */ - if( !(tdl=dlopen(shlib, RTLD_LAZY)) ){ - if( ermsg ) *ermsg = (char *)dlerror(); - return -1; - } - - /* look up init funtion */ - if( !(irtn=(MainLibInitCall)dlsym(tdl, tbuf)) ){ - if( ermsg ) *ermsg = (char *)dlerror(); - return -2; - } - - /* execute init function */ - tml = (*irtn)(); - - /* store values */ - tml->dl = tdl; - - /* look up and return MainLibProcess funtion, if it exists */ - tml->mainlibprocess=(MainLibProcessCall)dlsym(tml->dl, "MainLibProcess"); - - /* store MainLib record */ - *ml = tml; - - /* if we got here, its OK */ - return 0; -#else - /* avoid -W unused parameter warning */ - if( 0 ){ - name = name; - shlib = shlib; - ml = ml; - } - /* didn't find dlfcn.h */ - if( ermsg ) *ermsg = "dynamic load supported not found"; - return -1; -#endif -} |