diff options
Diffstat (limited to 'funtools/tmain.c')
-rw-r--r-- | funtools/tmain.c | 272 |
1 files changed, 272 insertions, 0 deletions
diff --git a/funtools/tmain.c b/funtools/tmain.c new file mode 100644 index 0000000..d0e41cb --- /dev/null +++ b/funtools/tmain.c @@ -0,0 +1,272 @@ +/* + * + * tmain -- call a funtools main program as a subroutine + * + * saoconfig shmainlib + * make + * make shmainlib + * gcc -g -o tmain -I. -I./util tmain.c libfuntools.a -ldl -lm + * + * gcc -g -o tmain -I. -I./util tmain.c libfuntoolsMainLib.a libfuntools.a + * -ldl -lnsl -lsocket -lm + * + * gcc -g -o tmain -I. -I./util tmain.c libfuntoolsMainLib.a libtclfun.a \ + * libfuntools.a /proj/rd/lib/libtcl8.4.so -ldl -lnsl -lsocket -lm + * + * ./tmain -s libfuntoolsMainLib.dylib $S "fundisp foo[circle(512,512,.1)]" + * or + * ./tmain -s libfuntoolsMainLib.so $S "fundisp foo[circle(512,512,.1)]" + * or + * ./tmain $S 'fundisp xxx[cir(512,512,.1)] | awk "NR>2{print $5}"' + * + */ + +#define DYNAMIC 0 + +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <dlfcn.h> +#include <sys/mman.h> +#include <mainlib.h> +#include <file.h> + +#define HAVE_TCL 0 + +extern char *optarg; +extern int optind; + +#ifdef ANSI_FUNC +int +main (int argc, char **argv) +#else +main(argc, argv) + int argc; + char **argv; +#endif +{ + int c; + int ip; + int len; + int got; + int args; + int prot; + int flags; + int domem=0; + char *buf=NULL; + char *buf2=NULL; + char *shobj=NULL; + char mode[SZ_LINE]; + char tbuf[SZ_LINE]; + char cmd[SZ_LINE]; + char file[SZ_LINE]; + char *ermsg; + char *extn; + char *iname; + char *ibuf; + char *s; + void *dl=NULL; + struct stat statbuf; + MainLib ml=NULL, ml2=NULL; + FILE *fp=NULL; + FILE *ifp=NULL, *ofp=NULL, *efp=NULL; + + /* initialize */ + *mode = '\0'; + + /* we want the args in the same order in which they arrived, and + gnu getopt sometimes changes things without this */ + putenv("POSIXLY_CORRECT=true"); + + /* process switch arguments */ + while ((c = getopt(argc, argv, "mi:e:o:s:t")) != -1){ + switch(c){ + case 'i': + if( !strcmp(optarg, "stdin") ){ + ifp = stdin; + } + else{ + if( !(ifp=fopen(optarg, "r")) ){ + fprintf(stderr, "can't open '%s' for reading\n", optarg); + exit(1); + } + } + snprintf(tbuf, SZ_LINE, "stdin=%d", fileno(ifp)); + if( *mode ) strncat(mode, ",", SZ_LINE); + strncat(mode, tbuf, SZ_LINE); + break; + case 'e': + if( !(efp=fopen(optarg, "w")) ){ + fprintf(stderr, "can't open '%s' for writing\n", optarg); + exit(1); + } + snprintf(tbuf, SZ_LINE, "stderr=%d", fileno(efp)); + if( *mode ) strncat(mode, ",", SZ_LINE); + strncat(mode, tbuf, SZ_LINE); + break; + case 'm': + domem=1; + break; + case 'o': + if( !strcmp(optarg, "stdout") ){ + ofp = stdout; + } + else{ + if( !(ofp=fopen(optarg, "w")) ){ + fprintf(stderr, "can't open '%s' for writing\n", optarg); + exit(1); + } + } + snprintf(tbuf, SZ_LINE, "stdout=%d", fileno(ofp)); + if( *mode ) strncat(mode, ",", SZ_LINE); + strncat(mode, tbuf, SZ_LINE); + break; + case 's': + shobj=optarg; + break; + case 't': + if( *mode ) strncat(mode, ",", SZ_LINE); + strncat(mode, "tcl=0", SZ_LINE); + break; + } + } + + /* process required args */ + args = argc - optind; + if( args < 2 ){ + fprintf(stderr, "usage: %s file cmd\n", argv[0]); + exit(1); + } + iname = argv[optind+0]; + ibuf = argv[optind+1]; + + /* read input file into memory */ + if( domem ){ + if( !(fp = fopen(iname, "r")) ){ + fprintf(stderr, "can't open input file: %s\n", iname); + exit(1); + } + fstat(fileno(fp), &statbuf); + len = statbuf.st_size; + prot = PROT_READ; + flags = MAP_PRIVATE; + s = mmap(NULL, len, prot, flags, fileno(fp), 0); + fclose(fp); + if( !s ){ + fprintf(stderr, "can't mmap input file: %s\n", iname); + exit(1); + } + } + else{ + s = (char *)FileContents(iname, 0, &len); + if( !s ){ + fprintf(stderr, "can't access input file: %s\n", iname); + exit(1); + } + } + +#if DYNAMIC!=1 + /* init routine is statically linked */ + ml = (MainLib)funtoolsMainLibInit(); +#endif + +#if DYNAMIC!=0 + /* load shared object and execute init routine */ + switch( MainLibLoad("funtools", shobj, (void **)&ml2, &ermsg) ){ + case -1: + fprintf(stderr, "can't load shared object %s (%s)\n", shobj, ermsg); + exit(1); + case -2: + fprintf(stderr, "can't init %s (%s)\n", "funtools", ermsg); + exit(1); + case -3: + fprintf(stderr, "invalid call to MainLibLoad (%s)\n", ermsg); + exit(1); + } + /* this is not always an error ( if we have the it linked statically) */ + if( !ml2->mainlibprocess ){ + fprintf(stderr, "no MainLibProcess routine found\n"); + exit(1); + } +#endif + +#if HAVE_TCL + /* initialize Tcl support */ + MainLibInit_Tcl(ml); +#endif + + /* parse command, file containing possible extension, and extra args */ + ip = 0; + *cmd = '\0'; + *file = '\0'; + if( !word(ibuf, cmd, &ip) ){ + fprintf(stderr, "requires a command (and usually a file)\n"); + exit(1); + } + + /* make up command containing memory-based buffer pointer as a filename */ + if( word(ibuf, file, &ip) && *file ){ + strncat(cmd, " ", SZ_LINE-1); + /* internal buffer pointer is passed as filename */ + /* snprintf(tbuf, SZ_LINE, "\"buf:0x%p:%d", s, len); */ + snprintf(tbuf, SZ_LINE, "\"buf:%#lx:%d", (long)s, len); + strncat(cmd, tbuf, SZ_LINE-1); + /* buffer pointer gets extension appended */ + if( (extn = FileExtension(file)) && *extn ) strncat(cmd, extn, SZ_LINE-1); + strncat(cmd, "\"", SZ_LINE-1); + /* extra arguments */ + strncat(cmd, " ", SZ_LINE-1); + strncat(cmd, &ibuf[ip], SZ_LINE-1); + } + + /* call main as library routine */ + fprintf(stderr, "executing: %s\n", cmd); + +#if DYNAMIC == 1 + got = ml2->mainlibprocess(ml2, cmd, &buf, mode); +#elif DYNAMIC == 2 + got = MainLibProcess(ml, cmd, &buf, mode); + got = ml2->mainlibprocess(ml2, cmd, &buf2, mode); +#else + got = MainLibProcess(ml, cmd, &buf, mode); +#endif + + /* handle result */ + if( got < 0 ){ + fprintf(stderr, "could not process cmd '%s'\n", cmd); + exit(1); + } + else if( got == 0 ){ + fprintf(stderr, "no output from cmd '%s'\n", cmd); + } + else if( got > 1 ){ + fprintf(stderr, "%s", buf); + if( buf2 ){ + fprintf(stderr, "\n"); + fprintf(stderr, "%s", buf2); + } + } + + /* clean up */ + if( extn ) xfree(extn); + if( buf ) xfree(buf); + if( s ){ + if( domem ){ + munmap(s, len); + } + else{ + xfree(s); + } + } + + /* close files */ + if( ifp ) fclose(ifp); + if( ofp && (ofp != stdout) ) fclose(ofp); + + /* close mainlib lists */ + if( ml ) MainLibFree(ml); + if( ml2 ) MainLibFree(ml2); + + /* success */ + return 0; +} |