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