home *** CD-ROM | disk | FTP | other *** search
/ minnie.tuhs.org / unixen.tar / unixen / PDP-11 / Trees / V7 / usr / src / cmd / ls.c < prev    next >
Encoding:
C/C++ Source or Header  |  1979-01-10  |  7.1 KB  |  426 lines

  1. /*
  2.  * list file or directory
  3.  */
  4.  
  5. #include <sys/param.h>
  6. #include <sys/stat.h>
  7. #include <sys/dir.h>
  8. #include <stdio.h>
  9.  
  10. #define    NFILES    1024
  11. FILE    *pwdf, *dirf;
  12. char    stdbuf[BUFSIZ];
  13.  
  14. struct lbuf {
  15.     union {
  16.         char    lname[15];
  17.         char    *namep;
  18.     } ln;
  19.     char    ltype;
  20.     short    lnum;
  21.     short    lflags;
  22.     short    lnl;
  23.     short    luid;
  24.     short    lgid;
  25.     long    lsize;
  26.     long    lmtime;
  27. };
  28.  
  29. int    aflg, dflg, lflg, sflg, tflg, uflg, iflg, fflg, gflg, cflg;
  30. int    rflg    = 1;
  31. long    year;
  32. int    flags;
  33. int    lastuid    = -1;
  34. char    tbuf[16];
  35. long    tblocks;
  36. int    statreq;
  37. struct    lbuf    *flist[NFILES];
  38. struct    lbuf    **lastp = flist;
  39. struct    lbuf    **firstp = flist;
  40. char    *dotp    = ".";
  41.  
  42. char    *makename();
  43. struct    lbuf *gstat();
  44. char    *ctime();
  45. long    nblock();
  46.  
  47. #define    ISARG    0100000
  48.  
  49. main(argc, argv)
  50. char *argv[];
  51. {
  52.     int i;
  53.     register struct lbuf *ep, **ep1;
  54.     register struct lbuf **slastp;
  55.     struct lbuf **epp;
  56.     struct lbuf lb;
  57.     char *t;
  58.     int compar();
  59.  
  60.     setbuf(stdout, stdbuf);
  61.     time(&lb.lmtime);
  62.     year = lb.lmtime - 6L*30L*24L*60L*60L; /* 6 months ago */
  63.     if (--argc > 0 && *argv[1] == '-') {
  64.         argv++;
  65.         while (*++*argv) switch (**argv) {
  66.  
  67.         case 'a':
  68.             aflg++;
  69.             continue;
  70.  
  71.         case 's':
  72.             sflg++;
  73.             statreq++;
  74.             continue;
  75.  
  76.         case 'd':
  77.             dflg++;
  78.             continue;
  79.  
  80.         case 'g':
  81.             gflg++;
  82.             continue;
  83.  
  84.         case 'l':
  85.             lflg++;
  86.             statreq++;
  87.             continue;
  88.  
  89.         case 'r':
  90.             rflg = -1;
  91.             continue;
  92.  
  93.         case 't':
  94.             tflg++;
  95.             statreq++;
  96.             continue;
  97.  
  98.         case 'u':
  99.             uflg++;
  100.             continue;
  101.  
  102.         case 'c':
  103.             cflg++;
  104.             continue;
  105.  
  106.         case 'i':
  107.             iflg++;
  108.             continue;
  109.  
  110.         case 'f':
  111.             fflg++;
  112.             continue;
  113.  
  114.         default:
  115.             continue;
  116.         }
  117.         argc--;
  118.     }
  119.     if (fflg) {
  120.         aflg++;
  121.         lflg = 0;
  122.         sflg = 0;
  123.         tflg = 0;
  124.         statreq = 0;
  125.     }
  126.     if(lflg) {
  127.         t = "/etc/passwd";
  128.         if(gflg)
  129.             t = "/etc/group";
  130.         pwdf = fopen(t, "r");
  131.     }
  132.     if (argc==0) {
  133.         argc++;
  134.         argv = &dotp - 1;
  135.     }
  136.     for (i=0; i < argc; i++) {
  137.         if ((ep = gstat(*++argv, 1))==NULL)
  138.             continue;
  139.         ep->ln.namep = *argv;
  140.         ep->lflags |= ISARG;
  141.     }
  142.     qsort(firstp, lastp - firstp, sizeof *lastp, compar);
  143.     slastp = lastp;
  144.     for (epp=firstp; epp<slastp; epp++) {
  145.         ep = *epp;
  146.         if (ep->ltype=='d' && dflg==0 || fflg) {
  147.             if (argc>1)
  148.                 printf("\n%s:\n", ep->ln.namep);
  149.             lastp = slastp;
  150.             readdir(ep->ln.namep);
  151.             if (fflg==0)
  152.                 qsort(slastp,lastp - slastp,sizeof *lastp,compar);
  153.             if (lflg || sflg)
  154.                 printf("total %D\n", tblocks);
  155.             for (ep1=slastp; ep1<lastp; ep1++)
  156.                 pentry(*ep1);
  157.         } else 
  158.             pentry(ep);
  159.     }
  160.     exit(0);
  161. }
  162.  
  163. pentry(ap)
  164. struct lbuf *ap;
  165. {
  166.     struct { char dminor, dmajor;};
  167.     register t;
  168.     register struct lbuf *p;
  169.     register char *cp;
  170.  
  171.     p = ap;
  172.     if (p->lnum == -1)
  173.         return;
  174.     if (iflg)
  175.         printf("%5u ", p->lnum);
  176.     if (sflg)
  177.     printf("%4D ", nblock(p->lsize));
  178.     if (lflg) {
  179.         putchar(p->ltype);
  180.         pmode(p->lflags);
  181.         printf("%2d ", p->lnl);
  182.         t = p->luid;
  183.         if(gflg)
  184.             t = p->lgid;
  185.         if (getname(t, tbuf)==0)
  186.             printf("%-6.6s", tbuf);
  187.         else
  188.             printf("%-6d", t);
  189.         if (p->ltype=='b' || p->ltype=='c')
  190.             printf("%3d,%3d", major((int)p->lsize), minor((int)p->lsize));
  191.         else
  192.             printf("%7ld", p->lsize);
  193.         cp = ctime(&p->lmtime);
  194.         if(p->lmtime < year)
  195.             printf(" %-7.7s %-4.4s ", cp+4, cp+20); else
  196.             printf(" %-12.12s ", cp+4);
  197.     }
  198.     if (p->lflags&ISARG)
  199.         printf("%s\n", p->ln.namep);
  200.     else
  201.         printf("%.14s\n", p->ln.lname);
  202. }
  203.  
  204. getname(uid, buf)
  205. int uid;
  206. char buf[];
  207. {
  208.     int j, c, n, i;
  209.  
  210.     if (uid==lastuid)
  211.         return(0);
  212.     if(pwdf == NULL)
  213.         return(-1);
  214.     rewind(pwdf);
  215.     lastuid = -1;
  216.     do {
  217.         i = 0;
  218.         j = 0;
  219.         n = 0;
  220.         while((c=fgetc(pwdf)) != '\n') {
  221.             if (c==EOF)
  222.                 return(-1);
  223.             if (c==':') {
  224.                 j++;
  225.                 c = '0';
  226.             }
  227.             if (j==0)
  228.                 buf[i++] = c;
  229.             if (j==2)
  230.                 n = n*10 + c - '0';
  231.         }
  232.     } while (n != uid);
  233.     buf[i++] = '\0';
  234.     lastuid = uid;
  235.     return(0);
  236. }
  237.  
  238. long
  239. nblock(size)
  240. long size;
  241. {
  242.     return((size+511)>>9);
  243. }
  244.  
  245. int    m1[] = { 1, S_IREAD>>0, 'r', '-' };
  246. int    m2[] = { 1, S_IWRITE>>0, 'w', '-' };
  247. int    m3[] = { 2, S_ISUID, 's', S_IEXEC>>0, 'x', '-' };
  248. int    m4[] = { 1, S_IREAD>>3, 'r', '-' };
  249. int    m5[] = { 1, S_IWRITE>>3, 'w', '-' };
  250. int    m6[] = { 2, S_ISGID, 's', S_IEXEC>>3, 'x', '-' };
  251. int    m7[] = { 1, S_IREAD>>6, 'r', '-' };
  252. int    m8[] = { 1, S_IWRITE>>6, 'w', '-' };
  253. int    m9[] = { 2, S_ISVTX, 't', S_IEXEC>>6, 'x', '-' };
  254.  
  255. int    *m[] = { m1, m2, m3, m4, m5, m6, m7, m8, m9};
  256.  
  257. pmode(aflag)
  258. {
  259.     register int **mp;
  260.  
  261.     flags = aflag;
  262.     for (mp = &m[0]; mp < &m[sizeof(m)/sizeof(m[0])];)
  263.         select(*mp++);
  264. }
  265.  
  266. select(pairp)
  267. register int *pairp;
  268. {
  269.     register int n;
  270.  
  271.     n = *pairp++;
  272.     while (--n>=0 && (flags&*pairp++)==0)
  273.         pairp++;
  274.     putchar(*pairp);
  275. }
  276.  
  277. char *
  278. makename(dir, file)
  279. char *dir, *file;
  280. {
  281.     static char dfile[100];
  282.     register char *dp, *fp;
  283.     register int i;
  284.  
  285.     dp = dfile;
  286.     fp = dir;
  287.     while (*fp)
  288.         *dp++ = *fp++;
  289.     *dp++ = '/';
  290.     fp = file;
  291.     for (i=0; i<DIRSIZ; i++)
  292.         *dp++ = *fp++;
  293.     *dp = 0;
  294.     return(dfile);
  295. }
  296.  
  297. readdir(dir)
  298. char *dir;
  299. {
  300.     static struct direct dentry;
  301.     register int j;
  302.     register struct lbuf *ep;
  303.  
  304.     if ((dirf = fopen(dir, "r")) == NULL) {
  305.         printf("%s unreadable\n", dir);
  306.         return;
  307.     }
  308.     tblocks = 0;
  309.     for(;;) {
  310.         if (fread((char *)&dentry, sizeof(dentry), 1, dirf) != 1)
  311.             break;
  312.         if (dentry.d_ino==0
  313.          || aflg==0 && dentry.d_name[0]=='.' &&  (dentry.d_name[1]=='\0'
  314.             || dentry.d_name[1]=='.' && dentry.d_name[2]=='\0'))
  315.             continue;
  316.         ep = gstat(makename(dir, dentry.d_name), 0);
  317.         if (ep==NULL)
  318.             continue;
  319.         if (ep->lnum != -1)
  320.             ep->lnum = dentry.d_ino;
  321.         for (j=0; j<DIRSIZ; j++)
  322.             ep->ln.lname[j] = dentry.d_name[j];
  323.     }
  324.     fclose(dirf);
  325. }
  326.  
  327. struct lbuf *
  328. gstat(file, argfl)
  329. char *file;
  330. {
  331.     extern char *malloc();
  332.     struct stat statb;
  333.     register struct lbuf *rep;
  334.     static int nomocore;
  335.  
  336.     if (nomocore)
  337.         return(NULL);
  338.     rep = (struct lbuf *)malloc(sizeof(struct lbuf));
  339.     if (rep==NULL) {
  340.         fprintf(stderr, "ls: out of memory\n");
  341.         nomocore = 1;
  342.         return(NULL);
  343.     }
  344.     if (lastp >= &flist[NFILES]) {
  345.         static int msg;
  346.         lastp--;
  347.         if (msg==0) {
  348.             fprintf(stderr, "ls: too many files\n");
  349.             msg++;
  350.         }
  351.     }
  352.     *lastp++ = rep;
  353.     rep->lflags = 0;
  354.     rep->lnum = 0;
  355.     rep->ltype = '-';
  356.     if (argfl || statreq) {
  357.         if (stat(file, &statb)<0) {
  358.             printf("%s not found\n", file);
  359.             statb.st_ino = -1;
  360.             statb.st_size = 0;
  361.             statb.st_mode = 0;
  362.             if (argfl) {
  363.                 lastp--;
  364.                 return(0);
  365.             }
  366.         }
  367.         rep->lnum = statb.st_ino;
  368.         rep->lsize = statb.st_size;
  369.         switch(statb.st_mode&S_IFMT) {
  370.  
  371.         case S_IFDIR:
  372.             rep->ltype = 'd';
  373.             break;
  374.  
  375.         case S_IFBLK:
  376.             rep->ltype = 'b';
  377.             rep->lsize = statb.st_rdev;
  378.             break;
  379.  
  380.         case S_IFCHR:
  381.             rep->ltype = 'c';
  382.             rep->lsize = statb.st_rdev;
  383.             break;
  384.         }
  385.         rep->lflags = statb.st_mode & ~S_IFMT;
  386.         rep->luid = statb.st_uid;
  387.         rep->lgid = statb.st_gid;
  388.         rep->lnl = statb.st_nlink;
  389.         if(uflg)
  390.             rep->lmtime = statb.st_atime;
  391.         else if (cflg)
  392.             rep->lmtime = statb.st_ctime;
  393.         else
  394.             rep->lmtime = statb.st_mtime;
  395.         tblocks += nblock(statb.st_size);
  396.     }
  397.     return(rep);
  398. }
  399.  
  400. compar(pp1, pp2)
  401. struct lbuf **pp1, **pp2;
  402. {
  403.     register struct lbuf *p1, *p2;
  404.  
  405.     p1 = *pp1;
  406.     p2 = *pp2;
  407.     if (dflg==0) {
  408.         if (p1->lflags&ISARG && p1->ltype=='d') {
  409.             if (!(p2->lflags&ISARG && p2->ltype=='d'))
  410.                 return(1);
  411.         } else {
  412.             if (p2->lflags&ISARG && p2->ltype=='d')
  413.                 return(-1);
  414.         }
  415.     }
  416.     if (tflg) {
  417.         if(p2->lmtime == p1->lmtime)
  418.             return(0);
  419.         if(p2->lmtime > p1->lmtime)
  420.             return(rflg);
  421.         return(-rflg);
  422.     }
  423.     return(rflg * strcmp(p1->lflags&ISARG? p1->ln.namep: p1->ln.lname,
  424.                 p2->lflags&ISARG? p2->ln.namep: p2->ln.lname));
  425. }
  426.