home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS 1992 September
/
Simtel20_Sept92.cdr
/
msdos
/
pcmag
/
vol7n14.arc
/
PATHSUB.C
< prev
next >
Wrap
C/C++ Source or Header
|
1988-06-30
|
12KB
|
342 lines
/*- PATHSUB - Substitute strings in environment variables (default: PATH)
Usage: PATHSUB [/var] pat sub
PATHSUB will substitute the 1st occurrance of 'pat' in the environment
variable 'var' with the replacement string 'sub'. Both 'pat' and 'sub'
are required. The default environment variable is "PATH".
If 'var' is specified, it is converted to uppercase. Both 'pat' and
'sub' are case sensitive.
There are two special values for the parameter 'pat'. If 'pat' is "^"
then 'sub' will be placed at the head of the environment variable (after
the '=' seperating the variable name from the value). If 'pat' is "$"
then 'sub' will be placed at the end of the environment. Note that
this is not full regular expression matching. The pattern "^C:\BIN"
will NOT attempt to find "C:\BIN" at the head of the path, but will
search for "^C:\BIN" anywhere in the path.
If you wish to delete something from the path, overspecify the pattern
and make the replacement match the extra e.g.:
PATHSUB ;C:\UTILS; ;
Exit codes:
4 - Program could not run, not enough parameters
3 - Program could not locate environment variable
2 - Pattern not found in environment variable
1 - Program could not update environment, substitution too big
0 - Success
*/
#include <stdio.h>
#include <stdlib.h>
#include <process.h>
#include <memory.h>
#include <ctype.h>
#include <dos.h>
#include <string.h>
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
#ifndef NULL
#define NULL 0
#endif
#define Lastchar(string) string[strlen(string)-1]
#define DEBUG TRUE
#define VERBOSE TRUE
#define ENV_OFF 0x2C /* environment segment */
#define PPSP_OFF 0x16 /* parent PSP */
/* PSP of copy of COMMAND.COM that invoked current process */
#define RPSP_OFF 0x10
/* Maximum memory block we will try to deal with is 255 Paragraphs long */
#define MAXLEN 0xFF0
extern unsigned _psp; /* from MSC: PSP segment for this task */
unsigned _rpsp; /* "root" PSP segment */
unsigned _cpsp; /* current PSP segment */
unsigned _env_seg; /* environment segment */
unsigned _ctrl_seg; /* memory control block segment */
unsigned _mem_seg; /* memory block segment */
struct _ctrl_block
{
char type; /* 'M' more memory follows, 'Z' zero more blocks */
unsigned owner; /* PSP of task which owns this memory */
unsigned length; /* # of segments in this block of memory */
} ctrl_block;
unsigned char mem_block[MAXLEN];
main(argc, argv)
int argc;
char *argv[];
{
unsigned _showds();
static char cmdpath[256];
static char path[256];
static char target[100] = { "PATH=" };
char *comspec,*pos;
int i, done;
int ppos, off;
unsigned ds;
int firstarg;
firstarg=1;
/* if alternate environment var specified */
if (argv[firstarg][0] == '/')
{
strcpy(target, argv[firstarg++]+1); /* copy from arg (after '/') */
strcat(target, "="); /* append an '=' */
strupr(target); /* convert to uppercase */
}
if (argc < firstarg+2)
{
fprintf(stderr, "\nPATHSUB: Usage - PATHSUB [/var] pat sub");
exit(4);
}
ds = _showds(); /* get our data segment */
_rpsp = _psp; /* start w/ our own PSP segment */
_cpsp = _rpsp ^ 0xFFFF; /* Dummy value to start with */
while (_cpsp != _rpsp) /* while haven't found PSP of 1st COMMAND */
{
_cpsp = _rpsp; /* up another layer */
/* get "root" PSP segment */
movedata(_cpsp, RPSP_OFF, ds, (unsigned)&_rpsp, 2);
}
/* get the memory control block from the root PSP */
_mem_seg = _cpsp; /* start with the PSP segment */
_ctrl_seg = _cpsp - 1; /* and back up by one segment */
/* copy it to where we can use it */
movedata(_ctrl_seg, 0, ds, (unsigned)&ctrl_block, sizeof(ctrl_block));
done = FALSE;
ppos = -1;
while (!done)
{
/* find next control block */
_ctrl_seg = _mem_seg + ctrl_block.length;
/* & next block of memory */
_mem_seg = _ctrl_seg + 1;
/* load control block */
movedata(_ctrl_seg, 0, ds, (unsigned)&ctrl_block.type, 5);
done = (ctrl_block.type != 'M');
if(!done)
/* examine mem block, if not too big */
if(ctrl_block.length < MAXLEN)
{
/* Load the block */
movedata(_mem_seg, 0, ds, (unsigned)mem_block,
ctrl_block.length*16);
/* find the first occurance of our pattern in the block */
/* if it does not appear, result will be -1 */
/* search the block */
for(ppos = off = 0; !done && off != -1; ppos++)
{
/* if found */
if( (off = memsrch(&mem_block[ppos], target,
(ctrl_block.length*16)-off )) != -1)
{
ppos+=off;
/* and if valid */
if(ppos == 0 || mem_block[ppos-1] == NULL)
{
done = TRUE; /* set to break main loop */
break; /* get out of for loop */
}
}
}
} /* end: look through this memory block */
} /* end: look through all memory blocks */
if((ppos == -1) || (ctrl_block.type != 'M'))
{
Lastchar(target);
fprintf(stderr,
"\nPATHSUB: Could not locate environment variable [%s].",
target);
exit(3);
}
strcpy(path, &mem_block[ppos]); /* copy our current "PATH=" string */
if(!strcmp(argv[firstarg],"^")) /* Insert at head of path */
sprintf(cmdpath,"%s%s%s", target, argv[firstarg+1],
path+strlen(target));
else if (!strcmp(argv[firstarg], "$")) /* Append to tail of path */
sprintf(cmdpath, "%s%s",path,argv[firstarg+1]);
else /* Substitute into path */
{
strcpy(cmdpath,path);
i = strsub(cmdpath+strlen(target), argv[firstarg],
argv[firstarg+1], 1);
if(i == 0)
{
target[strlen(target)-1] = NULL;
fprintf(stderr,
"PATHSUB: pattern [%s] not found in environment variable [%s].\n",
argv[firstarg], target);
exit(2);
}
}
/* Remove old entry FROM OUR COPY of environment block */
delete(mem_block, ppos);
/* Make new entry in OUR COPY of environment block. If the addition */
/* fits, THEN copy entire block back where it came from */
if(append(mem_block, cmdpath, ctrl_block.length*16))
{
movedata(ds, (unsigned)mem_block, _mem_seg, 0, ctrl_block.length*16);
exit(0);
}
/* if it did not get successfully added, just leave */
fprintf(stderr,
"PATHSUB: Not enough environment space -- environment unchanged\n");
exit(1);
}
/* ===================== String handling routines ========================= */
/* Purpose: this routine will substitute up to "num" occurances of the *
* pattern "pat" in the string "s" with the replacement "sub". *
* the actual number of substitutions performed is returned. *
* if "num" is -1, then all occurances of "pat" are changed. *
*/
int strsub(s, pat, sub, num)
char *s, *pat, *sub;
int num;
{
int idx, i, ii, count, off;
char news[161];
for( count = off = 0; TRUE; count++)
{
/* we only need to check string past end of last substitution */
idx = stridx(&s[off], pat);
/* if count is over the limit and limit specified,
or pattern not found */
if( ((count >= num) && (num != -1)) || (idx == -1))
return count+1;
/* idx + off is now the offset to the beginning of pat in s */
/* copy from up to pattern in string to local buffer */
for (i = off; i < idx+off; i++) /* only need to cp from last chg */
news[i] = s[i];
/* ad the substitution */
for (ii = 0; ii < strlen(sub); ii++)
news[i+ii] = sub[ii];
/* finish copying the rest of the string */
ii = idx+off + strlen(sub); /* where src picks up */
i = idx+off + strlen(pat); /* where need end on dest */
off = ii; /* remember for next cycle */
while(s[i])
news[ii++] = s[i++];
news[ii] = NULL;
strcpy(s, news);
}
return count; /* return number of subs done */
}
int stridx(s,p)
char *s,*p;
{
char *p2;
if( p2 = strstr(s,p)) /* if p found in s, */
return p2-s; /* return offset into s */
return -1; /* else return -1 */
}
unsigned _showds()
{
struct SREGS segregs;
segread(&segregs); /* read the segment registers */
return(segregs.ds); /* return DS */
}
int memsrch(mem,str,len)
char *mem, *str;
int len;
{
int i, j;
len -= strlen(str);
/* for each character of mem */
for( j = 0; j <= len; j++)
{
/* compare the following chars */
for( i = 0 ; (mem[j+i] == str[i]) && str[i]; i++);
if(!str[i]) /* if at end of string */
return j; /* return the index */
}
return -1;
}
delete(block, index)
char *block;
int index;
{
int size, end;
/* find end of environment (2nd of 2 NULLs in a row) */
for( end = 1; block[end-1] || block[end]; end++);
/* get length of entry being deleted */
size = strlen(&block[index])+1;
/* shift the remaining block down on top of string being deleted */
for(index += size; index <= end; index++)
block[index-size] = block[index];
}
append(block, string, maxlen)
char *block, *string;
unsigned int maxlen;
{
int end, size, i;
/* find starting point for string to be added */
for( end = 1; block[end-1] || block[end]; end++);
size = strlen(string) + 2; /* measure length of new string + 2 NULLs */
/* check to see where last (proposed) byte falls in block */
if((end+size) > maxlen)
return(FALSE);
/* copy it -- we have enough room */
for( i = 0; string[i]; block[end++] = string[i++]);
block[end++] = NULL;
block[end++] = NULL;
return TRUE;
}