home *** CD-ROM | disk | FTP | other *** search
- /*
- * eval.c - evaluate a command, with command substitution, environment variable
- * substitution, and wildcard expansion
- *
- * Author: R. Brittain 4/11/90
- *
- * Popen() is adapted from code obtained from simtel20
- * Recommended wildcard expansion code to use with this is wildargv.c by
- * Frank Whaley and placed in the public domain
- *
- * Syntax:
- * eval command argument argument .....
- *
- * Description:
- * The arguments to eval are first wildcard expanded (wildcards expanded into
- * alphabetically sorted lists as in unix) and then interatively scanned
- * for variable substitutions (%val or $val if you prefer) and command
- * substitutions (commands enclosed in `....`)
- * After the expansion, the first word is taken to be a command, which
- * is then executed , with the rest of the expansion as arguments.
- *
- * Command substitutions are usually performed by loading a shell (%SHELL or
- * %COMSPEC) to run the the command. If the first character of the
- * command is '@' the command is exec'ed directly (much faster than calling
- * system, but only works with .exe and .com files). Loading a shell allows
- * internal commands, batch files, shell aliases and pipelines.
- *
- * The magic characters %,`, and @ are set below by #defines
- *
- * This code placed in the public domain
- *
- * If your shell cannot handle a switch character other than /, #define SWITCH
- * By default, the subshells will be called as %COMSPEC ?c command - where ?
- * is the current switchar. Defining SWITCH forces use of /
- *
- * Revision history
- * 1.0 - first posted to net Dec 90 RB
- * 1.01 - fixed argument parsing so `.....` can span multiple arguments
- * without needing to be double quoted Jan 91 RB
- *
- */
- #include <string.h>
- #include <ctype.h>
- #include <dos.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <process.h>
-
- #include "comsub.h"
-
- #define MEMCHECK(x) if ((x) == NULL) fatal("Out of memory",1)
-
- /* prototypes */
-
- void fatal(char *msg, int status);
- char *concat(char *, char *);
- extern int getswitch(void);
- extern int setswitch(char);
-
- main(int argc, char **argv)
- {
- char version[] = "eval version 1.01 of "__DATE__ ;
- char usage[] = "Usage: eval command argument argument ...\n";
- static char *command_com = "COMMAND.COM";
- static char dash_c[ 3 ] = { '?', 'c', '\0' };
- int status, i;
- char *shell, *bp, *shellpath, *command;
- char saveswitch; /* Save the switch char */
- estring s = {NULL, NULL, 0, 80} ;
-
- if (argc == 1)
- fatal(usage,1);
-
- /* process command line for back-quotes and unexpanded env. vars. */
- rebuild_argv(&argc,&argv);
-
- /* now run the command, with the rest of the line as arguments */
- if (*argv[1] == EXE) {
- /*
- * we can spawn directly, and we know argv is now null terminated,
- * but first we must test the length of the generated command line
- * and truncate it if needed
- */
- int totlen=0;
- for (i=1; argv[i] != NULL; i++) {
- totlen += strlen(argv[i]) + 1;
- if (totlen > MAXARGLINE) {
- /* we ran over in argv[i] - truncate it and all following args */
- *(argv[i] + strlen(argv[i]) - (totlen - MAXARGLINE)) = '\0';
- fputs("Warning: command line too long: truncated\n",stderr);
- argv[i+1] = (char *)NULL;
- break;
- }
- }
- #ifdef DEBUG
- fprintf( stderr, "Running: %s", argv[1]+1 );
- for (i=2; argv[i] != NULL; i++) fprintf(stderr," %s",argv[i]);
- fprintf(stderr,"\n");
- #endif DEBUG
- status = spawnvp( P_WAIT, argv[1]+1, argv+1);
- } else {
- /* we need to call a shell */
- /* first make the arguments into one long string */
- for (i=1; argv[i] != NULL; i++) {
- addstring(&s, " ", 1);
- addstring(&s, argv[i], strlen(argv[i]));
- }
- /* Determine the command processor */
- if( ((shell = getenv( "SHELL" )) == (char *) NULL) &&
- ((shell = getenv( "COMSPEC" )) == (char *) NULL) ) shell = command_com;
- strupr( shell );
- shellpath = shell;
-
- /* Strip off any leading backslash directories */
- shell = strrchr( shellpath, '\\' );
- if ( shell != (char *) NULL )
- ++shell;
- else
- shell = shellpath;
-
- /* Strip off any leading slash directories */
- bp = strrchr( shell, '/' );
- if ( bp != (char *) NULL )
- shell = ++bp;
- if ( strstr( shell, "KSH" ) != NULL ) {
- /* MKS Shell needs quoted argument */
- command = concat("'",s.b);
- command = concat(command,"'");
- } else {
- command = s.b;
- }
- saveswitch = dash_c[ 0 ] = (char) getswitch();
- #ifdef SWITCH
- setswitch('/');
- dash_c[ 0 ] = '/';
- #endif
- /* Test the length of the generated command line */
- if (strlen(command) + strlen(shell) + 4 > MAXARGLINE) {
- fputs("Warning: command line too long: truncated\n",stderr);
- *(command + MAXARGLINE -strlen(shell) -strlen(dash_c) -2) = '\0';
- }
- /* Run the program */
- #ifdef DEBUG
- fprintf(stderr,"Running: (%s) %s %s %s\n",shellpath,shell,dash_c,command);
- #endif DEBUG
- status = spawnl( P_WAIT, shellpath, shell, dash_c, command, (char *) NULL );
- #ifdef SWITCH
- setswitch(saveswitch);
- #endif
- }
- if (status) fprintf(stderr,"eval: %s status %d\n", argv[1], status);
- return(status);
- }
-
- void fatal(char *msg, int status)
- {
- fputs(msg,stderr);
- exit(status);
- }
-
- char *concat(s1, s2)
- char *s1, *s2;
- {
- /*
- * return the concatenation of s1 and s2 in malloced memory
- */
- char *p;
- p = malloc(strlen(s1)+strlen(s2)+2);
- if (p == (char *)NULL) {
- fatal ("Out of memory\n",1);
- } else {
- strcpy(p,s1);
- strcat(p,s2);
- }
- return(p);
- }