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