Path: utzoo!attcan!uunet!husc6!umb!ileaf!io!md From: md@io.UUCP (Mark Dionne) Newsgroups: comp.unix.wizards Subject: Re: Finding where an executable was run Summary: I was wrong Message-ID: <612@io.UUCP> Date: 21 May 88 05:13:27 GMT References: <4527@hoptoad.uucp> <-63169371@sneaky> <611@io.UUCP> <53991@sun.uucp> Reply-To: md@marvin.UUCP (Mark Dionne) Organization: Interleaf, Cambridge, MA Lines: 113 I previously wrote: > I believe system V is different from BSD: argv[0] is always > the full path name of the executable. As several people have pointed out, I was either wrong or overgeneralizing. Sorry. I based this belief on what I was told when a "get_exec_name" routine we wrote was ported (by others) to AIX on an IBM RT. I don't have access to an RT right now, so I can't verify it. Here's a routine for finding the pathname of an executable. It might not be perfect, but it illustrates a couple of twists: watch out for directories, and watch out for "." and ".." #include #include #include #define PATHSIZE 256 GetExecName(argv0, buf) char* argv0; char* buf; /* pathname returnes in this buffer */ { char *path; char *getenv(), *getwd(), *getPathElement(); if (*argv0 == '/') { strcpy( buf, argv0 ); return(0); } if (*argv0 == '.' && *(argv0+1) == '/') { strcpy(buf, argv0 + 2); goto found; } if (*argv0 == '.' && *(argv0+1) == '.' && *(argv0+2) == '/' ) { strcpy(buf, argv0); goto found; } path = getenv("PATH"); while(path != 0) { path = getPathElement(path, buf); if (*buf == '\0') continue; /* ignore empty components (::) */ strcat(buf, "/"); strcat(buf, argv0); if (access(buf, X_OK) == 0) { /* watch out for directories that happen to match */ if((get_file_mode(buf) & S_IFMT) == S_IFDIR) continue; /* Got it. Now if it is not absolute, just prepend cwd */ if (*buf != '/') { char tmpbuf[PATHSIZE]; found: strcpy(tmpbuf, buf); if ( getwd(buf) == 0 ) break; strcat(buf, "/"); strcat( buf, tmpbuf ); } return(0); } } /* Not found */ *buf = 0; return(-1); } long get_file_mode( path) char* path; { struct stat stats; if ( stat( path, &stats) < 0 ) return ( -1 ); return ( stats.st_mode ); } /* Strip off first element of path into buf. Returns new path. */ char *getPathElement( path, buf ) register char *path; register char *buf; { while ( (*buf = *path++) != '\0' ) { if (*buf == ':') { *buf = '\0'; return(path); } ++buf; } return(0); } #include main(argc, argv, envp) int argc; char **argv; char **envp; { char buf[PATHSIZE]; printf("Argv[0] : %s\n", argv[0]); printf("Return value: %d\n", GetExecName(argv[0], buf)); printf("Exec name: %s\n", buf); } -- ...!mit-eddie!ileaf!md Mark Dionne, Interleaf ...!sun!sunne!ileaf!md Ten Canal Park, Cambridge, MA 02141 (617) 577-9813 x5551