jmsellens@watrose.UUCP (John M Sellens) (04/07/84)
X - bug killer
These routines are used by 'Find' and 'Make' (see adjacent
articles. Hope they're useful. - John
----------------------------------------------------------
/* The following are two routines to make it easier to access the
PATH environment variable. They are written for use with the
DeSmet C Compiler. Known portability problems:
- assembler code embedded in the C code
- requires that code segment register (CS) be set to the
same value as at program invocation so that the
program segment prefix can be located. This would
probably only be a problem if a "large model"
compiler is used.
The code is a little kludgy in places but...
Any suggestions for improvements gratefully accepted.
*/
/*
Written by John M Sellens, April, 1984
Code is all original except where indicated otherwise.
Until August, 1984:
jmsellens@watrose.UUCP
107 - 180 Brybeck Cres.
Kitchener, Ontario
N2M 5G4
After August, 1984:
c/o 1135 Lansdowne Ave. SW
Calgary, Alberta
T2S 1A4
(c) Copyright 1984 John M Sellens
Permission is granted to use, distribute and/or modify this code unless
done for direct commercial profit. If you find these routines useful,
modest contributions (monetary or otherwise) will be gratefully accepted.
Author's name, address and this notice must be included in any copies.
*/
#include <stdio.h>
typedef char *char_ptr;
main()
{
/* Example of how to use parse_path() and get_path() */
int i;
char *get_path();
char_ptr *paths, *parse_path();
paths = parse_path(get_path());
if (paths != NULL)
for (i=0; paths[i]!=NULL; i++)
printf("%s\n",paths[i]);
else
printf("No path is set\n");
}
char_ptr *parse_path(ps)
char *ps;
{
/* Takes the path string returned by get_path and destroys it,
by inserting NULL's and returning an array of pointers to
characters that point to locations in the original path
string. The pointer after the last pointer into the path
string is NULL. If the path string is NULL, then NULL is
returned.
*/
int i, j, num;
char_ptr *pa;
if (ps[0] == '\0') /* no path */
return(NULL);
/* count the number of semi-colons, add 1 = number of paths */
for (num=1, i=0; ps[i] != '\0'; i++)
if (ps[i] == ';')
num++;
pa = (char_ptr *)malloc(sizeof(char_ptr) * (num+1));
pa[num] = NULL;
/* now loop through and point to each path */
for (i=j=0; i<num; i++) {
pa[i] = &ps[j];
while(ps[j]!=';' && ps[j]!='\0')
j++;
ps[j++] = '\0';
}
return(pa);
}
char *get_path()
{
/* Returns a pointer to a string containing the value of
the environment variable PATH. E.g. if PATH=A:\;B:\
the string "A:\;B:\" is returned. If no PATH is set,
an empty string is returned.
*/
static int path_seg;
/* these three declarations must be first so that they can be
referred to by stack address near the end when copying
the PATH variable */
char *base, *path;
int siz;
char *next;
char env_str[10]; /* leave a little extra space just in case */
int i, done;
#asm
; determine the segment that the environment starts at
; this requires that cs is set to the same value as at
; program entry i.e. 100H past the program segment prefix
push es
mov ax,cs
sbb ax,10h
mov es,ax
mov ax,es:[2cH]
pop es
mov word get_path_path_seg_,ax
#
/* look for the start of PATH= */
/* there's always going to be at least one thing in environment */
done = FALSE;
next = 0;
env_str[0] = '\0';
while ((strncmp("PATH=",env_str,5) != 0) && !done) {
base = next;
/* set DS to path_seg */
#asm
push ds
mov ds,word get_path_path_seg_
#
if (base[0] == '\0')
done = TRUE; /* no more variables to look at */
else {
/* now copy 5 characters into memory */
for (i=0; i<5; i++)
env_str[i] = base[i]; /* ok since env_str is on stack */
/* now set next to first character after end of this string */
while ((next++)[0] != '\0')
;
}
/* reset DS */
#asm
pop ds
#
}
if (done) { /* no PATH environment variable set */
path = (char *)malloc(1);
path[0] = '\0';
} else {
siz = next - base - 5;
path = (char *)malloc(siz);
base += 5; /* skip over 'PATH=' */
/* copy the PATH string to path */
#asm
push cx
push es
push ds
mov cx,ds
mov es,cx
mov ds,word get_path_path_seg_
mov si,word [bp-2] ;base
mov di,word [bp-4] ;path
mov cx,word [bp-6] ;siz
rep movsb
pop ds
pop es
pop cx
#
}
return(path);
}