[net.micro.pc] PATH Environment variable finder for IBM PC

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);
}