Category : Batch File Utilities - mostly for DOS
Archive   : RBSETENV.ZIP
Filename : EVAL.C
* 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
#include
#include
#include
#include
#include
#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);
}
Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!
This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.
But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/