home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume24 / namei / namei.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-06-05  |  5.6 KB  |  283 lines

  1. /*-------------------------------------------------------------
  2.  
  3. The namei program
  4.  
  5. By: Roger S. Southwick
  6.  
  7. May 2, 1990
  8.  
  9. usage: namei pathname [pathname ... ]
  10.  
  11. This program reads it's arguments as pathnames to any type
  12. of Unix file (symlinks, files, directories, and so forth). 
  13. The program then follows each pathname until a terminal 
  14. point is found (a file, directory, char device, etc).
  15. If it finds a symbolic link, we show the link, and start
  16. following it, indenting the output to show the context.
  17.  
  18. This program is useful for finding a "too many levels of
  19. symbolic links" problems.
  20.  
  21. For each line output, the program puts a file type first:
  22.  
  23.    f: = the pathname we are currently trying to resolve
  24.     d = directory
  25.     D = directory that is a mount point
  26.     l = symbolic link (both the link and it's contents are output)
  27.     s = socket
  28.     b = block device
  29.     c = character device
  30.     - = regular file
  31.     ? = an error of some kind
  32.  
  33. The program prints an informative messages when we exceed
  34. the maximum number of symbolic links this system can have.
  35.  
  36. The program exits with a 1 status ONLY if it finds it cannot
  37. chdir to /,  or if it encounters an unknown file type.
  38.  
  39. -------------------------------------------------------------*/
  40.  
  41. #ifndef lint
  42. static char *RCSid = "$Id: namei.c,v 1.4 91/03/20 17:44:11 rogers Release_1 $";
  43. #endif
  44.  
  45. #include <stdio.h>
  46. #include <sys/types.h>
  47. #include <sys/stat.h>
  48. #include <sys/param.h>
  49.  
  50. extern char *sys_errlist[];
  51. extern int errno;
  52. #define ERR    sys_errlist[errno],errno
  53.  
  54. int symcount;
  55. int mflag = 0;
  56. int xflag = 0;
  57.  
  58. main(argc, argv)
  59. int argc;
  60. char *argv[];
  61. {
  62.     void namei(), usage();
  63.     char *getwd();
  64.     int getopt();
  65.     extern int optind;
  66.     register int c;
  67.     char curdir[MAXPATHLEN];
  68.  
  69.     if(argc < 2)
  70.     usage();
  71.  
  72.     while((c = getopt(argc, argv, "mx")) != EOF){
  73.     switch(c){
  74.         case 'm':
  75.         mflag++;
  76.         break;
  77.         
  78.         case 'x':
  79.         xflag++;
  80.         break;
  81.  
  82.         case '?':
  83.         default:
  84.         usage();
  85.     }
  86.     }
  87.  
  88.     if(getwd(curdir) == NULL){
  89.     (void)fprintf(stderr, "namei: unable to get current directory - %s\n", curdir);
  90.     exit(1);
  91.     }
  92.  
  93.  
  94.     for(; optind < argc; optind++){
  95.     (void)printf("f: %s\n", argv[optind]);
  96.     symcount = 1;
  97.     namei(argv[optind], 0);
  98.  
  99.     if(chdir(curdir) == -1){
  100.         (void)fprintf(stderr, "namei: unable to chdir to %s - %s (%d)\n", curdir, ERR);
  101.         exit(1);
  102.     }
  103.     }
  104.     exit(0);
  105. }
  106.  
  107. void
  108. usage()
  109. {
  110.     (void)fprintf(stderr,"usage: namei [-mx] pathname [pathname ...]\n");
  111.     exit(1);
  112. }
  113.  
  114. #ifndef NODEV
  115. #define NODEV        (dev_t)(-1)
  116. #endif
  117.  
  118. void
  119. namei(file, lev)
  120.  
  121. register char *file;
  122. register int lev;
  123. {
  124.     register char *cp;
  125.     char buf[BUFSIZ], sym[BUFSIZ];
  126.     struct stat stb;
  127.     register int i;
  128.     dev_t lastdev = NODEV;
  129.  
  130.     /*
  131.      * See if the file has a leading /, and if so cd to root
  132.      */
  133.     
  134.     if(*file == '/'){
  135.     while(*file == '/')
  136.         file++;
  137.     
  138.     if(chdir("/") == -1){
  139.         (void)fprintf(stderr,"namei: could not chdir to root!\n");
  140.         exit(1);
  141.     }
  142.     for(i = 0; i < lev; i++)
  143.         (void)printf("  ");
  144.  
  145.     if(stat("/", &stb) == -1){
  146.         (void)fprintf(stderr, "namei: could not stat root!\n");
  147.         exit(1);
  148.     }
  149.     lastdev = stb.st_dev;
  150.  
  151.     if(mflag)
  152.         (void)printf(" d %04o /\n", stb.st_mode & 07777);
  153.     else
  154.         (void)printf(" d /\n");
  155.     }
  156.  
  157.     for(;;){
  158.  
  159.     /*
  160.      * Copy up to the next / (or nil) into buf
  161.      */
  162.     
  163.     for(cp = buf; *file != '\0' && *file != '/'; cp++, file++)
  164.         *cp = *file;
  165.     
  166.     while(*file == '/')    /* eat extra /'s    */
  167.         file++;
  168.  
  169.     *cp = '\0';
  170.  
  171.     if(buf[0] == '\0'){
  172.  
  173.         /*
  174.          * Buf is empty, so therefore we are done
  175.          * with this level of file
  176.          */
  177.  
  178.         return;
  179.     }
  180.  
  181.     for(i = 0; i < lev; i++)
  182.         (void)printf("  ");
  183.  
  184.     /*
  185.      * See what type of critter this file is
  186.      */
  187.     
  188.     if(lstat(buf, &stb) == -1){
  189.         (void)printf(" ? %s - %s (%d)\n", buf, ERR);
  190.         return;
  191.     }
  192.  
  193.     switch(stb.st_mode & S_IFMT){
  194.         case S_IFDIR:
  195.  
  196.         /*
  197.          * File is a directory, chdir to it
  198.          */
  199.         
  200.         if(chdir(buf) == -1){
  201.             (void)printf(" ? could not chdir into %s - %s (%d)\n", buf, ERR );
  202.             return;
  203.         }
  204.         if(xflag && lastdev != stb.st_dev && lastdev != NODEV){
  205.             /* Across mnt point */
  206.             if(mflag)
  207.             (void)printf(" D %04o %s\n", stb.st_mode & 07777, buf);
  208.             else
  209.             (void)printf(" D %s\n", buf);
  210.         }
  211.         else {
  212.             if(mflag)
  213.             (void)printf(" d %04o %s\n", stb.st_mode & 07777, buf);
  214.             else
  215.             (void)printf(" d %s\n", buf);
  216.         }
  217.         lastdev = stb.st_dev;
  218.  
  219.         (void)fflush(stdout);
  220.         break;
  221.  
  222.         case S_IFLNK:
  223.         /*
  224.          * Sigh, another symlink.  Read it's contents and
  225.          * call namei()
  226.          */
  227.         
  228.         bzero(sym, BUFSIZ);
  229.         if(readlink(buf, sym, BUFSIZ) == -1){
  230.             (void)printf(" ? problems reading symlink %s - %s (%d)\n", buf, ERR);
  231.             return;
  232.         }
  233.  
  234.         if(mflag)
  235.             (void)printf(" l %04o %s -> %s", stb.st_mode & 07777, buf, sym);
  236.         else
  237.             (void)printf(" l %s -> %s", buf, sym);
  238.  
  239.         if(symcount > 0 && symcount++ > MAXSYMLINKS){
  240.             (void)printf("  *** EXCEEDED UNIX LIMIT OF SYMLINKS ***");
  241.             symcount = -1;
  242.         }
  243.         (void)printf("\n");
  244.         namei(sym, lev + 1);
  245.         break;
  246.  
  247.         case S_IFCHR:
  248.         if(mflag)
  249.             (void)printf(" c %04o %s\n", stb.st_mode & 07777, buf);
  250.         else
  251.             (void)printf(" c %s\n", buf);
  252.         break;
  253.         
  254.         case S_IFBLK:
  255.         if(mflag)
  256.             (void)printf(" b %04o %s\n", stb.st_mode & 07777, buf);
  257.         else
  258.             (void)printf(" b %s\n", buf);
  259.         break;
  260.         
  261.         case S_IFSOCK:
  262.         if(mflag)
  263.             (void)printf(" s %04o %s\n", stb.st_mode & 07777, buf);
  264.         else
  265.             (void)printf(" s %s\n", buf);
  266.         break;
  267.  
  268.         case S_IFREG:
  269.         if(mflag)
  270.             (void)printf(" - %04o %s\n", stb.st_mode & 07777, buf);
  271.         else
  272.             (void)printf(" - %s\n", buf);
  273.         break;
  274.         
  275.         default:
  276.         (void)fprintf(stderr,"namei: unknown file type 0%06o on file %s\n", stb.st_mode, buf );
  277.         exit(1);
  278.         
  279.     }
  280.     }
  281. }
  282.  
  283.