|
|
1.1 root 1: /*
2: **********************************************************************
3: * *
4: * dired [][dir][files] Stuart Cracraft (mclure@sri-unix) Sept 1980 *
5: * *
6: * Directory editor. *
7: * edit/delete files in a directory or a file list *
8: * compile with the berkeley termlib archive *
9: * and don't forget to change the 'helpfile' and *
10: * 'dirednam' strings to reflect your own setup. *
11: * *
12: * Note: if you make improvements, I'd like to get them too. *
13: * Stuart Cracraft mclure@sri-unix, *
14: * ucbvax!menlo70!sri-unix!mclure *
15: * so would I: Jay Lepreau lepreau@utah-20, *
16: * decvax!randvax!utah-cs!lepreau *
17: **********************************************************************
18: */
19:
20: /*
21: * Enhanced by J.Lepreau, Univ of Utah, 8-10/81:
22: * --bunch of stuff, including more cmds, 2 window mode,
23: * bufering output, pathname substition in !escapes,
24: * initial sort options, ^G escape from sorts, ^U escape
25: * from !escapes, empty dir check.
26: */
27:
28: #ifdef COMMENT
29:
30: Modified 12/81 by Lepreau:
31: 1. Fix up aborting of command escapes, with mildy tricky re-display.
32: 2. Make default window size be half-screen (2 window mode).
33: Added option -wf to get full screen.
34: 3. Add check for too many files to avoid core-dump.
35: 4. Fix bug in cmd escapes: must reset caught signals before invocation.
36:
37: #endif COMMENT
38:
39: /*
40: things to consider
41: - perhaps should be able to edit protection field and
42: be able to change protection instantly at the
43: touch of a key (or queue the change for later exit)
44:
45: -- Would be nice if there were cmds (e.g. 'c') which would update
46: 1) the file-info & re-display it, & 2) update whole
47: display's info.
48: */
49:
50: #ifdef vax /* this does for now */
51: # define VFORK
52: #endif
53:
54: #ifndef VFORK
55: # define vfork fork
56: #endif
57:
58: #define FALSE 0
59: #define TRUE 1
60: #define NOTDELETED 0
61: #define DELETED 1
62:
63: /* Sort Orders */
64: #define NAME 0
65: #define SIZE 1
66: #define WRITE 2
67: #define READ 3
68: char sortstr[] = "nswr"; /* must be in order by above */
69:
70: #define ESC '\033'
71: #define CURSOR 48 /* X-coord of cursor, just b4 file */
72: #define CTRL(c) ('c' & 037)
73:
74: #include <stdio.h>
75: #include <sys/types.h>
76: #include <signal.h>
77: #include <sgtty.h>
78: #include <sys/stat.h>
79: #include <sys/dir.h>
80:
81: #ifdef UTAH
82: char *dirednam = "/usr/local/dired "; /* Where dired lives - need blnk */
83: char *helpfile = "/usr/help/dired.hlp"; /* Where helpfile lives */
84: #else
85: char *dirednam = "dired "; /* Where dired lives - need blnk */
86: char *helpfile = "/usr/lib/dired"; /* Where helpfile lives */
87: #endif
88:
89: char divider[132]; /* divides the windows */
90: #define DIVCHAR '-' /* makes up the divider */
91:
92: #define MOREPGM "p " /* program to page thru a file */
93:
94: #define MAXFILES 2000 /* Max number of files we can handle */
95:
96: struct lbuf
97: {
98: union
99: {
100: char lname[30];
101: char *namep;
102: } ln;
103: short deleted;
104: char ltype;
105: short lnum;
106: short lflags;
107: short lnl;
108: short luid;
109: short lgid;
110: long lsize;
111: long latime;
112: long lctime;
113: long lmtime;
114: };
115:
116: struct lbuf file[MAXFILES];
117:
118: struct stat statbuf;
119: struct sgttyb ioctlb;
120:
121: #define ISARG 0100000
122:
123: int gflg,
124: iflg,
125: lflg,
126: sflg; /* Random flags */
127: int splitflg; /* Split screen? */
128: int sortyp; /* Key to sort on */
129: int errcode; /* Error variable used by rm */
130: int rflg = 1; /* Reverse sort flag */
131: int totfiles = 0; /* Total files */
132: int flags; /* Gets flags */
133: int blurb; /* 1=>thing in echo area,0 otherwise */
134: int numdeleted; /* Number of files marked deleted */
135: long ttime; /* Temp time variable */
136: long year; /* Six months ago */
137: long totblocks = 0; /* Total blocks */
138: int lastuid = -1; /* Last uid/gid we handled */
139: char tempbuf[128]; /* Random temporary buffer */
140: char userbuf[35]; /* Temporary buffer for user name */
141: FILE *pwdf, *dirf; /* Password/group file and directory files */
142:
143: int curfile = 0; /* Current file */
144: int topfile = 0; /* File at top of screen */
145: int curline = 0; /* Line that we're on */
146: int scrlen = 999; /* Length of screen - dired part: half size */
147: int Worklen = 0; /* Length of 'working window', the other part*/
148: int Worktop = 0; /* Top of " " */
149: int Tscrlen; /*Total length of screen,minus 1 for cmd line*/
150: int scrwid = 79; /* Width of screen */
151: char *CL,
152: *UP, /* Termcap strings we'll use */
153: *HO,
154: *CM,
155: *CD, /* clear to end of display */
156: *CE,
157: *AL; /* insert line */
158: char PC;
159: char tbuf[1024],
160: tcapbuf[128];
161: char *tgetstr (), *tgoto ();
162: char *getenv ();
163: int compar ();
164: char *ctime ();
165: char *index();
166: char *makename ();
167: char *catargs();
168: char *bldnam();
169: long nblock ();
170: int catchint();
171: int sigint;
172:
173: char bufout[BUFSIZ];
174:
175: main (argc, argv)
176: int argc;
177: char *argv[];
178: {
179: register int i,
180: cc;
181: int numarg,
182: special, /* flag says had % or # in cmd */
183: status;
184: char nambuf[128];
185: char command; /* Holds last command */
186: char **oldargv;
187: register char *t,
188: *tt;
189:
190: /* Get terminal type */
191:
192: getcap ();
193:
194: /* Process arg flags. They must be first! */
195: for (i=1; i<argc; i++) {
196: if (argv[i][0] != '-')
197: break;
198: switch (cc = argv[i][1]) {
199: case 'w': /* Window size */
200: if (argv[i][2] == 'h')
201: scrlen = 999; /* Half */
202: else if (argv[i][2] == 'f')
203: scrlen = 0; /* Full */
204: else
205: scrlen = atoi(&argv[i][2]);
206: break;
207: case 's': /* Initial sort order */
208: case 'r':
209: sortyp = index(sortstr, argv[i][2]) - sortstr;
210: rflg = (cc == 's') ? 1 : -1;
211: break;
212: default:
213: printf("Unknown option %s, ignored.\n", argv[i]);
214: break;
215: }
216: }
217: argc -= (i - 1);
218: oldargv = argv;
219: argv += (i - 1);
220:
221: if (scrlen == 0) /* full screen */
222: scrlen = Tscrlen;
223: else if (scrlen == 999) /* means split in half */
224: scrlen = (Tscrlen - 1) >> 1;
225: if (scrlen < 2)
226: scrlen = 2;
227: if (Tscrlen < scrlen)
228: scrlen = Tscrlen;
229: splitflg = (Tscrlen > scrlen+1); /* 1 extra line for separator */
230: if (splitflg) {
231: Worklen = Tscrlen - (scrlen+1); /* size of 'working' window */
232: Worktop = scrlen + 1; /* bottom half for now */
233: }
234: else
235: Worklen = 0;
236:
237: tt = divider + scrwid - 14;
238: for (t = divider; t < tt;) /* arbitrary length */
239: *t++ = DIVCHAR;
240: *t = '\0';
241:
242: signal (SIGINT, SIG_IGN);
243: signal (SIGQUIT, SIG_IGN);
244:
245: setdpy ();
246: printf ("Reading");
247:
248: time (&ttime);
249: year = ttime - 6L * 30L * 24L * 60L * 60L;/* 6 months ago */
250:
251: lflg = 1;
252: gflg = iflg = sflg = 0;
253: if (lflg)
254: {
255: t = "/etc/passwd";
256: if (gflg)
257: t = "/etc/group";
258: pwdf = fopen (t, "r");
259: }
260:
261:
262: numarg = argc;
263: if (argc == 1)
264: readdir (".");
265: else
266: if (argc == 2)
267: readdir (argv[1]);
268: else
269: {
270: while (--argc > 0)
271: {
272: if (totfiles == MAXFILES) {
273: overflow();
274: break;
275: }
276: if ((totfiles % 10) == 0)
277: putchar ('.');
278: if (gstat(*++argv) == 0) {
279: file[totfiles].ln.namep = *argv;
280: file[totfiles].lflags |= ISARG;
281: totfiles++;
282: }
283: }
284: }
285: if (totfiles == 0) {
286: printf("\n?Empty directory\n");
287: unsetdpy();
288: sleep(1); /* So user can see it - don't worry if less */
289: exit(0);
290: }
291: qsort (file, totfiles, sizeof (struct lbuf), compar);
292: blank ();
293: showscreen ();
294: curxy (0, Tscrlen);
295: ceol ();
296: curxy (CURSOR, 0);
297: startup:
298: while ((command = readchar()) != 'q')
299: {
300: if (blurb)
301: {
302: telluser ("");
303: blurb = 0;
304: }
305: switch (command)
306: {
307: case 'a': /* Abort completely */
308: blank ();
309: unsetdpy ();
310: exit (1);
311: break;
312: case 'P': /* Print a file */
313: case 'p': /* do a pr2 */
314: if (file[curfile].ltype == 'd')
315: {
316: telluser ("?Can only print files");
317: break;
318: }
319: tempbuf[0] = '\0';
320: bldnam(tempbuf, numarg, curfile, argv);
321: telluser ("Printing...");
322: while ((i = vfork ()) == -1)
323: sleep (3);
324: if (i == 0) {
325: #ifdef UTAH
326: if (command == 'p') /* little print */
327: execlp("pr2", "pr2", tempbuf, 0);
328: else /* big print */
329: #endif
330: execlp ("print", "print", tempbuf, 0);
331: telluser ("?Can't find program to list file.\n");
332: _exit(1);
333: }
334: wait (&status);
335: break;
336:
337: case '!': /* Execute a system command */
338: telluser ("");
339: curxy (0, Tscrlen);
340: unsetdpy ();
341: printf ("Command: ");
342: tempbuf[0] = 'x'; /* dummy kludge */
343: if (gets(tempbuf) != NULL && tempbuf[0] != '\0') {
344: extern char *skipto();
345: register char *op, /* old ptr */
346: *np; /* new ptr */
347: char bldbuf[70];
348:
349: bldbuf[0] = '\0';
350: op = tempbuf;
351: special = 0;
352: while (cc = *(np = skipto(op, "%#"))) {
353: special++; /* set flag */
354: *np++ = '\0'; /* zap the %/# and bump past it */
355: strcat(bldbuf, op); /* 1st part */
356: if (cc == '%') /* complete file name */
357: bldnam(bldbuf, numarg, curfile, argv);
358: else { /* Had # sign, trailing comp only */
359: if (numarg <= 2)
360: strcat (bldbuf, file[curfile].ln.lname);
361: else
362: strcat (bldbuf, file[curfile].ln.namep);
363: }
364:
365: op = np;
366: }
367: strcat(bldbuf, op);
368:
369: blank ();
370: if (special) { /* display expanded command */
371: printf( "%s\n", bldbuf);
372: } /* "system" takes long enuf for him to see it */
373: signal(SIGINT, SIG_DFL); /* temp kludge here... */
374: signal(SIGQUIT, SIG_DFL); /* should not use 'system' */
375: system (bldbuf);
376: signal (SIGINT, SIG_IGN);
377: signal (SIGQUIT, SIG_IGN);
378: printf ("\nCR to return...");
379: setdpy ();
380: readchar();
381: blank ();
382: showscreen ();
383: telluser ("");
384: }
385: else { /* CR only, or EOF, or error */
386: /*
387: * He changed his mind, skip it. Since we were in
388: * cooked mode, the CR ending the gets is echoed and
389: * we lost the first line of the display. So we
390: * re-insert it.
391: */
392: setdpy();
393: if (tempbuf[0] == 'x') /* means EOF */
394: telluser("");
395: /* null entry, normal case */
396: else if (AL == 0) { /* no insert line capability */
397: blank();
398: showscreen();
399: }
400: else { /* be a little sneakier */
401: curxy(0, Tscrlen-1); /* go back to where prompt */
402: ceol(); /* is now, and blank it */
403: home();
404: insline(); /* make some room */
405: pentry(topfile);
406: putchar('\n');
407: }
408: curxy(CURSOR, curline);
409: }
410: break;
411:
412: case 'r': /* Reverse sort */
413: curxy (0, Tscrlen);
414: printf ("reverse ");
415: rflg = -1;
416: case 's': /* Normal sort */
417: if (command == 's')
418: {
419: curxy (0, Tscrlen);
420: rflg = 1;
421: }
422: printf ("sort by [s,n,r,w]: ");
423: command = readchar();
424: while ((command == '?') || !((command == 'n') ||
425: (command == 'r') || (command == 'w') || (command == 's') ||
426: (command == CTRL(g))))
427: {
428: curxy (0, Tscrlen);
429: ceol ();
430: if (rflg == -1)
431: printf ("reverse ");
432: printf ("sort by size, name, read or write date: ");
433: command = readchar();
434: }
435:
436: if (command == CTRL(g)) { /* abort */
437: putchar(CTRL(g)); /* echo it */
438: telluser("");
439: curxy(CURSOR, curline);
440: break;
441: }
442:
443: if (command == 's')
444: sortyp = SIZE;
445: else
446: if (command == 'w')
447: sortyp = WRITE;
448: else
449: if (command == 'r')
450: sortyp = READ;
451: else
452: sortyp = 0;
453: printf ("%c", command);
454: qsort (file, totfiles, sizeof (struct lbuf), compar);
455: topfile = 0;
456: curfile = 0;
457: curline = 0;
458: blank ();
459: showscreen ();
460: curxy (CURSOR, 0);
461: break;
462:
463: case 'e': /* Edit a file or directory */
464: if (file[curfile].ltype == 'd') {
465: strcpy (tempbuf, dirednam);
466: catargs(tempbuf, oldargv);
467: }
468: else {
469: if ((t = getenv("EDITOR")) != NULL)
470: strcat(strcpy(tempbuf, t), " ");
471: else
472: strcpy (tempbuf, "ed ");
473: }
474: bldnam(tempbuf, numarg, curfile, argv);
475: blank ();
476: unsetdpy ();
477: system (tempbuf);
478: setdpy ();
479: blank ();
480: showscreen ();
481: telluser ("");
482: break;
483:
484: case 'm': /* 'more' a file */
485: if (file[curfile].ltype == 'd')
486: {
487: telluser ("?Can only page thru files");
488: break;
489: }
490: strcpy (tempbuf, MOREPGM);
491: bldnam(tempbuf, numarg, curfile, argv);
492: blank ();
493: unsetdpy ();
494: system (tempbuf);
495: /* if (!sigint) { */
496: printf ("\nCR to return...");
497: /* } */
498: setdpy ();
499: readchar();
500: blank ();
501: showscreen ();
502: telluser ("");
503: break;
504:
505: case 'T': /* don't wait at page end */
506: case 't': /* quickly type the file -- added 5/81, J.Lepreau */
507: if (file[curfile].ltype == 'd')
508: {
509: telluser ("?Can only type files");
510: break;
511: }
512: tempbuf[0] = '\0';
513: bldnam(tempbuf, numarg, curfile, argv);
514: if (type(tempbuf, command == 't')) /* little t means wait */
515: showscreen ();
516: curxy (CURSOR, curline);
517: break;
518:
519: case 'l': /* Refresh screen */
520: case CTRL(l): /* added for editor compatibility -fjl */
521: blank ();
522: showscreen ();
523: telluser ("");
524: break;
525: case 'c': /* Refresh current line */
526: curxy (0, curline);
527: pentry (curfile);
528: curxy (CURSOR, curline);
529: break;
530: case CTRL(v):
531: case 'f': /* forward window */
532: fscreen ();
533: break;
534: /* wish we could do meta-v */
535: case 'b': /* backward window */
536: bscreen ();
537: break;
538: case CTRL(n):
539: case '\r':
540: case '\n': /* next file */
541: if (curfile == totfiles - 1)
542: telluser ("?At end of files");
543: else
544: if (curline == scrlen - 1)
545: {
546: topfile = curfile;
547: curline = 0;
548: blank ();
549: showscreen ();
550: curxy (CURSOR, 0);
551: downline ();
552: }
553: else
554: downline ();
555: break;
556: case '^': /* previous file */
557: case CTRL(h): /* backspace */
558: case '-':
559: case CTRL(p):
560: if (curfile == 0)
561: telluser ("?At start of files");
562: else
563: if (curline == 0)
564: {
565: topfile = curfile - scrlen + 1;
566: curline = scrlen - 1;
567: blank ();
568: showscreen ();
569: curxy (CURSOR, curline);
570: upline ();
571: }
572: else
573: upline ();
574: break;
575: case 'h': /* Help */
576: case '?':
577: if (type(helpfile, 1)) /* wait */
578: showscreen ();
579: curxy (CURSOR, curline);
580: break;
581: case 'd': /* delete file */
582: if (file[curfile].deleted == DELETED)
583: telluser ("?Already marked deleted");
584: else
585: {
586: numdeleted++;
587: file[curfile].deleted = DELETED;
588: printf ("D%c", 010);
589: if (curline + 1 == scrlen)
590: {
591: fscreen ();
592: downline ();
593: }
594: else
595: if (curfile != totfiles - 1)
596: downline ();
597: }
598: break;
599: case 'u': /* undelete file */
600: if (file[curfile].deleted == NOTDELETED)
601: telluser ("?Not marked deleted");
602: else
603: {
604: numdeleted--;
605: file[curfile].deleted = NOTDELETED;
606: printf (" %c", 010);
607: }
608: break;
609: default:
610: telluser ("Unknown command. Type ? or h for help");
611: break;
612: }
613: }
614: if (numdeleted)
615: {
616: blank ();
617: printf ("The following %s marked for deletion:\n",
618: (numdeleted == 1) ? "is" : "are");
619: typefiles ();
620: printf ("\nShall I delete %s? ",
621: (numdeleted == 1) ? "this" : "these");
622: if ((command = readchar()) != 'y')
623: {
624: blank ();
625: showscreen ();
626: curxy (0, Tscrlen);
627: ceol ();
628: curxy (CURSOR, curline);
629: goto startup;
630: }
631: else
632: {
633: printf ("y\n");
634: for (i = 0; i < totfiles; i++)
635: if (file[i].deleted == DELETED) {
636: nambuf[0] = '\0';
637: bldnam(nambuf, numarg, i, argv);
638: if (file[i].ltype == 'd')
639: rm (nambuf, 0);
640: else
641: if (unlink (nambuf) < 0)
642: printf ("Delete of %s failed.\n", nambuf);
643: }
644: }
645: }
646: else
647: blank ();
648:
649: unsetdpy ();
650: exit(0);
651: }
652:
653: typefiles ()
654: {
655: int longsiz,
656: i,
657: j,
658: maxperln,
659: numout,
660: longthis;
661: longsiz = numout = 0;
662: for (i = 0; i < totfiles; i++)
663: if (file[i].deleted == DELETED)
664: if (file[i].lflags & ISARG)
665: {
666: if (strlen (file[i].ln.namep) > longsiz)
667: {
668: longsiz = strlen (file[i].ln.namep);
669: }
670: }
671: else
672: {
673: if (strlen (file[i].ln.lname) > longsiz)
674: {
675: longsiz = strlen (file[i].ln.lname);
676: }
677: }
678: maxperln = scrwid / (longsiz + 3);
679: for (i = 0; i < totfiles; i++)
680: if (file[i].deleted == DELETED)
681: {
682: if (file[i].lflags & ISARG)
683: {
684: printf ("%s", file[i].ln.namep);
685: longthis = strlen (file[i].ln.namep);
686: }
687: else
688: {
689: printf ("%.14s", file[i].ln.lname);
690: longthis = strlen (file[i].ln.lname);
691: }
692: numout++;
693: if ((numout % maxperln) == 0)
694: putchar ('\n');
695: else if (numout != numdeleted)
696: for (j = 0; j < (longsiz + 3 - longthis); j++)
697: putchar (' ');
698: }
699: }
700:
701: rm (arg, level)
702: char arg[];
703: {
704: struct stat buf;
705: struct direct direct;
706: char name[100];
707: int d;
708:
709: if (stat (arg, &buf))
710: {
711: return;
712: }
713: if ((buf.st_mode & S_IFMT) == S_IFDIR)
714: {
715: if (access (arg, 02) < 0)
716: {
717: printf ("%s not deleted.\n", arg);
718: return;
719: }
720: if ((d = open (arg, 0)) < 0)
721: {
722: printf ("rm: %s: cannot read\n", arg);
723: return;
724: }
725: while (read (d, (char *) & direct, sizeof (direct)) == sizeof (direct))
726: {
727: if (direct.d_ino != 0 && !dotname (direct.d_name))
728: {
729: sprintf (name, "%s/%.14s", arg, direct.d_name);
730: rm (name, level + 1);
731: }
732: }
733: close (d);
734: errcode += rmdir (arg);
735: return;
736: }
737:
738: if (unlink (arg))
739: {
740: ++errcode;
741: printf ("%s not deleted.\n", arg);
742: }
743: }
744:
745: dotname (s)
746: char *s;
747: {
748: if (s[0] == '.')
749: if (s[1] == '.')
750: if (s[2] == '\0')
751: return (1);
752: else
753: return (0);
754: else
755: if (s[1] == '\0')
756: return (1);
757: return (0);
758: }
759:
760: rmdir (f)
761: char *f;
762: {
763: int status,
764: i;
765:
766: if (dotname (f))
767: return (0);
768: while ((i = vfork ()) == -1)
769: sleep (3);
770: if (i == 0) {
771: execl ("/bin/rmdir", "rmdir", f, 0);
772: execl ("/usr/bin/rmdir", "rmdir", f, 0);
773: printf ("rm: can't find rmdir\n");
774: _exit(1);
775: }
776: wait (&status);
777: return (status);
778: }
779:
780: fscreen ()
781: {
782: if (topfile + scrlen - 1 > totfiles - 1)
783: telluser ("?No remaining windows");
784: else
785: {
786: topfile = topfile + scrlen - 1;
787: curfile = topfile;
788: curline = 0;
789: blank ();
790: showscreen ();
791: curxy (CURSOR, 0);
792: }
793: }
794:
795: bscreen ()
796: {
797: if (topfile - scrlen + 1 < 0)
798: telluser ("?No previous windows");
799: else
800: {
801: topfile = topfile - scrlen + 1;
802: curfile = topfile;
803: curline = 0;
804: blank ();
805: showscreen ();
806: curxy (CURSOR, 0);
807: }
808: }
809:
810: showscreen ()
811: {
812: int i,
813: numprint;
814: home ();
815: numprint = 0;
816: for (i = topfile; (numprint < scrlen) && (i < totfiles); i++)
817: {
818: numprint++;
819: pentry (i);
820: putchar ('\n');
821: }
822: if (splitflg)
823: printf ("%s\n", divider);
824: }
825:
826: readdir (dir) /* Reads directory dir */
827: char *dir;
828: {
829: static struct direct dentry;
830: register int j;
831:
832: if ((dirf = fopen (dir, "r")) == NULL)
833: {
834: printf ("\nSorry, %s unreadable.\n", dir);
835: unsetdpy ();
836: exit(1);
837: }
838: for (;;)
839: {
840: if (fread ((char *) & dentry, sizeof (dentry), 1, dirf) != 1)
841: break;
842: if (dentry.d_ino == 0
843: || dentry.d_name[0] == '.' && (dentry.d_name[1] == '\0'
844: || dentry.d_name[1] == '.' && dentry.d_name[2] == '\0'))
845: continue;
846:
847: if (totfiles == MAXFILES)
848: overflow(); /* abort, too may files */
849: /* Just ignore if can't find the file, dir may be changing */
850: if (gstat (makename (dir, dentry.d_name)) == 0) { /* 0 == Ok */
851: file[totfiles].lnum = dentry.d_ino;
852: for (j = 0; j < DIRSIZ; j++)
853: file[totfiles].ln.lname[j] = dentry.d_name[j];
854: totfiles++;
855: if (totfiles % 10 == 0)
856: putchar ('.');
857: }
858: }
859: fclose (dirf);
860: }
861:
862: gstat (name) /* Stats the file with name */
863: char *name;
864: {
865:
866: file[totfiles].lflags = 0;
867: file[totfiles].lnum = 0;
868: file[totfiles].ltype = '-';
869:
870: if (stat (name, &statbuf) < 0)
871: {
872: return(-1);
873: }
874: file[totfiles].lnum = statbuf.st_ino;
875: file[totfiles].lsize = statbuf.st_size;
876: switch (statbuf.st_mode & S_IFMT)
877: {
878: case S_IFLNK:
879: file[totfiles].ltype = 'l';
880: break;
881: case S_IFDIR:
882: file[totfiles].ltype = 'd';
883: break;
884: case S_IFBLK:
885: file[totfiles] .ltype = 'b';
886: file[totfiles].lsize = statbuf.st_rdev;
887: break;
888: case S_IFCHR:
889: file[totfiles].ltype = 'c';
890: file[totfiles].lsize = statbuf.st_rdev;
891: break;
892: }
893: file[totfiles].lflags = statbuf.st_mode & ~S_IFMT;
894: file[totfiles].luid = statbuf.st_uid;
895: file[totfiles].lgid = statbuf.st_gid;
896: file[totfiles].lnl = statbuf.st_nlink;
897: file[totfiles].latime = statbuf.st_atime;
898: file[totfiles].lctime = statbuf.st_ctime;
899: file[totfiles].lmtime = statbuf.st_mtime;
900: totblocks += nblock (statbuf.st_size);
901: return(0);
902: }
903:
904: char *
905: makename (dir, filen)
906: char *dir,
907: *filen;
908: {
909: static char dfile[100];
910: register char *dp,
911: *fp;
912: register int i;
913:
914: dp = dfile;
915: fp = dir;
916: while (*fp)
917: *dp++ = *fp++;
918: *dp++ = '/';
919: fp = filen;
920: for (i = 0; i < DIRSIZ; i++)
921: *dp++ = *fp++;
922: *dp = 0;
923: return (dfile);
924: }
925:
926: long
927: nblock (size)
928: long size;
929: {
930: return ((size + 511) >> 9);
931: }
932:
933: pentry (whichone)
934: int whichone;
935: {
936: struct
937: {
938: char dminor,
939: dmajor;
940: };
941: register t;
942: register char *cp;
943:
944: if (file[whichone].lnum == -1)
945: return;
946: if (iflg)
947: printf ("%5u ", file[whichone].lnum);
948: if (sflg)
949: printf ("%4D ", nblock (file[whichone].lsize));
950: if (lflg)
951: {
952: putchar (file[whichone].ltype);
953: pmode (file[whichone].lflags);
954: printf ("%2d ", file[whichone].lnl);
955: t = file[whichone].luid;
956: if (gflg)
957: t = file[whichone].lgid;
958: if (getname (t, userbuf) == 0)
959: printf ("%-14.14s", userbuf);
960: else
961: printf ("%-14d", t);
962: if (file[whichone].ltype == 'b' || file[whichone].ltype == 'c')
963: printf ("%3d,%3d", major ((int) file[whichone].lsize),
964: minor ((int) file[whichone].lsize));
965: else
966: printf ("%7ld", file[whichone].lsize);
967: if ((sortyp == WRITE) || (sortyp == 0) || (sortyp == SIZE))
968: {
969: cp = ctime (&file[whichone].lmtime);
970: if (file[whichone].lmtime < year)
971: printf (" %-7.7s %-4.4s ", cp + 4, cp + 20);
972: else
973: printf (" %-12.12s ", cp + 4);
974: }
975: else
976: if (sortyp == READ)
977: {
978: cp = ctime (&file[whichone].latime);
979: if (file[whichone].latime < year)
980: printf (" %-7.7s %-4.4s ", cp + 4, cp + 20);
981: else
982: printf (" %-12.12s ", cp + 4);
983: }
984: }
985: printf ("%c", file[whichone].deleted ? 'D' : ' ');
986: if (file[whichone].lflags & ISARG)
987: printf (" %s", file[whichone].ln.namep);
988: else {
989: putchar(' ');
990: for (t=0; t<14; t++) {
991: register c = file[whichone].ln.lname[t] & 0377;;
992: if (c == '\0')
993: break;
994: if (c<' ' || c>=0200) {
995: c &= 0177;
996: c |= 0100;
997: putchar('^');
998: }
999: putchar(c);
1000: }
1001: }
1002: }
1003:
1004: getname (uid, buf)
1005: int uid;
1006: char buf[];
1007: {
1008: int j,
1009: c,
1010: n,
1011: i;
1012:
1013: if (uid == lastuid)
1014: return (0);
1015: if (pwdf == NULL)
1016: return (-1);
1017: rewind (pwdf);
1018: lastuid = -1;
1019: do
1020: {
1021: i = 0;
1022: j = 0;
1023: n = 0;
1024: while ((c = fgetc (pwdf)) != '\n')
1025: {
1026: if (c == EOF)
1027: return (-1);
1028: if (c == ':')
1029: {
1030: j++;
1031: c = '0';
1032: }
1033: if (j == 0)
1034: buf[i++] = c;
1035: if (j == 2)
1036: n = n * 10 + c - '0';
1037: }
1038: } while (n != uid);
1039: buf[i++] = '\0';
1040: lastuid = uid;
1041: return (0);
1042: }
1043:
1044: int m1[] =
1045: {
1046: 1, S_IREAD >> 0, 'r', '-'
1047: };
1048: int m2[] =
1049: {
1050: 1, S_IWRITE >> 0, 'w', '-'
1051: };
1052: int m3[] =
1053: {
1054: 2, S_ISUID, 's', S_IEXEC >> 0, 'x', '-'
1055: };
1056: int m4[] =
1057: {
1058: 1, S_IREAD >> 3, 'r', '-'
1059: };
1060: int m5[] =
1061: {
1062: 1, S_IWRITE >> 3, 'w', '-'
1063: };
1064: int m6[] =
1065: {
1066: 2, S_ISGID, 's', S_IEXEC >> 3, 'x', '-'
1067: };
1068: int m7[] =
1069: {
1070: 1, S_IREAD >> 6, 'r', '-'
1071: };
1072: int m8[] =
1073: {
1074: 1, S_IWRITE >> 6, 'w', '-'
1075: };
1076: int m9[] =
1077: {
1078: 2, S_ISVTX, 't', S_IEXEC >> 6, 'x', '-'
1079: };
1080:
1081: int *m[] =
1082: {
1083: m1, m2, m3, m4, m5, m6, m7, m8, m9
1084: };
1085:
1086: pmode (aflag)
1087: {
1088: register int **mp;
1089:
1090: flags = aflag;
1091: for (mp = &m[0]; mp < &m[sizeof (m) / sizeof (m[0])];)
1092: select (*mp++);
1093: }
1094:
1095: select (pairp)
1096: register int *pairp;
1097: {
1098: register int n;
1099:
1100: n = *pairp++;
1101: while (--n >= 0 && (flags & *pairp++) == 0)
1102: pairp++;
1103: putchar (*pairp);
1104: }
1105:
1106: compar (pp1, pp2)
1107: struct lbuf *pp1,
1108: *pp2;
1109: {
1110: register struct lbuf *p1,
1111: *p2;
1112:
1113: p1 = pp1;
1114: p2 = pp2;
1115: if (p1 -> lflags & ISARG && p1 -> ltype == 'd')
1116: {
1117: if (!(p2 -> lflags & ISARG && p2 -> ltype == 'd'))
1118: return (1);
1119: }
1120: else
1121: {
1122: if (p2 -> lflags & ISARG && p2 -> ltype == 'd')
1123: return (-1);
1124: }
1125: if (sortyp == SIZE)
1126: {
1127: if (p2 -> lsize == p1 -> lsize)
1128: return (0);
1129: if (p2 -> lsize > p1 -> lsize)
1130: return (rflg);
1131: return (-rflg);
1132: }
1133: else
1134: if (sortyp == WRITE)
1135: {
1136: if (p2 -> lmtime == p1 -> lmtime)
1137: return (0);
1138: if (p2 -> lmtime > p1 -> lmtime)
1139: return (rflg);
1140: return (-rflg);
1141: }
1142: else
1143: if (sortyp == READ)
1144: {
1145: if (p2 -> latime == p1 -> latime)
1146: return (0);
1147: if (p2 -> latime > p1 -> latime)
1148: return (rflg);
1149: return (-rflg);
1150: }
1151: return (rflg * strcmp (p1 -> lflags & ISARG ? p1 -> ln.namep : p1 -> ln.lname,
1152: p2 -> lflags & ISARG ? p2 -> ln.namep : p2 -> ln.lname));
1153: }
1154:
1155: ceod()
1156: {
1157: putpad(CD);
1158: }
1159:
1160: ceol ()
1161: {
1162: putpad (CE);
1163: }
1164: blank ()
1165: {
1166: putpad (CL);
1167: }
1168: home ()
1169: {
1170: if (HO)
1171: putpad (HO);
1172: else
1173: curxy(0,0);
1174: }
1175: insline ()
1176: {
1177: putpad (AL);
1178: }
1179:
1180: /* Yes, folks, we use direct cursor addressing to get to next line!
1181: Before you mumble "What sort of cretin would do this?" here's
1182: the reason. We don't use \n since that obviously won't work.
1183: We don't use \012 since virgin version 7 makes that into a crlf.
1184: We don't use raw mode since we type out help files efficently,
1185: and we don't want to switch modes all the time. So enjoy. -- SMC */
1186:
1187: downline ()
1188: {
1189: curxy (CURSOR, ++curline);
1190: curfile++;
1191: }
1192: upline ()
1193: {
1194: putpad (UP);
1195: curline--;
1196: curfile--;
1197: }
1198:
1199: /*VARARGS1*/
1200: telluser (msg, args)
1201: char *msg;
1202: {
1203: curxy (0, Tscrlen);
1204: ceol ();
1205: printf (msg, args);
1206: curxy (CURSOR, curline);
1207: blurb++;
1208: }
1209: curxy (col, lin)
1210: {
1211: char *cmstr = tgoto (CM, col, lin);
1212: putpad (cmstr);
1213: }
1214:
1215: char *fgets();
1216:
1217: type (filestr, waitflg) /* Modified to type help file & others. fjl 5/81 */
1218: char *filestr; /* Kludgy now with split screen stuff! */
1219: {
1220: int helpfd = 5;
1221: FILE *fd = stdin;
1222: char *eof;
1223: register int i, n;
1224: register int cc = 0;
1225: int cur_scrl; /* current screen length */
1226: char helpbuf[512];
1227:
1228: if (!splitflg)
1229: helpfd = open(filestr, 0);
1230: else
1231: fd = fopen(filestr, "r");
1232: if (helpfd < 0 || fd == NULL) {
1233: telluser("?Unable to open %sfile",strcmp(filestr,helpfile)?"":"help ");
1234: return (FALSE);
1235: }
1236:
1237: signal(SIGINT, catchint);
1238: sigint = 0;
1239:
1240: if (!splitflg) {
1241: blank();
1242: fflush(stdout);
1243: while ((i = read (helpfd, helpbuf, 512)) > 0 && !sigint)
1244: write (1, helpbuf, i);
1245: close(helpfd);
1246: }
1247: else {
1248: cur_scrl = totfiles - topfile + 1; /* topfile starts at 0 */
1249: Worktop = ((cur_scrl < scrlen) ? cur_scrl : scrlen) + 1;
1250: do {
1251: curxy(0, Worktop);
1252: ceod();
1253: for (i = Worktop; (i < Tscrlen) && !sigint && (cc != EOF); i++) {
1254: n = 0;
1255: while ((cc = getc(fd)) != EOF) {
1256: if (cc == '\t')
1257: n |= 07;
1258: chklen: if (n++ == scrwid-1) { /* Use most of screen */
1259: if (cc != '\n') {
1260: ungetc(cc, fd);
1261: cc = '\n';
1262: }
1263: }
1264: if (cc < ' ' && cc!='\n' && cc!='\t' || cc>=0200) {
1265: putchar('^');
1266: cc &= 0177;
1267: cc |= 0100;
1268: goto chklen;
1269: }
1270: putchar(cc);
1271: if (cc == '\n')
1272: break;
1273: }
1274: }
1275: } while (!sigint && (cc != EOF) && waitchk(waitflg));
1276:
1277: if (feof(fd))
1278: printf("===== End-of-File =====\n");
1279: fflush(stdout);
1280: fclose(fd);
1281: return(FALSE); /* means needs no re-display */
1282: }
1283:
1284: if (!splitflg) { /* redundant now... */
1285: if (!sigint) {
1286: curxy(0, Tscrlen);
1287: printf ("CR to return...");
1288: readchar();
1289: }
1290: blank ();
1291: return (TRUE);
1292: }
1293: }
1294:
1295: waitchk(waitflg)
1296: {
1297: if (!waitflg)
1298: return(1);
1299: fflush(stdout);
1300: curxy(0, Tscrlen);
1301: printf ("---Continue---");
1302: ceol();
1303: curxy(0, Tscrlen);
1304: readchar();
1305: ceol();
1306: if (sigint)
1307: return(0); /* avoids clear of screen */
1308: return(1);
1309: }
1310:
1311: setdpy ()
1312: {
1313: ioctl (0, TIOCGETP, &ioctlb);
1314: ioctlb.sg_flags |= CBREAK;
1315: ioctlb.sg_flags &= ~ECHO;
1316: ioctl (0, TIOCSETP, &ioctlb);
1317: }
1318:
1319: unsetdpy ()
1320: {
1321: ioctlb.sg_flags &= ~CBREAK;
1322: ioctlb.sg_flags |= ECHO;
1323: ioctl (0, TIOCSETP, &ioctlb);
1324: }
1325:
1326: getcap ()
1327: {
1328: char *ap;
1329: char *term;
1330: char *xPC;
1331:
1332: term = getenv ("TERM");
1333: if (term == 0)
1334: {
1335: printf("No TERM in environment\n");
1336: exit(1);
1337: }
1338:
1339: switch (tgetent (tbuf, term))
1340: {
1341: case -1:
1342: printf("Cannot open termcap file\n");
1343: exit (2);
1344: case 0:
1345: printf("%s: unknown terminal", term);
1346: exit (3);
1347: }
1348:
1349: ap = tcapbuf;
1350:
1351: Tscrlen = tgetnum ("li") - 1;
1352: scrwid = tgetnum ("co") - 1;/* lose 1 so won't scroll in last line */
1353:
1354: UP = tgetstr ("up", &ap);
1355: CD = tgetstr ("cd", &ap);
1356: CE = tgetstr ("ce", &ap);
1357: HO = tgetstr ("ho", &ap);
1358: CL = tgetstr ("cl", &ap);
1359: CM = tgetstr ("cm", &ap);
1360: AL = tgetstr ("al", &ap); /* insert line, optional */
1361:
1362: xPC = tgetstr ("pc", &ap);
1363: if (xPC)
1364: PC = *xPC;
1365:
1366: if ((CM == 0) || (CL == 0) || (UP == 0))
1367: {
1368: printf("Tty must have cursor addr, clear, and 4 cursor motions.\n");
1369: exit (1);
1370: }
1371: if (Tscrlen <= 0 || scrwid <= 0)
1372: {
1373: printf("Must know the screen size\n");
1374: exit (1);
1375: }
1376: }
1377:
1378: outch (c)
1379: {
1380: putchar (c);
1381: }
1382:
1383: putpad (str)
1384: char *str;
1385: {
1386: if (str)
1387: tputs (str, 0, outch);
1388: }
1389:
1390: catchint(sig)
1391: {
1392: signal(SIGINT, SIG_IGN); /* reset it */
1393: sigint = 1;
1394: }
1395:
1396: char *
1397: bldnam(str, numarg, filidx, argv)
1398: char *str;
1399: char *argv[];
1400: {
1401:
1402: if (numarg == 1)
1403: strcat (str, file[filidx].ln.lname);
1404: else
1405: if (numarg == 2) {
1406: strcat (str, argv[1]);
1407: strcat (str, "/");
1408: strcat (str, file[filidx].ln.lname);
1409: }
1410: else
1411: strcat (str, file[filidx].ln.namep);
1412: return(str);
1413: }
1414:
1415: char *
1416: catargs(str, argv)
1417: char *str;
1418: char *argv[];
1419: {
1420: register int i;
1421:
1422: for (++argv; *argv; argv++) {
1423: if (**argv == '-') {
1424: strcat(str, *argv);
1425: strcat(str, " ");
1426: }
1427: }
1428: return(str);
1429: }
1430:
1431: overflow()
1432: {
1433: printf("\n?Too many files\007\n");
1434: fflush(stdout);
1435: sleep(1); /* So user can see it - don't worry if less */
1436: }
1437:
1438: char *skipto (string,charset)
1439: char *charset,*string;
1440: {
1441: register char *setp,*strp;
1442: register int found;
1443:
1444: found = 0; /* not found yet */
1445: strp = string; /* start at first char */
1446:
1447: while (*strp && !found) { /* until null or found */
1448: /* find first char in charset matching *strp */
1449: for (setp=charset; (*setp) && (*setp != *strp); setp++) ;
1450: if (*setp) found = 1; /* matches a char */
1451: else strp++; /* else keep looking */
1452: }
1453:
1454: return (strp);
1455: }
1456:
1457: readchar()
1458: {
1459: static neofs;
1460: register c;
1461:
1462: fflush(stdout);
1463: c = getchar();
1464: if (c == EOF)
1465: if (++neofs > 100)
1466: exit(1);
1467: return(c);
1468: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.