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