home *** CD-ROM | disk | FTP | other *** search
- /*-------------------------------------------------------------
-
- The namei program
-
- By: Roger S. Southwick
-
- May 2, 1990
-
- usage: namei pathname [pathname ... ]
-
- This program reads it's arguments as pathnames to any type
- of Unix file (symlinks, files, directories, and so forth).
- The program then follows each pathname until a terminal
- point is found (a file, directory, char device, etc).
- If it finds a symbolic link, we show the link, and start
- following it, indenting the output to show the context.
-
- This program is useful for finding a "too many levels of
- symbolic links" problems.
-
- For each line output, the program puts a file type first:
-
- f: = the pathname we are currently trying to resolve
- d = directory
- D = directory that is a mount point
- l = symbolic link (both the link and it's contents are output)
- s = socket
- b = block device
- c = character device
- - = regular file
- ? = an error of some kind
-
- The program prints an informative messages when we exceed
- the maximum number of symbolic links this system can have.
-
- The program exits with a 1 status ONLY if it finds it cannot
- chdir to /, or if it encounters an unknown file type.
-
- -------------------------------------------------------------*/
-
- #ifndef lint
- static char *RCSid = "$Id: namei.c,v 1.4 91/03/20 17:44:11 rogers Release_1 $";
- #endif
-
- #include <stdio.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <sys/param.h>
-
- extern char *sys_errlist[];
- extern int errno;
- #define ERR sys_errlist[errno],errno
-
- int symcount;
- int mflag = 0;
- int xflag = 0;
-
- main(argc, argv)
- int argc;
- char *argv[];
- {
- void namei(), usage();
- char *getwd();
- int getopt();
- extern int optind;
- register int c;
- char curdir[MAXPATHLEN];
-
- if(argc < 2)
- usage();
-
- while((c = getopt(argc, argv, "mx")) != EOF){
- switch(c){
- case 'm':
- mflag++;
- break;
-
- case 'x':
- xflag++;
- break;
-
- case '?':
- default:
- usage();
- }
- }
-
- if(getwd(curdir) == NULL){
- (void)fprintf(stderr, "namei: unable to get current directory - %s\n", curdir);
- exit(1);
- }
-
-
- for(; optind < argc; optind++){
- (void)printf("f: %s\n", argv[optind]);
- symcount = 1;
- namei(argv[optind], 0);
-
- if(chdir(curdir) == -1){
- (void)fprintf(stderr, "namei: unable to chdir to %s - %s (%d)\n", curdir, ERR);
- exit(1);
- }
- }
- exit(0);
- }
-
- void
- usage()
- {
- (void)fprintf(stderr,"usage: namei [-mx] pathname [pathname ...]\n");
- exit(1);
- }
-
- #ifndef NODEV
- #define NODEV (dev_t)(-1)
- #endif
-
- void
- namei(file, lev)
-
- register char *file;
- register int lev;
- {
- register char *cp;
- char buf[BUFSIZ], sym[BUFSIZ];
- struct stat stb;
- register int i;
- dev_t lastdev = NODEV;
-
- /*
- * See if the file has a leading /, and if so cd to root
- */
-
- if(*file == '/'){
- while(*file == '/')
- file++;
-
- if(chdir("/") == -1){
- (void)fprintf(stderr,"namei: could not chdir to root!\n");
- exit(1);
- }
- for(i = 0; i < lev; i++)
- (void)printf(" ");
-
- if(stat("/", &stb) == -1){
- (void)fprintf(stderr, "namei: could not stat root!\n");
- exit(1);
- }
- lastdev = stb.st_dev;
-
- if(mflag)
- (void)printf(" d %04o /\n", stb.st_mode & 07777);
- else
- (void)printf(" d /\n");
- }
-
- for(;;){
-
- /*
- * Copy up to the next / (or nil) into buf
- */
-
- for(cp = buf; *file != '\0' && *file != '/'; cp++, file++)
- *cp = *file;
-
- while(*file == '/') /* eat extra /'s */
- file++;
-
- *cp = '\0';
-
- if(buf[0] == '\0'){
-
- /*
- * Buf is empty, so therefore we are done
- * with this level of file
- */
-
- return;
- }
-
- for(i = 0; i < lev; i++)
- (void)printf(" ");
-
- /*
- * See what type of critter this file is
- */
-
- if(lstat(buf, &stb) == -1){
- (void)printf(" ? %s - %s (%d)\n", buf, ERR);
- return;
- }
-
- switch(stb.st_mode & S_IFMT){
- case S_IFDIR:
-
- /*
- * File is a directory, chdir to it
- */
-
- if(chdir(buf) == -1){
- (void)printf(" ? could not chdir into %s - %s (%d)\n", buf, ERR );
- return;
- }
- if(xflag && lastdev != stb.st_dev && lastdev != NODEV){
- /* Across mnt point */
- if(mflag)
- (void)printf(" D %04o %s\n", stb.st_mode & 07777, buf);
- else
- (void)printf(" D %s\n", buf);
- }
- else {
- if(mflag)
- (void)printf(" d %04o %s\n", stb.st_mode & 07777, buf);
- else
- (void)printf(" d %s\n", buf);
- }
- lastdev = stb.st_dev;
-
- (void)fflush(stdout);
- break;
-
- case S_IFLNK:
- /*
- * Sigh, another symlink. Read it's contents and
- * call namei()
- */
-
- bzero(sym, BUFSIZ);
- if(readlink(buf, sym, BUFSIZ) == -1){
- (void)printf(" ? problems reading symlink %s - %s (%d)\n", buf, ERR);
- return;
- }
-
- if(mflag)
- (void)printf(" l %04o %s -> %s", stb.st_mode & 07777, buf, sym);
- else
- (void)printf(" l %s -> %s", buf, sym);
-
- if(symcount > 0 && symcount++ > MAXSYMLINKS){
- (void)printf(" *** EXCEEDED UNIX LIMIT OF SYMLINKS ***");
- symcount = -1;
- }
- (void)printf("\n");
- namei(sym, lev + 1);
- break;
-
- case S_IFCHR:
- if(mflag)
- (void)printf(" c %04o %s\n", stb.st_mode & 07777, buf);
- else
- (void)printf(" c %s\n", buf);
- break;
-
- case S_IFBLK:
- if(mflag)
- (void)printf(" b %04o %s\n", stb.st_mode & 07777, buf);
- else
- (void)printf(" b %s\n", buf);
- break;
-
- case S_IFSOCK:
- if(mflag)
- (void)printf(" s %04o %s\n", stb.st_mode & 07777, buf);
- else
- (void)printf(" s %s\n", buf);
- break;
-
- case S_IFREG:
- if(mflag)
- (void)printf(" - %04o %s\n", stb.st_mode & 07777, buf);
- else
- (void)printf(" - %s\n", buf);
- break;
-
- default:
- (void)fprintf(stderr,"namei: unknown file type 0%06o on file %s\n", stb.st_mode, buf );
- exit(1);
-
- }
- }
- }
-
-