|
|
1.1 ! root 1: /* ! 2: * ls ! 3: */ ! 4: ! 5: #include <sys/param.h> ! 6: #include <sys/stat.h> ! 7: #include <ndir.h> ! 8: #include <stdio.h> ! 9: #include <pwd.h> ! 10: #include <grp.h> ! 11: ! 12: #define NUID 500 ! 13: #define NGID 50 ! 14: #define NMAX 8 ! 15: ! 16: struct id { ! 17: int id; ! 18: char name[NMAX+1]; ! 19: }; ! 20: ! 21: struct id *names, *lastname; ! 22: struct id *groups, *lastgroup; ! 23: ! 24: #define kbytes(size) ((size + 1023) / 1024) ! 25: ! 26: struct afile { ! 27: char ftype; /* file type, e.g. 'd', 'c', 'f' */ ! 28: char flink; /* 'L' for symlinks, ' ' otherwise */ ! 29: ino_t fnum; /* inode number of file */ ! 30: short fflags; /* mode&~S_IFMT, perhaps ISARG */ ! 31: short fnl; /* number of links */ ! 32: short fuid; /* owner id */ ! 33: short fgid; /* group id */ ! 34: long fsize; /* file size */ ! 35: time_t fmtime; /* time (modify or access or create) */ ! 36: char *fname; /* file name */ ! 37: char *flinkto; /* symbolic link value */ ! 38: }; ! 39: ! 40: #define ISARG 0x8000 /* extra ``mode'' */ ! 41: ! 42: struct subdirs { ! 43: char *sd_name; ! 44: struct subdirs *sd_next; ! 45: } *subdirs; ! 46: ! 47: int aflg, dflg, lflg, sflg, tflg, uflg, iflg, fflg, cflg, rflg = 1; ! 48: int Fflg, Lflg, Rflg; ! 49: ! 50: time_t now, sixmonthsago; ! 51: ! 52: char *dotp = "."; ! 53: ! 54: struct afile *gstat(); ! 55: int fcmp(); ! 56: char *cat(), *savestr(); ! 57: char *fmtentry(); ! 58: char *getname(), *getgroup(); ! 59: ! 60: char *ctime(); ! 61: char *malloc(), *realloc(); ! 62: char *strcpy(), *strcat(); ! 63: ! 64: main(argc, argv) ! 65: int argc; ! 66: char *argv[]; ! 67: { ! 68: int i; ! 69: struct afile *fp0, *fplast; ! 70: register struct afile *fp; ! 71: char ebuf[BUFSIZ]; ! 72: char obuf[BUFSIZ]; ! 73: ! 74: setbuf(stderr, ebuf); ! 75: setbuf(stdout, obuf); ! 76: argc--, argv++; ! 77: (void) time(&now); sixmonthsago = now - 6L*30L*24L*60L*60L; now += 60; ! 78: while (argc > 0 && **argv == '-') { ! 79: (*argv)++; ! 80: lsacct(*argv); ! 81: while (**argv) switch (*(*argv)++) { ! 82: ! 83: case 'a': ! 84: aflg++; break; ! 85: case 'c': ! 86: cflg++; break; ! 87: case 's': ! 88: sflg++; break; ! 89: case 'd': ! 90: dflg++; break; ! 91: case 'l': ! 92: lflg++; break; ! 93: case 'r': ! 94: rflg = -1; break; ! 95: case 't': ! 96: tflg++; break; ! 97: case 'u': ! 98: uflg++; break; ! 99: case 'i': ! 100: iflg++; break; ! 101: case 'f': ! 102: fflg++; break; ! 103: case 'L': ! 104: Lflg++; break; ! 105: case 'F': ! 106: Fflg++; break; ! 107: case 'R': ! 108: Rflg++; break; ! 109: } ! 110: argc--, argv++; ! 111: } ! 112: if (fflg) { ! 113: aflg++; lflg = 0; sflg = 0; tflg = 0; ! 114: } ! 115: if (argc == 0) { ! 116: argc++; ! 117: argv = &dotp; ! 118: } ! 119: fp = (struct afile *)malloc(argc * sizeof (struct afile)); ! 120: if (fp == 0) { ! 121: dprintf("ls: out of memory\n"); ! 122: exit(1); ! 123: } ! 124: fp0 = fp; ! 125: for (i = 0; i < argc; i++) { ! 126: if (gstat(fp, *argv, 1)) { ! 127: fp->fname = *argv; ! 128: fp->fflags |= ISARG; ! 129: fp++; ! 130: } ! 131: argv++; ! 132: } ! 133: fplast = fp; ! 134: qsort((char *)fp0, fplast - fp0, sizeof (struct afile), fcmp); ! 135: for (fp = fp0; fp < fplast; fp++) { ! 136: if ((fflg == 0) && (dflg || fp->ftype != 'd')) { ! 137: printf("%s\n", fmtentry(fp)); ! 138: continue; ! 139: } ! 140: formatd(fp->fname, argc > 1); ! 141: while (subdirs) { ! 142: struct subdirs *t; ! 143: ! 144: t = subdirs; ! 145: subdirs = t->sd_next; ! 146: formatd(t->sd_name, 1); ! 147: cfree(t->sd_name); ! 148: cfree((char *)t); ! 149: } ! 150: } ! 151: exit(0); ! 152: } ! 153: ! 154: formatd(name, title) ! 155: char *name; ! 156: int title; ! 157: { ! 158: register struct afile *fp; ! 159: register struct subdirs *dp; ! 160: struct afile *dfp0, *dfplast; ! 161: ! 162: getdir(name, &dfp0, &dfplast); ! 163: if (dfp0 == 0) ! 164: return; ! 165: if (fflg == 0) ! 166: qsort((char *)dfp0, dfplast - dfp0, sizeof (struct afile), fcmp); ! 167: if (title) ! 168: printf("%s:\n", name); ! 169: for (fp = dfp0; fp < dfplast; fp++) ! 170: printf("%s\n", fmtentry(fp)); ! 171: if (Rflg) ! 172: for (fp = dfplast-1; fp >= dfp0; fp--) { ! 173: if (fp->ftype != 'd' || ! 174: (fp->flink=='L' && (fp->fflags&ISARG)==0) || ! 175: !strcmp(fp->fname, ".") || ! 176: !strcmp(fp->fname, "..")) ! 177: continue; ! 178: dp = (struct subdirs *)malloc(sizeof (struct subdirs)); ! 179: dp->sd_name = savestr(cat(name, fp->fname)); ! 180: dp->sd_next = subdirs; subdirs = dp; ! 181: } ! 182: for (fp = dfp0; fp < dfplast; fp++) { ! 183: if ((fp->fflags&ISARG) == 0 && fp->fname) ! 184: free(fp->fname); ! 185: if (fp->flinkto) ! 186: free(fp->flinkto); ! 187: } ! 188: free((char *)dfp0); ! 189: } ! 190: ! 191: getdir(dir, pfp0, pfplast) ! 192: char *dir; ! 193: struct afile **pfp0, **pfplast; ! 194: { ! 195: register struct afile *fp; ! 196: DIR *dirp; ! 197: register struct direct *dp; ! 198: int nent = 20; ! 199: ! 200: dirp = opendir(dir); ! 201: if (dirp == NULL) { ! 202: *pfp0 = *pfplast = NULL; ! 203: printf("%s unreadable\n", dir); /* not stderr! */ ! 204: return; ! 205: } ! 206: fp = *pfp0 = (struct afile *)malloc(nent * sizeof (struct afile)); ! 207: *pfplast = *pfp0 + nent; ! 208: while (dp = readdir(dirp)) { ! 209: if (dp->d_ino == 0) ! 210: continue; ! 211: if (aflg == 0 && dp->d_name[0]=='.' && ! 212: (dp->d_name[1]==0 || dp->d_name[1]=='.' && dp->d_name[2]==0)) ! 213: continue; ! 214: if (gstat(fp, cat(dir, dp->d_name), 0) == 0) ! 215: continue; ! 216: fp->fnum = dp->d_ino; ! 217: fp->fname = savestr(dp->d_name); ! 218: fp++; ! 219: if (fp == *pfplast) { ! 220: *pfp0 = (struct afile *)realloc((char *)*pfp0, ! 221: 2 * nent * sizeof (struct afile)); ! 222: if (*pfp0 == 0) { ! 223: dprintf("ls: out of memory\n"); ! 224: exit(1); ! 225: } ! 226: fp = *pfp0 + nent; ! 227: *pfplast = fp + nent; ! 228: nent *= 2; ! 229: } ! 230: } ! 231: closedir(dirp); ! 232: *pfplast = fp; ! 233: } ! 234: ! 235: int stat(), lstat(); ! 236: ! 237: struct afile * ! 238: gstat(fp, file, statarg) ! 239: register struct afile *fp; ! 240: char *file; ! 241: int statarg; ! 242: { ! 243: char buf[BUFSIZ]; int cc; ! 244: static struct afile azerofile = { 0, ' ' }; ! 245: static struct afile azerolink = { 0, 'L' }; ! 246: ! 247: *fp = azerofile; ! 248: fp->fflags = 0; ! 249: fp->fnum = 0; ! 250: fp->ftype = '-'; ! 251: if (statarg || sflg || lflg || tflg || Fflg || Rflg) { ! 252: struct stat stb; ! 253: ! 254: if (lstat(file, &stb) < 0) { ! 255: if (statarg) { ! 256: dprintf("%s not found\n", file); ! 257: return (0); ! 258: } ! 259: return (&azerofile); ! 260: } ! 261: fp->flink = ' '; ! 262: if (Lflg==0 && (stb.st_mode&S_IFMT)==S_IFLNK) { ! 263: fp->flink = 'L'; ! 264: if (stat(file, &stb) < 0) ! 265: return (&azerolink); ! 266: } ! 267: fp->fsize = stb.st_size; ! 268: switch (stb.st_mode & S_IFMT) { ! 269: ! 270: case S_IFDIR: ! 271: fp->ftype = 'd'; break; ! 272: case S_IFBLK: ! 273: fp->ftype = 'b'; fp->fsize = stb.st_rdev; break; ! 274: case S_IFCHR: ! 275: fp->ftype = 'c'; fp->fsize = stb.st_rdev; break; ! 276: case S_IFLNK: ! 277: fp->ftype = 'l'; ! 278: if (lflg) { ! 279: cc = readlink(file, buf, BUFSIZ); ! 280: if (cc >= 0) { ! 281: buf[cc] = 0; ! 282: fp->flinkto = savestr(buf); ! 283: } ! 284: } ! 285: break; ! 286: } ! 287: fp->fnum = stb.st_ino; ! 288: fp->fflags = stb.st_mode & ~S_IFMT; ! 289: fp->fnl = stb.st_nlink; ! 290: fp->fuid = stb.st_uid; ! 291: fp->fgid = stb.st_gid; ! 292: if (uflg) ! 293: fp->fmtime = stb.st_atime; ! 294: else if (cflg) ! 295: fp->fmtime = stb.st_ctime; ! 296: else ! 297: fp->fmtime = stb.st_mtime; ! 298: } ! 299: return (fp); ! 300: } ! 301: ! 302: fcmp(cf1, cf2) ! 303: char *cf1, *cf2; ! 304: { ! 305: register struct afile *f1, *f2; ! 306: ! 307: f1 = (struct afile *)cf1; ! 308: f2 = (struct afile *)cf2; ! 309: if (dflg == 0 && fflg == 0) { ! 310: if ((f1->fflags&ISARG) && f1->ftype == 'd') { ! 311: if ((f2->fflags&ISARG) == 0 || f2->ftype != 'd') ! 312: return (1); ! 313: } else { ! 314: if ((f2->fflags&ISARG) && f2->ftype == 'd') ! 315: return (-1); ! 316: } ! 317: } ! 318: if (tflg) { ! 319: if (f2->fmtime == f1->fmtime) ! 320: return (0); ! 321: if (f2->fmtime > f1->fmtime) ! 322: return (rflg); ! 323: return (-rflg); ! 324: } ! 325: return (rflg * strcmp(f1->fname, f2->fname)); ! 326: } ! 327: ! 328: char * ! 329: cat(dir, file) ! 330: char *dir, *file; ! 331: { ! 332: static char dfile[BUFSIZ]; ! 333: ! 334: if (strlen(dir)+1+strlen(file)+1 > BUFSIZ) { ! 335: dprintf("ls: filename too long\n"); ! 336: exit(1); ! 337: } ! 338: if (!strcmp(dir, "") || !strcmp(dir, ".")) { ! 339: (void) strcpy(dfile, file); ! 340: return (dfile); ! 341: } ! 342: (void) strcpy(dfile, dir); ! 343: if (dir[strlen(dir) - 1] != '/' && *file != '/') ! 344: (void) strcat(dfile, "/"); ! 345: (void) strcat(dfile, file); ! 346: return (dfile); ! 347: } ! 348: ! 349: char * ! 350: savestr(str) ! 351: char *str; ! 352: { ! 353: char *cp = malloc(strlen(str) + 1); ! 354: ! 355: if (cp == NULL) { ! 356: dprintf("ls: out of memory\n"); ! 357: exit(1); ! 358: } ! 359: (void) strcpy(cp, str); ! 360: return (cp); ! 361: } ! 362: ! 363: char *fmtinum(), *fmtsize(), *fmtlstuff(), *fmtmode(); ! 364: ! 365: dprintf(a, b, c) ! 366: char *a, *b, *c; ! 367: { ! 368: fprintf(stderr, a, b, c); ! 369: fflush(stderr); ! 370: } ! 371: ! 372: char * ! 373: fmtentry(fp) ! 374: register struct afile *fp; ! 375: { ! 376: static char fmtres[BUFSIZ]; ! 377: register char *cp, *dp; ! 378: ! 379: (void) sprintf(fmtres, "%s%s%s", ! 380: iflg ? fmtinum(fp) : "", ! 381: sflg ? fmtsize(fp) : "", ! 382: lflg ? fmtlstuff(fp) : ""); ! 383: dp = &fmtres[strlen(fmtres)]; ! 384: for (cp = fp->fname; *cp; cp++) ! 385: *dp++ = *cp; ! 386: if (Fflg) { ! 387: if (fp->ftype == 'd') ! 388: *dp++ = '/'; ! 389: else if (fp->ftype == 'l') ! 390: *dp++ = '@'; ! 391: else if (fp->fflags & 0111) ! 392: *dp++ = '*'; ! 393: } ! 394: if (lflg && fp->flinkto) { ! 395: (void) strcpy(dp, " -> "); dp += 4; ! 396: for (cp = fp->flinkto; *cp; cp++) ! 397: *dp++ = *cp; ! 398: } ! 399: *dp = 0; ! 400: return (fmtres); ! 401: } ! 402: ! 403: char * ! 404: fmtinum(p) ! 405: register struct afile *p; ! 406: { ! 407: static char inumbuf[8]; ! 408: ! 409: (void) sprintf(inumbuf, "%5d ", p->fnum); ! 410: return (inumbuf); ! 411: } ! 412: ! 413: char * ! 414: fmtsize(p) ! 415: register struct afile *p; ! 416: { ! 417: static char sizebuf[32]; ! 418: ! 419: switch (p->ftype) { ! 420: ! 421: case 'b': ! 422: case 'c': ! 423: (void) sprintf(sizebuf, "%4ld ", 0); ! 424: break; ! 425: ! 426: default: ! 427: (void) sprintf(sizebuf, "%4ld ", kbytes(p->fsize)); ! 428: break; ! 429: } ! 430: return (sizebuf); ! 431: } ! 432: ! 433: char * ! 434: fmtlstuff(p) ! 435: register struct afile *p; ! 436: { ! 437: static char lstuffbuf[256]; ! 438: char gname[32], uname[32], fsize[32], ftime[32]; ! 439: register char *lp = lstuffbuf; ! 440: extern char *ngs(); ! 441: ! 442: /* type mode uname gname fsize ftime */ ! 443: /* get uname */ ! 444: { char *cp = getname(p->fuid); ! 445: if (cp) ! 446: (void) sprintf(uname, "%.*s", NMAX, cp); ! 447: else ! 448: (void) sprintf(uname, "%d", p->fuid); ! 449: } ! 450: /* get gname */ ! 451: { ! 452: char *cp = getgroup(p->fgid); ! 453: if (cp) ! 454: (void) sprintf(gname, "%.*s", NMAX, cp); ! 455: else ! 456: (void) sprintf(gname, "%d", p->fgid); ! 457: } ! 458: /* get fsize */ ! 459: if (p->ftype == 'b' || p->ftype == 'c') ! 460: (void) sprintf(fsize, "%d,%3d", ! 461: major(p->fsize), minor(p->fsize)); ! 462: else ! 463: (void) sprintf(fsize, "%ld", p->fsize); ! 464: /* get ftime */ ! 465: { char *cp = ctime(&p->fmtime); ! 466: if ((p->fmtime < sixmonthsago) || (p->fmtime > now)) ! 467: (void) sprintf(ftime, " %-7.7s %-4.4s ", cp+4, cp+20); ! 468: else ! 469: (void) sprintf(ftime, " %-12.12s ", cp+4); ! 470: } ! 471: /* splat */ ! 472: *lp++ = p->ftype; ! 473: lp = fmtmode(lp, p->fflags); ! 474: (void) sprintf(lp, "%2d%c %s%s", ! 475: p->fnl, p->flink, ngs(uname, gname, fsize), ftime); ! 476: return (lstuffbuf); ! 477: } ! 478: ! 479: /* format username, group, size in small space */ ! 480: char * ! 481: ngs(name, group, size) ! 482: char *name, *group, *size; ! 483: { ! 484: static char r[64]; ! 485: register s1, s2; ! 486: register sn=strlen(name), sg=strlen(group), ss=strlen(size); ! 487: ! 488: s1 = 8-sn; ! 489: s2 = 12-(sg+ss); ! 490: if (s2<1) { ! 491: s1 -= 1-s2; ! 492: s2 = 1; ! 493: } ! 494: if (s1<1) { ! 495: s2 -= 1-s1; ! 496: s1 = 1; ! 497: } ! 498: if (s2<1) ! 499: s2 = 1; ! 500: sprintf(r, "%s%*s%s%*s%s", name, s1, "", group, s2, "", size); ! 501: return(r); ! 502: } ! 503: ! 504: ! 505: int m1[] = { 1, S_IREAD>>0, 'r', '-' }; ! 506: int m2[] = { 1, S_IWRITE>>0, 'w', '-' }; ! 507: int m3[] = { 2, S_ISUID, 's', S_IEXEC>>0, 'x', '-' }; ! 508: int m4[] = { 1, S_IREAD>>3, 'r', '-' }; ! 509: int m5[] = { 1, S_IWRITE>>3, 'w', '-' }; ! 510: int m6[] = { 2, S_ISGID, 's', S_IEXEC>>3, 'x', '-' }; ! 511: int m7[] = { 1, S_IREAD>>6, 'r', '-' }; ! 512: int m8[] = { 1, S_IWRITE>>6, 'w', '-' }; ! 513: int m9[] = { 1, S_IEXEC>>6, 'x', '-' }; ! 514: ! 515: int *m[] = { m1, m2, m3, m4, m5, m6, m7, m8, m9}; ! 516: ! 517: char * ! 518: fmtmode(lp, flags) ! 519: char *lp; ! 520: int flags; ! 521: { ! 522: int **mp; ! 523: char cc; ! 524: ! 525: if ((flags&S_ICCTYP)==S_ISYNC) { ! 526: flags &= ~S_ICCTYP; ! 527: cc = 'y'; ! 528: } else if ((flags&S_ICCTYP)==S_IEXCL) { ! 529: flags &= ~S_ICCTYP; ! 530: cc = 'e'; ! 531: } else ! 532: cc = ' '; ! 533: ! 534: for (mp = &m[0]; mp < &m[sizeof(m)/sizeof(m[0])]; ) { ! 535: register int *pairp = *mp++; ! 536: register int n = *pairp++; ! 537: ! 538: while (--n >= 0 && (flags&*pairp++) == 0) ! 539: pairp++; ! 540: *lp++ = *pairp; ! 541: } ! 542: *lp++ = cc; ! 543: return (lp); ! 544: } ! 545: ! 546: /* rest should be done with nameserver or database */ ! 547: ! 548: char * ! 549: getname(uid) ! 550: { ! 551: register struct id *ip; ! 552: static struct id *lastip; ! 553: ! 554: if (names == NULL) ! 555: initnames(); ! 556: if (names == NULL) ! 557: return (NULL); ! 558: if (lastip && lastip->id == uid) ! 559: return (lastip->name); ! 560: for (ip = names; ip < lastname; ip++) ! 561: if (ip->id == uid) { ! 562: lastip = ip; ! 563: return (ip->name); ! 564: } ! 565: return (NULL); ! 566: } ! 567: ! 568: initnames() ! 569: { ! 570: register struct passwd *pw; ! 571: register struct id *ip; ! 572: register int nnames; ! 573: struct passwd *getpwent(); ! 574: char *malloc(), *realloc(); ! 575: ! 576: if ((names = (struct id *)malloc(sizeof(*names) * NUID)) == NULL) ! 577: return; ! 578: nnames = NUID; ! 579: ip = names; ! 580: setpwent(); ! 581: while (pw = getpwent()) { ! 582: if (ip >= names + nnames) { ! 583: if ((names = (struct id *)realloc((char *)names, ! 584: sizeof(*names) * (NUID+nnames))) == NULL) ! 585: return; ! 586: ip = names + nnames; ! 587: nnames += NUID; ! 588: } ! 589: ip->id = pw->pw_uid; ! 590: strncpy(ip->name, pw->pw_name, NMAX); ! 591: ip++; ! 592: } ! 593: lastname = ip; ! 594: endpwent(); ! 595: } ! 596: ! 597: char * ! 598: getgroup(gid) ! 599: { ! 600: register struct id *ip; ! 601: static struct id *lastip; ! 602: ! 603: if (groups == NULL) ! 604: initgroups(); ! 605: if (groups == NULL) ! 606: return (NULL); ! 607: if (lastip && lastip->id == gid) ! 608: return (lastip->name); ! 609: for (ip = groups; ip < lastgroup; ip++) ! 610: if (ip->id == gid) { ! 611: lastip = ip; ! 612: return (ip->name); ! 613: } ! 614: return (NULL); ! 615: } ! 616: ! 617: initgroups() ! 618: { ! 619: register struct group *gr; ! 620: register struct id *ip; ! 621: register int ngroups; ! 622: struct group *getgrent(); ! 623: char *malloc(), *realloc(); ! 624: ! 625: if ((groups = (struct id *)malloc(sizeof(*groups) * NGID)) == NULL) ! 626: return; ! 627: ngroups = NGID; ! 628: ip = groups; ! 629: setgrent(); ! 630: while (gr = getgrent()) { ! 631: if (ip >= groups + ngroups) { ! 632: if ((groups = (struct id *)realloc((char *)groups, ! 633: sizeof(*groups) * (NGID+ngroups))) == NULL) ! 634: return; ! 635: ip = groups + ngroups; ! 636: ngroups += NGID; ! 637: } ! 638: ip->id = gr->gr_gid; ! 639: strncpy(ip->name, gr->gr_name, NMAX); ! 640: ip++; ! 641: } ! 642: lastgroup = ip; ! 643: endgrent(); ! 644: } ! 645: ! 646: /* ! 647: * temp hack ! 648: */ ! 649: ! 650: lsacct(s) ! 651: char *s; ! 652: { ! 653: int f; ! 654: ! 655: if ((f = open("/tmp/lsacct", 1)) < 0) ! 656: return; ! 657: write(f, s, strlen(s)); ! 658: write(f, "\n", 1); ! 659: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.