Path: utzoo!attcan!utgpu!jarvis.csri.toronto.edu!rutgers!apple!bloom-beacon!tut.cis.ohio-state.edu!ucbvax!agate!eris.berkeley.edu!mwm From: mwm@eris.berkeley.edu (Mike (I'll think of something yet) Meyer) Newsgroups: comp.sys.amiga.tech Subject: Re: What is my name? Message-ID: <26564@agate.BERKELEY.EDU> Date: 21 Jul 89 11:08:45 GMT References: <26385@agate.BERKELEY.EDU> <20565@cup.portal.com> <1227@atanasoff.cs.iastate.edu> <432@xdos.UUCP> <7372@cbmvax.UUCP> <433@xdos.UUCP> <26555@agate.BERKELEY.EDU> Sender: usenet@agate.BERKELEY.EDU Reply-To: mwm@eris.berkeley.edu (Mike (I'll think of something yet) Meyer) Organization: Missionaria Phonibalonica Lines: 152 Having seen everyone's examples, I finally sat down and wrote my own. For my uses, I needed a subroutine that handed back a "canonical" form - i.e., one that gave me the same name every time, no matter how invoked. Two things made this happen. One was taking the device part of any absolute names to a lock, then using getpath() from the Lattice library (this is basically just Lock2Path, as written by Doug) to turn it back into a path. Thus, all path names come out with assigns, etc. mapped out. The other step is to take any part of the file name not handed back by getpath, and deal with occurences of "//" in the name. There's one other Lattice library function here, findpath(). It walks the path of a cli, and returns a lock on the first directory that contains a file (subdirectory path) with the name of it's argument file (subdirectory path). This is pretty trivial to derive from which.c. Since I was using those routines, I went ahead and wrote my preferred function headers - ANSI prototype style. Those of you with Lattice 5. or later should be able to just compile this. -L -dTEST to get a binary that reports it's name in canonical form, sans those to get a .o file with a "which" routine that will pass back that name. Those of you with Manx will have to change it. #include #include #include #include #include static int myname(char *, char *) ; #ifdef TEST void main(argc, argv) char **argv; { char pathbuf[FMSIZE] ; if (!which(argv[0], pathbuf)) puts("Can't find path") ; else puts(pathbuf) ; } #endif which(char *myname, char *pathbuf) { char *ip ; BPTR lock ; int status ; if (*myname != ':' && (ip = strchr(myname, ':')) != NULL) { /* * Absolute path, so just canonicalize that. This means we * need to get a lock on the dev: file, and change myname * to point at the rest of it. */ ip = '\0' ; lock = Lock(myname, ACCESS_READ) ; myname = ip + 1 ; } else { /* * Get a lock on the directory we're from, if we're in * a directory on the path. * N.B.: findpath returns a lock on the current directory * if we feed it an absolute path name. Strange, but true. */ lock = findpath(myname) ; if (lock == -1) { /* * Not on the path, so see if we're in C: */ sprintf(pathbuf, "c:%s", myname) ; if (getfa(pathbuf) != -1) return 0 ; /* * It exists in C:. So get a lock on C:, so get a lock * on the c: directory for later use. */ lock = Lock("c:", ACCESS_READ) ; if (lock == -1) return 0 ; } } /* * At this point, lock is a lock on the directory that we were * run from (well, one hopes that, anyway). So we turn that * into a path name, then combine the two correctly. */ status = getpath(lock, pathbuf) ; UnLock(lock) ; if (status) return 0 ; /* * We now have a directory name known to be in canonical form, * and the name of a file that isn't canonical, but can be found * in that directory. So we canonicalize the catenation of the two. * * Step one: deal with ":". Note that getpath has the noxious habit * of returning "dev", instead of the more proper "dev:". This leaves * four cases: * * *myname : ? * * status * true add ':' to pathbuf add ':' to pathbuf * false ip = strchr(pathbuf, ':') add '/' to pathbuf * * both above need myname += 1 * * "add x to pathbuf" means ip = memchr(pathbuf, '\0', FMSIZE) * and *ip = x */ status = (ip = strchr(pathbuf, ':')) == NULL ; if (*myname == ':' && !status) myname += 1 ; else { ip = strchr(pathbuf, '\0') ; *ip = status ? ':' : '/' ; if (*myname == ':') myname += 1 ; } /* * Step two: Deal with "//" in the non-canonical path. Since * pathbuf now holds a valid "dev:" string plus some canonical * path from it, and myname a path from that directory down, that's * all we have to worry about. Actually, we ought to put in a check * for *myname == '/' && *ip == ':' (meaning we're trying to back up * over the device), but that should never happen. */ for (;*myname; myname += 1) if (*myname == '/' && *ip == '/') /* double '/', get rid of one of them! */ while (*--ip != '/' && *ip != ':') ; else *++ip = *myname ; return 1 ; } -- Il brilgue: les toves lubricilleux Mike Meyer Se gyrent en vrillant dans le guave, mwm@berkeley.edu Enmimes sont les gougebosqueux, ucbvax!mwm Et le momerade horsgrave. mwm@ucbjade.BITNET