|
|
1.1 root 1: /* Copyright (c) 1979 Regents of the University of California */
2: #
3: /*
4: * ls - list file or directory
5: *
6: * Modified by Bill Joy UCB May/August 1977
7: *
8: * This version of ls is designed for graphic terminals and to
9: * list directories with lots of files in them compactly.
10: * It supports three variants for listings:
11: *
12: * 1) Columnar output.
13: * 2) Stream output.
14: * 3) Old one per line format.
15: *
16: * Columnar output is the default.
17: * If, however, the standard output is not a teletype, the default
18: * is one-per-line.
19: *
20: * With columnar output, the items are sorted down the columns.
21: * We use columns only for a directory we are interpreting.
22: * Thus, in particular, we do not use columns for
23: *
24: * ls /usr/bin/p*
25: *
26: * This version of ls also prints non-printing characters as '?' if
27: * the standard output is a teletype.
28: *
29: * Flags relating to these and other new features are:
30: *
31: * -m force stream output.
32: *
33: * -1 force one entry per line, e.g. to a teletype
34: *
35: * -q force non-printings to be '?'s, e.g. to a file
36: *
37: * -c force columnar output, e.g. into a file
38: *
39: * -n like -l, but user/group id's in decimal rather than
40: * looking in /etc/passwd to save time
41: */
42:
43: #include <sys/param.h>
44: #include <sys/stat.h>
45: #include <sys/dir.h>
46: #include <stdio.h>
47: #include <ctype.h>
48:
49:
50: #define NFILES 1024
51: FILE *pwdf, *dirf;
52:
53: struct lbuf {
54: union {
55: char lname[15];
56: char *namep;
57: } ln;
58: char ltype;
59: short lnum;
60: short lflags;
61: short lnl;
62: short luid;
63: short lgid;
64: long lsize;
65: long lmtime;
66: };
67:
68: int aflg, dflg, lflg, sflg, tflg, uflg, iflg, fflg, gflg, cflg;
69: int Aflg, nflg, qflg, across;
70: int nopad;
71: char buff[32];
72: int rflg = 1;
73: long year;
74: int flags;
75: int lastuid = -1;
76: char tbuf[16];
77: long tblocks;
78: int statreq;
79: struct lbuf *flist[NFILES];
80: struct lbuf **lastp = flist;
81: struct lbuf **firstp = flist;
82: char *dotp = ".";
83:
84: char *makename();
85: struct lbuf *gstat();
86: char *ctime();
87: long nblock();
88:
89: #define ISARG 0100000
90: int colwidth = 15;
91: int outcol;
92:
93: char obuf[BUFSIZ];
94:
95: main(argc, argv)
96: char *argv[];
97: {
98: int i;
99: register struct lbuf *ep, **ep1;
100: register struct lbuf **slastp;
101: struct lbuf **epp;
102: struct lbuf lb;
103: char *t;
104: char *cp;
105: int compar();
106:
107: Aflg = getuid() == 0;
108: setbuf(stdout, obuf);
109: time(&lb.lmtime);
110: year = lb.lmtime - 6L*30L*24L*60L*60L; /* 6 months ago */
111: qflg = gtty(1, buff) == 0;
112: /*
113: * If the standard output is not a teletype,
114: * then we default to one-per-line format
115: * otherwise decide between stream and
116: * columnar based on our name.
117: */
118: if (qflg) {
119: cflg = 1;
120: for (cp = argv[0]; cp[0] && cp[1]; cp++)
121: continue;
122: /*
123: * Name ends in l => stream
124: */
125: if (cp[0] == 'l')
126: nopad = 1, cflg = 0;
127: /*
128: * ... if doesn't end in l or s ==> columns sorted across
129: *
130: else if (cp[0] == 'x')
131: across = 1;
132: */
133: }
134: if (--argc > 0 && *argv[1] == '-') {
135: argv++;
136: while (*++*argv) switch (**argv) {
137: /*
138: * c - force columnar output
139: */
140: case 'c':
141: cflg = 1;
142: nopad = 0;
143: continue;
144: /*
145: * m - force stream output
146: */
147: case 'm':
148: cflg = 0;
149: nopad = 1;
150: continue;
151: /*
152: * x - force sort across
153: */
154: case 'x':
155: across = 1;
156: nopad = 0;
157: cflg = 1;
158: continue;
159: /*
160: * q - force ?'s in output
161: */
162: case 'q':
163: qflg = 1;
164: continue;
165: /*
166: * 1 - force 1/line in output
167: */
168: case '1':
169: cflg = 0;
170: nopad = 0;
171: continue;
172: /* STANDARD FLAGS */
173: case 'a':
174: aflg++;
175: continue;
176:
177: case 'A':
178: Aflg = !Aflg;
179: continue;
180:
181: case 's':
182: colwidth += 5;
183: sflg++;
184: statreq++;
185: continue;
186:
187: case 'd':
188: dflg++;
189: continue;
190:
191: /*
192: * n - don't look in password file
193: */
194: case 'n':
195: nflg++;
196: case 'l':
197: lflg++;
198: statreq++;
199: continue;
200:
201: case 'r':
202: rflg = -1;
203: continue;
204:
205: case 't':
206: tflg++;
207: statreq++;
208: continue;
209:
210: case 'u':
211: uflg++;
212: continue;
213:
214: case 'i':
215: colwidth += 5;
216: iflg++;
217: continue;
218:
219: case 'f':
220: fflg++;
221: continue;
222:
223: case 'g':
224: gflg++;
225: continue;
226:
227: default:
228: continue;
229: }
230: argc--;
231: }
232: if (fflg) {
233: aflg++;
234: lflg = 0;
235: sflg = 0;
236: tflg = 0;
237: statreq = 0;
238: }
239: if(lflg) {
240: cflg = 0;
241: t = "/etc/passwd";
242: if (gflg)
243: t = "/etc/group";
244: nopad = 0;
245: colwidth = 70;
246: pwdf = fopen(t, "r");
247: }
248: if (argc==0) {
249: argc++;
250: argv = &dotp - 1;
251: }
252: for (i=0; i < argc; i++) {
253: if ((ep = gstat(*++argv, 1))==NULL)
254: continue;
255: ep->ln.namep = *argv;
256: ep->lflags |= ISARG;
257: }
258: qsort(firstp, lastp - firstp, sizeof *lastp, compar);
259: slastp = lastp;
260: for (epp=firstp; epp<slastp; epp++) {
261: ep = *epp;
262: if (ep->ltype=='d' && dflg==0 || fflg) {
263: if (argc>1)
264: printf("\n%s:\n", ep->ln.namep);
265: lastp = slastp;
266: readdir(ep->ln.namep);
267: if (fflg==0)
268: qsort(slastp,lastp - slastp,sizeof *lastp,compar);
269: if (lflg || sflg)
270: printf("total %D", tblocks);
271: pem(slastp, lastp);
272: newline();
273: } else
274: pentry(ep);
275: }
276: if (outcol)
277: putc('\n', stdout);
278: fflush(stdout);
279: }
280:
281: pem(slp, lp)
282: register struct lbuf **slp, **lp;
283: {
284: int ncols, nrows, row, col;
285: register struct lbuf **ep;
286:
287: ncols = 80 / colwidth;
288: if (ncols == 1 || cflg == 0) {
289: for (ep = slp; ep < lp; ep++)
290: pentry(*ep);
291: return;
292: }
293: if (across) {
294: for (ep = slp; ep < lp; ep++)
295: pentry(*ep);
296: return;
297: }
298: if (statreq)
299: slp--;
300: nrows = (lp - slp - 1) / ncols + 1;
301: for (row = 0; row < nrows; row++) {
302: col = row == 0 && statreq;
303: for (; col < ncols; col++) {
304: ep = slp + (nrows * col) + row;
305: if (ep < lp)
306: pentry(*ep);
307: }
308: if (outcol)
309: printf("\n");
310: }
311: }
312:
313: pputchar(c)
314: char c;
315: {
316:
317: switch (c) {
318: case '\t':
319: outcol = (outcol + 8) &~ 7;
320: break;
321: case '\n':
322: outcol = 0;
323: break;
324: default:
325: if (qflg && (c < ' ' || c >= 0177))
326: c = '?';
327: outcol++;
328: break;
329: }
330: putc(c, stdout);
331: }
332:
333: newline()
334: {
335: if (outcol)
336: putc('\n', stdout);
337: outcol = 0;
338: }
339:
340: column()
341: {
342:
343: if (outcol == 0)
344: return;
345: if (nopad) {
346: putc(',', stdout);
347: outcol++;
348: if (outcol + colwidth + 2 > 80) {
349: putc('\n', stdout);
350: outcol = 0;
351: return;
352: }
353: putc(' ', stdout);
354: outcol++;
355: return;
356: }
357: if (cflg == 0) {
358: putc('\n', stdout);
359: return;
360: }
361: if ((outcol / colwidth + 2) * colwidth > 80) {
362: putc('\n', stdout);
363: outcol = 0;
364: return;
365: }
366: do {
367: outcol++;
368: putc(' ', stdout);
369: } while (outcol % colwidth);
370: }
371:
372:
373: getname(uid, buf)
374: int uid;
375: char buf[];
376: {
377: int j, c, n, i;
378:
379: if (uid==lastuid)
380: return(0);
381: if(pwdf == NULL)
382: return(-1);
383: rewind(pwdf);
384: lastuid = -1;
385: do {
386: i = 0;
387: j = 0;
388: n = 0;
389: while((c=fgetc(pwdf)) != '\n') {
390: if (c==EOF)
391: return(-1);
392: if (c==':') {
393: j++;
394: c = '0';
395: }
396: if (j==0)
397: buf[i++] = c;
398: if (j==2)
399: n = n*10 + c - '0';
400: }
401: } while (n != uid);
402: buf[i++] = '\0';
403: lastuid = uid;
404: return(0);
405: }
406:
407: long
408: nblock(size)
409: long size;
410: {
411: return((size+511)>>9);
412: }
413:
414: int m1[] = { 1, S_IREAD>>0, 'r', '-' };
415: int m2[] = { 1, S_IWRITE>>0, 'w', '-' };
416: int m3[] = { 2, S_ISUID, 's', S_IEXEC>>0, 'x', '-' };
417: int m4[] = { 1, S_IREAD>>3, 'r', '-' };
418: int m5[] = { 1, S_IWRITE>>3, 'w', '-' };
419: int m6[] = { 2, S_ISGID, 's', S_IEXEC>>3, 'x', '-' };
420: int m7[] = { 1, S_IREAD>>6, 'r', '-' };
421: int m8[] = { 1, S_IWRITE>>6, 'w', '-' };
422: int m9[] = { 2, S_ISVTX, 't', S_IEXEC>>6, 'x', '-' };
423:
424: int *m[] = { m1, m2, m3, m4, m5, m6, m7, m8, m9};
425:
426: pmode(aflag)
427: {
428: register int **mp;
429:
430: flags = aflag;
431: for (mp = &m[0]; mp < &m[sizeof(m)/sizeof(m[0])];)
432: select(*mp++);
433: }
434:
435: select(pairp)
436: register int *pairp;
437: {
438: register int n;
439:
440: n = *pairp++;
441: while (--n>=0 && (flags&*pairp++)==0)
442: pairp++;
443: pputchar(*pairp);
444: }
445:
446: char *
447: makename(dir, file)
448: char *dir, *file;
449: {
450: static char dfile[100];
451: register char *dp, *fp;
452: register int i;
453:
454: dp = dfile;
455: fp = dir;
456: while (*fp)
457: *dp++ = *fp++;
458: *dp++ = '/';
459: fp = file;
460: for (i=0; i<DIRSIZ; i++)
461: *dp++ = *fp++;
462: *dp = 0;
463: return(dfile);
464: }
465:
466: readdir(dir)
467: char *dir;
468: {
469: static struct direct dentry;
470: register int j;
471: register struct lbuf *ep;
472:
473: if ((dirf = fopen(dir, "r")) == NULL) {
474: printf("%s unreadable\n", dir);
475: return;
476: }
477: tblocks = 0;
478: for(;;) {
479: if (fread(&dentry, sizeof(dentry), 1, dirf) != 1)
480: break;
481: if (dentry.d_ino==0 ||
482: aflg==0 && dentry.d_name[0]=='.' && (
483: !Aflg ||
484: dentry.d_name[1]=='\0'
485: || dentry.d_name[1]=='.' && dentry.d_name[2]=='\0'))
486: continue;
487: ep = gstat(makename(dir, dentry.d_name), 0);
488: if (ep==NULL)
489: continue;
490: if (ep->lnum != -1)
491: ep->lnum = dentry.d_ino;
492: for (j=0; j<DIRSIZ; j++)
493: ep->ln.lname[j] = dentry.d_name[j];
494: }
495: fclose(dirf);
496: }
497:
498: struct lbuf *
499: gstat(file, argfl)
500: char *file;
501: {
502: struct stat statb;
503: register struct lbuf *rep;
504: static int nomocore;
505:
506: if (nomocore)
507: return(NULL);
508: rep = (struct lbuf *)malloc(sizeof(struct lbuf));
509: if (rep==NULL) {
510: fprintf(stderr, "ls: out of memory\n");
511: nomocore = 1;
512: return(NULL);
513: }
514: if (lastp >= &flist[NFILES]) {
515: static int msg;
516: lastp--;
517: if (msg==0) {
518: fprintf(stderr, "ls: too many files\n");
519: msg++;
520: }
521: }
522: *lastp++ = rep;
523: rep->lflags = 0;
524: rep->lnum = 0;
525: rep->ltype = '-';
526: if (argfl || statreq) {
527: if (stat(file, &statb)<0) {
528: printf("%s not found\n", file);
529: statb.st_ino = -1;
530: statb.st_size = 0;
531: statb.st_mode = 0;
532: if (argfl) {
533: lastp--;
534: return(0);
535: }
536: }
537: rep->lnum = statb.st_ino;
538: rep->lsize = statb.st_size;
539: switch(statb.st_mode&S_IFMT) {
540:
541: case S_IFDIR:
542: rep->ltype = 'd';
543: break;
544:
545: case S_IFBLK:
546: rep->ltype = 'b';
547: rep->lsize = statb.st_rdev;
548: break;
549:
550: case S_IFCHR:
551: rep->ltype = 'c';
552: rep->lsize = statb.st_rdev;
553: break;
554: }
555: rep->lflags = statb.st_mode & ~S_IFMT;
556: rep->luid = statb.st_uid;
557: rep->lgid = statb.st_gid;
558: rep->lnl = statb.st_nlink;
559: if(uflg)
560: rep->lmtime = statb.st_atime;
561: else if (cflg)
562: rep->lmtime = statb.st_ctime;
563: else
564: rep->lmtime = statb.st_mtime;
565: tblocks += nblock(statb.st_size);
566: }
567: return(rep);
568: }
569:
570: compar(pp1, pp2)
571: struct lbuf **pp1, **pp2;
572: {
573: register struct lbuf *p1, *p2;
574:
575: p1 = *pp1;
576: p2 = *pp2;
577: if (dflg==0) {
578: if (p1->lflags&ISARG && p1->ltype=='d') {
579: if (!(p2->lflags&ISARG && p2->ltype=='d'))
580: return(1);
581: } else {
582: if (p2->lflags&ISARG && p2->ltype=='d')
583: return(-1);
584: }
585: }
586: if (tflg) {
587: if(p2->lmtime == p1->lmtime)
588: return(0);
589: if(p2->lmtime > p1->lmtime)
590: return(rflg);
591: return(-rflg);
592: }
593: return(rflg * strcmp(p1->lflags&ISARG? p1->ln.namep: p1->ln.lname,
594: p2->lflags&ISARG? p2->ln.namep: p2->ln.lname));
595: }
596: pentry(ap)
597: struct lbuf *ap;
598: {
599: struct { char dminor, dmajor;};
600: register t;
601: register struct lbuf *p;
602: register char *cp;
603:
604: p = ap;
605: if (p->lnum == -1)
606: return;
607: column();
608: if (iflg)
609: if (nopad && !lflg)
610: printf("%d ", p->lnum);
611: else
612: printf("%5d ", p->lnum);
613: if (sflg)
614: if (nopad && !lflg)
615: printf("%D ", nblock(p->lsize));
616: else
617: printf("%4D ", nblock(p->lsize));
618: if (lflg) {
619: pputchar(p->ltype);
620: pmode(p->lflags);
621: printf("%2d ", p->lnl);
622: t = p->luid;
623: if(gflg)
624: t = p->lgid;
625: if (nflg == 0 && getname(t, tbuf)==0)
626: printf("%-8.8s", tbuf);
627: else
628: printf("%-8d", t);
629: if (p->ltype=='b' || p->ltype=='c')
630: printf("%3d,%3d", major((int)p->lsize), minor((int)p->lsize));
631: else
632: printf("%7ld", p->lsize);
633: cp = ctime(&p->lmtime);
634: if(p->lmtime < year)
635: printf(" %-7.7s %-4.4s ", cp+4, cp+20); else
636: printf(" %-12.12s ", cp+4);
637: }
638: if (p->lflags&ISARG)
639: printf("%s", p->ln.namep);
640: else
641: printf("%.14s", p->ln.lname);
642: }
643: /* char printf_id[] = "@(#) printf.c:2.2 6/5/79";*/
644: #include "varargs.h"
645: /* This version of printf is compatible with the Version 7 C
646: * printf. The differences are only minor except that this
647: * printf assumes it is to print through pputchar. Version 7
648: * printf is more general (and is much larger) and includes
649: * provisions for floating point.
650: */
651:
652:
653: #define MAXOCT 11 /* Maximum octal digits in a long */
654: #define MAXINT 32767 /* largest normal length positive integer */
655: #define BIG 1000000000 /* largest power of 10 less than an unsigned long */
656: #define MAXDIGS 10 /* number of digits in BIG */
657:
658: static int width, sign, fill;
659:
660: char *b_dconv();
661:
662: printf(va_alist)
663: va_dcl
664: {
665: va_list ap;
666: register char *fmt;
667: char fcode;
668: int prec;
669: int length,mask1,nbits,n;
670: long int mask2, num;
671: register char *bptr;
672: char *ptr;
673: char buf[134];
674:
675: va_start(ap);
676: fmt = va_arg(ap,char *);
677: for (;;) {
678: /* process format string first */
679: while ((fcode = *fmt++)!='%') {
680: /* ordinary (non-%) character */
681: if (fcode=='\0')
682: return;
683: pputchar(fcode);
684: }
685: /* length modifier: -1 for h, 1 for l, 0 for none */
686: length = 0;
687: /* check for a leading - sign */
688: sign = 0;
689: if (*fmt == '-') {
690: sign++;
691: fmt++;
692: }
693: /* a '0' may follow the - sign */
694: /* this is the requested fill character */
695: fill = 1;
696: if (*fmt == '0') {
697: fill--;
698: fmt++;
699: }
700:
701: /* Now comes a digit string which may be a '*' */
702: if (*fmt == '*') {
703: width = va_arg(ap, int);
704: if (width < 0) {
705: width = -width;
706: sign = !sign;
707: }
708: fmt++;
709: }
710: else {
711: width = 0;
712: while (*fmt>='0' && *fmt<='9')
713: width = width * 10 + (*fmt++ - '0');
714: }
715:
716: /* maybe a decimal point followed by more digits (or '*') */
717: if (*fmt=='.') {
718: if (*++fmt == '*') {
719: prec = va_arg(ap, int);
720: fmt++;
721: }
722: else {
723: prec = 0;
724: while (*fmt>='0' && *fmt<='9')
725: prec = prec * 10 + (*fmt++ - '0');
726: }
727: }
728: else
729: prec = -1;
730:
731: /*
732: * At this point, "sign" is nonzero if there was
733: * a sign, "fill" is 0 if there was a leading
734: * zero and 1 otherwise, "width" and "prec"
735: * contain numbers corresponding to the digit
736: * strings before and after the decimal point,
737: * respectively, and "fmt" addresses the next
738: * character after the whole mess. If there was
739: * no decimal point, "prec" will be -1.
740: */
741: switch (*fmt) {
742: case 'L':
743: case 'l':
744: length = 2;
745: /* no break!! */
746: case 'h':
747: case 'H':
748: length--;
749: fmt++;
750: break;
751: }
752:
753: /*
754: * At exit from the following switch, we will
755: * emit the characters starting at "bptr" and
756: * ending at "ptr"-1, unless fcode is '\0'.
757: */
758: switch (fcode = *fmt++) {
759: /* process characters and strings first */
760: case 'c':
761: buf[0] = va_arg(ap, int);
762: ptr = bptr = &buf[0];
763: if (buf[0] != '\0')
764: ptr++;
765: break;
766: case 's':
767: bptr = va_arg(ap,char *);
768: if (bptr==0)
769: bptr = "(null pointer)";
770: if (prec < 0)
771: prec = MAXINT;
772: for (n=0; *bptr++ && n < prec; n++) ;
773: ptr = --bptr;
774: bptr -= n;
775: break;
776: case 'O':
777: length = 1;
778: fcode = 'o';
779: /* no break */
780: case 'o':
781: case 'X':
782: case 'x':
783: if (length > 0)
784: num = va_arg(ap,long);
785: else
786: num = (unsigned)va_arg(ap,int);
787: if (fcode=='o') {
788: mask1 = 0x7;
789: mask2 = 0x1fffffffL;
790: nbits = 3;
791: }
792: else {
793: mask1 = 0xf;
794: mask2 = 0x0fffffffL;
795: nbits = 4;
796: }
797: n = (num!=0);
798: bptr = buf + MAXOCT + 3;
799: /* shift and mask for speed */
800: do
801: if (((int) num & mask1) < 10)
802: *--bptr = ((int) num & mask1) + 060;
803: else
804: *--bptr = ((int) num & mask1) + 0127;
805: while (num = (num >> nbits) & mask2);
806:
807: if (fcode=='o') {
808: if (n)
809: *--bptr = '0';
810: }
811: else
812: if (!sign && fill <= 0) {
813: pputchar('0');
814: pputchar(fcode);
815: width -= 2;
816: }
817: else {
818: *--bptr = fcode;
819: *--bptr = '0';
820: }
821: ptr = buf + MAXOCT + 3;
822: break;
823: case 'D':
824: case 'U':
825: case 'I':
826: length = 1;
827: fcode = fcode + 'a' - 'A';
828: /* no break */
829: case 'd':
830: case 'i':
831: case 'u':
832: if (length > 0)
833: num = va_arg(ap,long);
834: else {
835: n = va_arg(ap,int);
836: if (fcode=='u')
837: num = (unsigned) n;
838: else
839: num = (long) n;
840: }
841: if (n = (fcode != 'u' && num < 0))
842: num = -num;
843: /* now convert to digits */
844: bptr = b_dconv(num, buf);
845: if (n)
846: *--bptr = '-';
847: if (fill == 0)
848: fill = -1;
849: ptr = buf + MAXDIGS + 1;
850: break;
851: default:
852: /* not a control character,
853: * print it.
854: */
855: ptr = bptr = &fcode;
856: ptr++;
857: break;
858: }
859: if (fcode != '\0')
860: b_emit(bptr,ptr);
861: }
862: va_end(ap);
863: }
864:
865: /* b_dconv converts the unsigned long integer "value" to
866: * printable decimal and places it in "buffer", right-justified.
867: * The value returned is the address of the first non-zero character,
868: * or the address of the last character if all are zero.
869: * The result is NOT null terminated, and is MAXDIGS characters long,
870: * starting at buffer[1] (to allow for insertion of a sign).
871: *
872: * This program assumes it is running on 2's complement machine
873: * with reasonable overflow treatment.
874: */
875: char *
876: b_dconv(value, buffer)
877: long value;
878: char *buffer;
879: {
880: register char *bp;
881: register int svalue;
882: int n;
883: long lval;
884:
885: bp = buffer;
886:
887: /* zero is a special case */
888: if (value == 0) {
889: bp += MAXDIGS;
890: *bp = '0';
891: return(bp);
892: }
893:
894: /* develop the leading digit of the value in "n" */
895: n = 0;
896: while (value < 0) {
897: value -= BIG; /* will eventually underflow */
898: n++;
899: }
900: while ((lval = value - BIG) >= 0) {
901: value = lval;
902: n++;
903: }
904:
905: /* stash it in buffer[1] to allow for a sign */
906: bp[1] = n + '0';
907: /*
908: * Now develop the rest of the digits. Since speed counts here,
909: * we do it in two loops. The first gets "value" down until it
910: * is no larger than MAXINT. The second one uses integer divides
911: * rather than long divides to speed it up.
912: */
913: bp += MAXDIGS + 1;
914: while (value > MAXINT) {
915: *--bp = (int)(value % 10) + '0';
916: value /= 10;
917: }
918:
919: /* cannot lose precision */
920: svalue = value;
921: while (svalue > 0) {
922: *--bp = (svalue % 10) + '0';
923: svalue /= 10;
924: }
925:
926: /* fill in intermediate zeroes if needed */
927: if (buffer[1] != '0') {
928: while (bp > buffer + 2)
929: *--bp = '0';
930: --bp;
931: }
932: return(bp);
933: }
934:
935: /*
936: * This program sends string "s" to pputchar. The character after
937: * the end of "s" is given by "send". This allows the size of the
938: * field to be computed; it is stored in "alen". "width" contains the
939: * user specified length. If width<alen, the width will be taken to
940: * be alen. "sign" is zero if the string is to be right-justified
941: * in the field, nonzero if it is to be left-justified. "fill" is
942: * 0 if the string is to be padded with '0', positive if it is to be
943: * padded with ' ', and negative if an initial '-' should appear before
944: * any padding in right-justification (to avoid printing "-3" as
945: * "000-3" where "-0003" was intended).
946: */
947: b_emit(s, send)
948: register char *s;
949: char *send;
950: {
951: char cfill;
952: register int alen;
953: int npad;
954:
955: alen = send - s;
956: if (alen > width)
957: width = alen;
958: cfill = fill>0? ' ': '0';
959:
960: /* we may want to print a leading '-' before anything */
961: if (*s == '-' && fill < 0) {
962: pputchar(*s++);
963: alen--;
964: width--;
965: }
966: npad = width - alen;
967:
968: /* emit any leading pad characters */
969: if (!sign)
970: while (--npad >= 0)
971: pputchar(cfill);
972:
973: /* emit the string itself */
974: while (--alen >= 0)
975: pputchar(*s++);
976:
977: /* emit trailing pad characters */
978: if (sign)
979: while (--npad >= 0)
980: pputchar(cfill);
981: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.