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+1023)>>10); 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: }