/*****************************************************************************/ /* (C) Copyright, B. EICHBGERGER, All rights reserved. */ /* */ /* This program remains the exclusive property of B. EICHBERGER */ /* may not be sold, used, copied, displayed or modified without the written */ /* consent of Burkhard Eichberger, P.O.Box 4767, Boulder, Colorado 80306 */ /*****************************************************************************/ #include #include #include #include "def.h" #define EXPARG_M #include "exparg.h" #include "def_s.h" #include "dir.h" VAR_EXT; int system(const char *); #define MAXBUF 100 #define MAXLEAD 20 #define FN_EXP "~" #define FN_CFG "dx.cfg" #define CHR_SYS '`' #define CHR_QUOTE '"' #define CHR_INV '!' #define CHR_SEP ';' #define CHR_PIPE '^' #define CHR_IN '<' #define CHR_OUT '>' #define CHR_ENV1 '%' #define CHR_ENV2 '$' #define CHR_LST '@' int do_arg_xinv = OFF; char do_arg_sep = CHR_SEP; char do_arg_pipe = CHR_PIPE; char do_arg_in = CHR_IN; char do_arg_out = CHR_OUT; char do_arg_dir[MAXFILNAM+1]; /* last directory */ char do_arg_lead[MAXLEAD+1]; /* leadin command */ int do_arg_ins(char *szNew); int do_fillst(char *szArg); int do_getenv(char *szArg,char *szOut); int do_arg_bld(char *szArg); int do_arg_sys(char *szCmd,char *szTail); /****** PROCESS ARGUMENT EXPANSION ******************************************/ /* Input: */ /* ac = Number of arguments on command line */ /* av = Argument Vector */ /* */ /* Output: */ /* 0 = OK */ /* -1 = Cannot open database */ /* -2 = Cannot open window environment */ /* -3 = Cannot open getinp environment */ /* -4 = Cannot get sellst RAM */ /* -5 = Not enough RAM */ /* -6 = Missing string flex file */ /* -7 = Escape at initial screen */ /****************************************************************************/ int do_arg(int ac,char *av[]) { FILE *fcfg; register int i, i0, i1; char buf1[100+1]; char bufcmd[128+1]; char fncfg[MAXFILNAM+1]; char c, c1, c2, cout; char *arg, *p, *p0, *pout; char *ptail; int xend; int xsys; /****** INIT ************************************************************/ argc = 0; MEMZAP0(do_arg_dir,sizeof(do_arg_dir)); /****** PROCESS PROGRAM NAME ********************************************/ do_arg_ins(av[0]); /****** PROCESS ARGUMENTS ***********************************************/ for (i=1; i < ac; i++) { /****** GET ARGUMENT ************************************************/ arg = av[i]; /****** PROCESS FILE LIST *******************************************/ if (do_fillst(arg) == 0) { continue; } /****** PROCESS ENVIRONMENT *****************************************/ if (do_getenv(arg,buf1) == 0) { do_arg_bld(buf1); continue; } /****** CHECK FOR BACK QUOTE SYSTEM CALLS `cmd` *********************/ xsys = OFF; p = arg; pout = do_arg_lead; while ((c = *p++) != '\0') { if (c == CHR_SYS) { xsys = ON; break; } *pout++ = c; } *pout = '\0'; /****** REGULAR PLAIN ARGUMENT **************************************/ if (xsys == OFF) { do_arg_bld(arg); continue; } p0 = p; /****** PROCESS THE CONFIG FILE *************************************/ strncpy(fncfg,av[0],sizeof(fncfg)); p = fncfg + strlen(fncfg) - 1; while (*p != '\\') *p-- = '\0'; p++; strcat(p,FN_CFG); if ((fcfg = fopen(fncfg,"rb")) != NULL) { while (fgetl(bufcmd,sizeof(bufcmd)-1,fcfg) != EOF) { p = bufcmd; cout = '\0'; while ((c = *p++) != '\0') { if (c != '=') continue; if (*p != '\\') { cout = *p; break; } c1 = shtoi(p[1]); c2 = shtoi(p[2]); if ((c1 < 0) || (c2 < 0)) { FERR"exp: Invalid hex number in '%s': %s\n", fncfg,bufcmd); break; } cout = (c1<<4) + c2; break; } if (cout == '\0') continue; if (memcmp(bufcmd,"PIPE=" ,5) == 0) { do_arg_pipe = cout; continue; } if (memcmp(bufcmd,"CMDSEP=",7) == 0) { do_arg_sep = cout; continue; } if (memcmp(bufcmd,"IN=" ,3) == 0) { do_arg_in = cout; continue; } if (memcmp(bufcmd,"OUT=" ,4) == 0) { do_arg_out = cout; continue; } FERR"exp: Incorrect command in '%s': %s\n",fncfg,bufcmd); } fclose(fcfg); } /****** JOIN COMMANDS UNTIL CLOSING BACK QUOTE **********************/ xend = OFF; pout = bufcmd; i0 = i; do { if (i == i0) p = p0; /* start after leadin */ else p = av[i]; /* regular argument */ if (*p == CHR_SYS) p++; /* skip leading backquote ` */ if (do_getenv(p,buf1) == 0) p = buf1; i1 = strlen(p) - 1; ptail = p; while (*ptail != '\0') { if (*ptail != CHR_SYS) { ptail++; continue; } *ptail++ = '\0'; /* cut ` out */ xend = ON; break; } while ((c = *p++) != '\0') { if (c == do_arg_pipe) c = '|'; if (c == do_arg_in ) c = '<'; if (c == do_arg_out ) c = '>'; *pout++ = c; } if (xend == ON) break; *pout++ = ' '; i++; } while (i < ac); *pout = '\0'; do_arg_sys(bufcmd,ptail); } /****** CLEANUP *********************************************************/ unlink(EXP_FN_LST); for (i=0; i < MAXDIRLEV; i++) dir_close(); return(argc); } /****** BUILD NEW ARGUMENT INTO TABLE ***************************************/ /* Input: */ /* argtxt = Text of new argument */ /* */ /* Output: */ /* 0 = Inserted */ /* -1 = Directory contains meta char */ /* -2 = Cannot change to new directory */ /****************************************************************************/ do_arg_bld(argtxt) char *argtxt; { register char c, *p, *p0, *pin, *pout; char *pexp; char *pexpinv; char bufdir[MAXFILNAM+1]; char bufarg[MAXFILNAM+1]; char bufin[MAXFILNAM+1]; char fn[MAXFILNAM+1]; char rdbu[MAXFILNAM+1]; char bufexp[100]; char bufexp_[100]; char bufexpinv[100]; char bufexpinv_[100]; int nlen; int ncolon; int col; int xexp; int xfile; int xdir; int xdrv; int xcopy; int xsamedir; /* same directory as last argument one */ int xroot; /* ON: root directory exception */ int nhit; int ret_, ret; int i, i1, i2; /****** CHECK IF ARGUMENT CONTAINS EXPRESSION(S) ************************/ pin = p0 = argtxt; xexp = OFF; xfile = ON; xcopy = OFF; pexpinv = NULL; c = *pin; if (c == '\'') { xcopy = ON; p0++; } pin = p0 + strlen(p0) - 1; if ((*pin == '\'') || (*pin == '`')) *pin = '\0'; /* strip trailing '` */ if (access(argtxt,ACC_RD) == 0) xcopy = ON; /****** CHECK IF TEXT CONTAINS NO META CHARACTER ************************/ if (xcopy == ON) { NOEXP: /****** INSERT ROOT DIR & CONVERT DOUBLE \\ TO \ ********************/ p = p0; pout = bufarg; i = 0; ncolon = 0; while ((c = *p++) != '\0') { *pout++ = c; if (c == ':') ncolon++; if ((i++ == 1) && (c == ':') && ((*p != '/') && (*p != '\\'))) *pout++ = '/'; } *pout = '\0'; if (ncolon > 1) strncpy(bufarg,p0,sizeof(bufarg)); return(do_arg_ins(bufarg)); } /****** INIT ************************************************************/ MEMZAP0(bufdir,sizeof(bufdir)); MEMZAP0(bufexp,sizeof(bufexp)); /****** SKIP LEADING BLANKS *********************************************/ if (*p0 == CHR_INV) { do_arg_xinv = ON; p0++; strfld(p0,CHR_INV,1,1,bufin,sizeof(bufin)); /* get invert expr */ if (strfld(p0,CHR_INV,2,2,bufexpinv,sizeof(bufexpinv)) > 0) { /****** TRANSLATE THE SHELL EXPRESSION TO REGULAR EXPRESSION ****/ pin = bufexpinv; pout = bufexpinv_; *pout++ = '^'; while ((c = *pin++) != '\0') { /****** ESCAPE **********************************************/ if (c == '\\') { *pout++ = *pin++; continue; } /****** STAR TO: ANY CHAR REPEATED ANY AMOUNT ***************/ if (c == '*') { *pout++ = '.'; *pout++ = '*'; continue; } /****** QUESTION MARK TO: SINGLE CHARACTER ******************/ if (c == '?') { *pout++ = '.'; continue; } /****** DOT TO: ACTUAL CHARACTER DOT ************************/ if (c == '.') { *pout++ = '\\'; *pout++ = c; continue; } *pout++ = c; } *pout++ = '$'; *pout = '\0'; /****** COMPILER REGULAR EXPRESSION *****************************/ if (getenv("REDEBUG") != NULL) FERR"INV: in: %s out: %s\n",bufexpinv,bufexpinv_); pexpinv = regcmp(bufexpinv_,NULL); } } else{ do_arg_xinv = OFF; strncpy(bufin,p0,sizeof(bufin)); } pin = bufin; pout = bufdir; while (*pin == ' ') pin++; /* skip leading blanks */ /****** TRANSLATE \ TO / AND INSERT ROOT / AFTER D: *********************/ p = pin; pout = bufarg; i = 0; ncolon = 0; while ((c = *p++) != '\0') { /****** CHECK FOR RE ESCAPE *****************************************/ if ((c == '/') && (*p == '\\')) { *pout++ = '\\'; *pout++ = *++p; p++; continue; } /****** CHECK FOR DIRECTORY SEPARATOR *******************************/ if (*p == '\\') *p = '/'; /****** COPY ********************************************************/ *pout++ = c; /****** CHECK FOR DRIVE : *******************************************/ if (c == ':') ncolon++; /****** INSERT ROOT DIRECTORY IF DRIVE ******************************/ if ((i++ == 1) && (c == ':') && ((*p != '/') && (*p != '\\'))) *pout++ = '/'; } *pout = '\0'; if (ncolon > 1) strncpy(bufarg,pin,sizeof(bufarg)); /****** SEPARATE DIRECTORY FROM FILE/EXPRESSION *************************/ p0 = bufarg; nlen = strlen(p0); pin = p0 + nlen - 1; xdir = xdrv = OFF; col = nlen; while (pin >= p0) { c = *pin--; col--; if (c == '/') { xdir = ON; break; } } /****** CHECK IF DIRECTORY FOUND ****************************************/ if (xdir == ON) { MEMCPY(bufdir,p0,col); MEMCPY(bufexp,p0+col+1,nlen-col); } else{ sprintf(bufdir,"."); MEMCPY(bufexp,p0,nlen); } /****** CHECK IF META CHARACTER ON DIRECTORY ****************************/ pin = bufdir; xexp = OFF; while ((c = *pin++) != '\0') { switch (c) { case '*': case '?': case '[': case ']': case '^': case '$': xexp = ON; break; } if (xexp == ON) { p0 = argtxt; goto NOEXP; } } /****** GET ALL FILES ***************************************************/ xsamedir = xroot = OFF; if (bufdir[0] == '\0') /* straight root exception */ { xroot = ON; bufdir[0] = '/'; bufdir[1] = '\0'; } if ((bufdir[1] == ':') && (bufdir[2] == '\0')) /* drive root exception */ { xroot = ON; bufdir[2] = '/'; bufdir[3] = '\0'; } if ((i1 = strlen(bufdir)) == (i2 = strlen(do_arg_dir))) { if (memcmp(bufdir,do_arg_dir,i1) == 0) xsamedir = ON; } if (xsamedir == OFF) { MEMCPY(do_arg_dir,bufdir,sizeof(do_arg_dir)); dir_close(); if (dir_open(bufdir) < 1) { p0 = argtxt; goto NOEXP; } } else{ dir_rewind(); } /****** TRANSLATE THE SHELL EXPRESSION TO REGULAR EXPRESSION ************/ pin = bufexp; pout = bufexp_; *pout++ = '^'; while ((c = *pin++) != '\0') { /****** ESCAPE ******************************************************/ if (c == '\\') { *pout++ = *pin++; continue; } /****** STAR TO: ANY CHAR REPEATED ANY AMOUNT ***********************/ if (c == '*') { *pout++ = '.'; *pout++ = '*'; continue; } /****** QUESTION MARK TO: SINGLE CHARACTER **************************/ if (c == '?') { *pout++ = '.'; continue; } /****** DOT TO: ACTUAL CHARACTER DOT ********************************/ if (c == '.') { *pout++ = '\\'; *pout++ = c; continue; } *pout++ = c; } *pout++ = '$'; *pout = '\0'; /****** COMPILER REGULAR EXPRESSION *************************************/ if (getenv("REDEBUG") != NULL) FERR"in: %s out: %s\n",bufexp,bufexp_); if ((pexp = regcmp(bufexp_,NULL)) == NULL) { p0 = argtxt; goto NOEXP; } /****** SCAN FILENAMES **************************************************/ nhit = 0; while (dir_read(fn) == 0) { if ((fn[0] == '.') && (fn[1] == '\0')) continue; if ((fn[0] == '.') && (fn[1] == '.')) continue; if (pexpinv == NULL) { ret_ = regchk(fn,pexp); if (do_arg_xinv == OFF) { if (ret_ != 0) continue; } else{ if (ret_ == 0) continue; } } else{ /****** FIRST CHECK IF HIT ***************************************/ ret_ = regchk(fn,pexpinv); if (ret_ != 0) continue; /****** THEN CHECK IF NOT INVERSE EXPR ***************************/ ret_ = regchk(fn,pexp); if (ret_ == 0) continue; } nhit++; if ((bufdir[0] == '\0') || (memcmp(bufdir,".",2) == 0)) { do_arg_ins(fn); continue; } if (xroot == OFF) sprintf(rdbu,"%s/%s",bufdir,fn); else sprintf(rdbu,"%s%s",bufdir,fn); do_arg_ins(rdbu); } free_(pexp); if (nhit == 0) { p0 = argtxt; goto NOEXP; } ret = 0; return(ret); } /****** INSERT NEW ARGUMENT INTO TABLE **************************************/ /* Input: */ /* argtxt = Text of new argument */ /* */ /* Output: */ /* 0 = Inserted */ /* -1 = Out of memory */ /****************************************************************************/ do_arg_ins(argtxt) char *argtxt; { register char c, *pin; int xfile; int nlen; /****** CHECK IF FIRST TIME ******************************************/ if (argc == 0) { MEMZAP0(argv,sizeof(argv)); if ((argv_p = malloc_(MAXARGVLEN,"argv")) == NULL) return(-1); argv_nwr = 0; } /****** CHECK IF FILE ************************************************/ if (access(argtxt,ACC_RD) == 0) xfile = ON; else xfile = OFF; /****** CHECK MEMORY *************************************************/ nlen = strlen(argtxt) + 1; if ((argv_nwr+nlen) > MAXARGVLEN) { if ((argv_p = malloc_(MAXARGVLEN,"argv")) == NULL) return(-1); argv_nwr = 0; } /****** INSERT NEW ARGUMENT ******************************************/ pin = argtxt; if (argc >= MAXARGV) { if (argc == MAXARGV) { FERR"More than %d arguments\n",MAXARGV); argc++;} return(-3); } argv[argc++] = argv_p; while ((c = *pin++) != '\0') { /****** TRANSLATE CHARACTER TO UNIX STYLE IF FILE/DIRECTORY ******/ if (xfile == ON) { if (c == '\\') c = '/'; else c = tolower(c); } *argv_p++ = c; } *argv_p++ = '\0'; argv_nwr += nlen; return(0); } /****** PROCESS SYSTEM CALL *************************************************/ /* Input: */ /* argtxt = Text of new argument */ /* tail = tail text (if any) */ /* */ /* Output: */ /* 0 = Inserted */ /* -1 = Out of memory */ /****************************************************************************/ do_arg_sys(argtxt,tail) char *argtxt, *tail; { FILE *fin; register char c; char bufcmd[128+1]; char rdbu[MAXBUF+1]; char *p; int xredirect; int nmax, i; /****** INIT ************************************************************/ unlink(FN_EXP); /****** RUN COMMANDS ****************************************************/ i = 1; while (strfld(argtxt,do_arg_sep,i,i,bufcmd,sizeof(bufcmd)) > 0) { i++; xredirect = OFF; p = bufcmd; while ((c = *p++) != '\0') { if (c != '>') continue; xredirect = ON; break; } if (xredirect == OFF) { strcat(bufcmd,">>"); strcat(bufcmd,FN_EXP); } system(bufcmd); } /****** GET RESULT ******************************************************/ if ((fin = fopen(FN_EXP,"rb")) == NULL) return(-1); nmax = 0; while (fgetl(rdbu,MAXBUF,fin) != EOF) nmax++; rewind(fin); i = 0; while (fgetl(rdbu,MAXBUF,fin) != EOF) { if (i++ == 0) sprintf(p = bufcmd,"%s%s",do_arg_lead,rdbu); else p = rdbu; if (i == nmax) strcat(p,tail); do_arg_bld(p); } fclose(fin); unlink(FN_EXP); return(0); } /****** RETRIEVE ENVIRONMENT ************************************************/ /* Input: */ /* arg = argument */ /* out = text output */ /* */ /* Output: */ /* 0 = out filled with environment */ /* 1 = no environment variable given */ /* -1 = environment not found */ /****************************************************************************/ do_getenv(arg,out) char *arg, *out; { char buf1[100]; char *p; char *penv; if ((arg[0] != CHR_ENV1) && (arg[0] != CHR_ENV2)) return(1); strncpy(buf1,arg,sizeof(buf1)); p = buf1 + strlen(buf1) - 1; if (*p == CHR_ENV1) *p = '\0'; /* cancel trailing % */ if (*p == CHR_SYS ) *p = '\0'; /* cancel trailing ` */ strupp(buf1); *out = '\0'; if ((penv = getenv(buf1+1)) == NULL) return(0); strcpy(out,penv); return(0); } /****** PROCESS FILE LIST ***************************************************/ /* Input: */ /* arg = argument */ /* out = text output */ /* */ /* Output: */ /* 0 = out filled with environment */ /* 1 = no environment variable given */ /* -1 = environment not found */ /****************************************************************************/ do_fillst(char *arg) { FILE *fin; char rdbu[MAXBUF+1]; fin = NULL; if (arg[0] != CHR_LST) return(1); if ((fin = fopen(arg+1,"rb")) == NULL) { FERR"ARG: Cannot open file '%s' (%s)\n",arg+1,SYSERR); return(0); /* so that it is not passed on */ } while (fgetl(rdbu,MAXBUF,fin) != EOF) { do_arg_bld(rdbu); } if (fin != NULL) fclose(fin); return(0); }