Annotation of src/bin/ls/print.c, Revision 1.30
1.30 ! lukem 1: /* $NetBSD: print.c,v 1.29 2000/06/22 23:42:22 assar Exp $ */
1.13 cgd 2:
1.1 cgd 3: /*
1.11 mycroft 4: * Copyright (c) 1989, 1993, 1994
5: * The Regents of the University of California. All rights reserved.
1.1 cgd 6: *
7: * This code is derived from software contributed to Berkeley by
8: * Michael Fischbein.
9: *
10: * Redistribution and use in source and binary forms, with or without
11: * modification, are permitted provided that the following conditions
12: * are met:
13: * 1. Redistributions of source code must retain the above copyright
14: * notice, this list of conditions and the following disclaimer.
15: * 2. Redistributions in binary form must reproduce the above copyright
16: * notice, this list of conditions and the following disclaimer in the
17: * documentation and/or other materials provided with the distribution.
18: * 3. All advertising materials mentioning features or use of this software
19: * must display the following acknowledgement:
20: * This product includes software developed by the University of
21: * California, Berkeley and its contributors.
22: * 4. Neither the name of the University nor the names of its contributors
23: * may be used to endorse or promote products derived from this software
24: * without specific prior written permission.
25: *
26: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36: * SUCH DAMAGE.
37: */
38:
1.16 christos 39: #include <sys/cdefs.h>
1.1 cgd 40: #ifndef lint
1.13 cgd 41: #if 0
1.14 jtc 42: static char sccsid[] = "@(#)print.c 8.5 (Berkeley) 7/28/94";
1.13 cgd 43: #else
1.30 ! lukem 44: __RCSID("$NetBSD: print.c,v 1.29 2000/06/22 23:42:22 assar Exp $");
1.13 cgd 45: #endif
1.1 cgd 46: #endif /* not lint */
47:
48: #include <sys/param.h>
49: #include <sys/stat.h>
1.11 mycroft 50:
51: #include <err.h>
52: #include <errno.h>
1.5 mycroft 53: #include <fts.h>
1.1 cgd 54: #include <grp.h>
55: #include <pwd.h>
1.11 mycroft 56: #include <stdio.h>
1.5 mycroft 57: #include <stdlib.h>
58: #include <string.h>
1.11 mycroft 59: #include <time.h>
60: #include <tzfile.h>
61: #include <unistd.h>
62: #include <utmp.h>
63:
1.1 cgd 64: #include "ls.h"
1.5 mycroft 65: #include "extern.h"
1.1 cgd 66:
1.30 ! lukem 67: static int printaname(FTSENT *, int, int);
! 68: static void printlink(FTSENT *);
! 69: static void printtime(time_t);
! 70: static int printtype(u_int);
1.5 mycroft 71:
1.20 mycroft 72: static time_t now;
73:
1.5 mycroft 74: #define IS_NOPRINT(p) ((p)->fts_number == NO_PRINT)
75:
76: void
1.30 ! lukem 77: printscol(DISPLAY *dp)
1.1 cgd 78: {
1.11 mycroft 79: FTSENT *p;
1.5 mycroft 80:
81: for (p = dp->list; p; p = p->fts_link) {
82: if (IS_NOPRINT(p))
83: continue;
84: (void)printaname(p, dp->s_inode, dp->s_block);
1.1 cgd 85: (void)putchar('\n');
86: }
87: }
88:
1.5 mycroft 89: void
1.30 ! lukem 90: printlong(DISPLAY *dp)
1.5 mycroft 91: {
1.11 mycroft 92: struct stat *sp;
93: FTSENT *p;
1.5 mycroft 94: NAMES *np;
95: char buf[20];
96:
1.22 mycroft 97: now = time(NULL);
1.20 mycroft 98:
1.5 mycroft 99: if (dp->list->fts_level != FTS_ROOTLEVEL && (f_longform || f_size))
1.24 christos 100: (void)printf("total %llu\n",
1.21 lukem 101: (long long)(howmany(dp->btotal, blocksize)));
1.5 mycroft 102:
103: for (p = dp->list; p; p = p->fts_link) {
104: if (IS_NOPRINT(p))
105: continue;
106: sp = p->fts_statp;
1.1 cgd 107: if (f_inode)
1.23 christos 108: (void)printf("%*lu ", dp->s_inode,
109: (unsigned long)sp->st_ino);
1.1 cgd 110: if (f_size)
1.24 christos 111: (void)printf("%*llu ", dp->s_block,
1.17 thorpej 112: (long long)howmany(sp->st_blocks, blocksize));
1.5 mycroft 113: (void)strmode(sp->st_mode, buf);
114: np = p->fts_pointer;
1.23 christos 115: (void)printf("%s %*lu %-*s %-*s ", buf, dp->s_nlink,
116: (unsigned long)sp->st_nlink, dp->s_user, np->user,
117: dp->s_group, np->group);
1.5 mycroft 118: if (f_flags)
119: (void)printf("%-*s ", dp->s_flags, np->flags);
120: if (S_ISCHR(sp->st_mode) || S_ISBLK(sp->st_mode))
1.18 mycroft 121: (void)printf("%*u, %*u ",
122: dp->s_major, major(sp->st_rdev), dp->s_minor,
123: minor(sp->st_rdev));
1.1 cgd 124: else
1.24 christos 125: (void)printf("%*llu ", dp->s_size,
1.17 thorpej 126: (long long)sp->st_size);
1.1 cgd 127: if (f_accesstime)
1.5 mycroft 128: printtime(sp->st_atime);
1.1 cgd 129: else if (f_statustime)
1.5 mycroft 130: printtime(sp->st_ctime);
1.1 cgd 131: else
1.5 mycroft 132: printtime(sp->st_mtime);
1.28 assar 133: if (f_nonprint)
1.29 assar 134: (void)printescaped(p->fts_name);
1.28 assar 135: else
136: (void)printf("%s", p->fts_name);
137:
1.26 kleink 138: if (f_type || (f_typedir && S_ISDIR(sp->st_mode)))
1.5 mycroft 139: (void)printtype(sp->st_mode);
140: if (S_ISLNK(sp->st_mode))
141: printlink(p);
1.1 cgd 142: (void)putchar('\n');
143: }
144: }
145:
1.5 mycroft 146: void
1.30 ! lukem 147: printcol(DISPLAY *dp)
1.1 cgd 148: {
149: extern int termwidth;
1.5 mycroft 150: static FTSENT **array;
151: static int lastentries = -1;
1.11 mycroft 152: FTSENT *p;
1.16 christos 153: int base, chcnt, col, colwidth, num;
1.15 thorpej 154: int numcols, numrows, row;
1.1 cgd 155:
1.19 lukem 156: colwidth = dp->maxlen;
157: if (f_inode)
158: colwidth += dp->s_inode + 1;
159: if (f_size)
160: colwidth += dp->s_block + 1;
1.26 kleink 161: if (f_type || f_typedir)
1.19 lukem 162: colwidth += 1;
163:
164: colwidth += 1;
165:
166: if (termwidth < 2 * colwidth) {
167: printscol(dp);
168: return;
169: }
170:
1.5 mycroft 171: /*
172: * Have to do random access in the linked list -- build a table
173: * of pointers.
174: */
175: if (dp->entries > lastentries) {
176: lastentries = dp->entries;
177: if ((array =
178: realloc(array, dp->entries * sizeof(FTSENT *))) == NULL) {
1.27 drochner 179: warn(NULL);
1.5 mycroft 180: printscol(dp);
181: }
182: }
183: for (p = dp->list, num = 0; p; p = p->fts_link)
184: if (p->fts_number != NO_PRINT)
185: array[num++] = p;
186:
1.19 lukem 187: numcols = termwidth / colwidth;
188: colwidth = termwidth / numcols; /* spread out if possible */
189: numrows = num / numcols;
190: if (num % numcols)
191: ++numrows;
192:
193: if (dp->list->fts_level != FTS_ROOTLEVEL && (f_longform || f_size))
1.24 christos 194: (void)printf("total %llu\n",
1.21 lukem 195: (long long)(howmany(dp->btotal, blocksize)));
1.19 lukem 196: for (row = 0; row < numrows; ++row) {
197: for (base = row, chcnt = col = 0; col < numcols; ++col) {
198: chcnt = printaname(array[base], dp->s_inode,
199: dp->s_block);
200: if ((base += numrows) >= num)
201: break;
202: while (chcnt++ < colwidth)
1.22 mycroft 203: (void)putchar(' ');
1.19 lukem 204: }
205: (void)putchar('\n');
206: }
207: }
208:
209: void
1.30 ! lukem 210: printacol(DISPLAY *dp)
1.19 lukem 211: {
212: extern int termwidth;
213: FTSENT *p;
214: int chcnt, col, colwidth;
215: int numcols;
216:
1.5 mycroft 217: colwidth = dp->maxlen;
1.1 cgd 218: if (f_inode)
1.5 mycroft 219: colwidth += dp->s_inode + 1;
1.1 cgd 220: if (f_size)
1.5 mycroft 221: colwidth += dp->s_block + 1;
1.26 kleink 222: if (f_type || f_typedir)
1.1 cgd 223: colwidth += 1;
224:
1.15 thorpej 225: colwidth += 1;
226:
1.1 cgd 227: if (termwidth < 2 * colwidth) {
1.5 mycroft 228: printscol(dp);
1.1 cgd 229: return;
230: }
231:
232: numcols = termwidth / colwidth;
1.15 thorpej 233: colwidth = termwidth / numcols; /* spread out if possible */
1.1 cgd 234:
1.5 mycroft 235: if (dp->list->fts_level != FTS_ROOTLEVEL && (f_longform || f_size))
1.24 christos 236: (void)printf("total %llu\n",
1.21 lukem 237: (long long)(howmany(dp->btotal, blocksize)));
1.19 lukem 238: chcnt = col = 0;
239: for (p = dp->list; p; p = p->fts_link) {
240: if (IS_NOPRINT(p))
241: continue;
242: if (col >= numcols) {
243: chcnt = col = 0;
1.22 mycroft 244: (void)putchar('\n');
1.1 cgd 245: }
1.19 lukem 246: chcnt = printaname(p, dp->s_inode, dp->s_block);
247: while (chcnt++ < colwidth)
1.22 mycroft 248: (void)putchar(' ');
1.19 lukem 249: col++;
1.25 kleink 250: }
251: (void)putchar('\n');
252: }
253:
254: void
1.30 ! lukem 255: printstream(DISPLAY *dp)
1.25 kleink 256: {
257: extern int termwidth;
258: FTSENT *p;
259: int col;
260: int extwidth;
261:
262: extwidth = 0;
263: if (f_inode)
264: extwidth += dp->s_inode + 1;
265: if (f_size)
266: extwidth += dp->s_block + 1;
267: if (f_type)
268: extwidth += 1;
269:
270: for (col = 0, p = dp->list; p != NULL; p = p->fts_link) {
271: if (IS_NOPRINT(p))
272: continue;
273: if (col > 0) {
274: (void)putchar(','), col++;
275: if (col + 1 + extwidth + p->fts_namelen >= termwidth)
276: (void)putchar('\n'), col = 0;
277: else
278: (void)putchar(' '), col++;
279: }
280: col += printaname(p, dp->s_inode, dp->s_block);
1.1 cgd 281: }
1.22 mycroft 282: (void)putchar('\n');
1.1 cgd 283: }
284:
285: /*
286: * print [inode] [size] name
1.5 mycroft 287: * return # of characters printed, no trailing characters.
1.1 cgd 288: */
1.5 mycroft 289: static int
1.30 ! lukem 290: printaname(FTSENT *p, int inodefield, int sizefield)
1.1 cgd 291: {
1.5 mycroft 292: struct stat *sp;
1.1 cgd 293: int chcnt;
294:
1.5 mycroft 295: sp = p->fts_statp;
1.1 cgd 296: chcnt = 0;
297: if (f_inode)
1.23 christos 298: chcnt += printf("%*lu ", inodefield, (unsigned long)sp->st_ino);
1.1 cgd 299: if (f_size)
1.24 christos 300: chcnt += printf("%*llu ", sizefield,
1.17 thorpej 301: (long long)howmany(sp->st_blocks, blocksize));
1.29 assar 302: if (f_nonprint)
303: chcnt += printescaped(p->fts_name);
304: else
305: chcnt += printf("%s", p->fts_name);
1.26 kleink 306: if (f_type || (f_typedir && S_ISDIR(sp->st_mode)))
1.5 mycroft 307: chcnt += printtype(sp->st_mode);
308: return (chcnt);
1.1 cgd 309: }
310:
1.5 mycroft 311: static void
1.30 ! lukem 312: printtime(time_t ftime)
1.1 cgd 313: {
314: int i;
1.5 mycroft 315: char *longstring;
1.1 cgd 316:
1.5 mycroft 317: longstring = ctime(&ftime);
1.1 cgd 318: for (i = 4; i < 11; ++i)
319: (void)putchar(longstring[i]);
320:
321: #define SIXMONTHS ((DAYSPERNYEAR / 2) * SECSPERDAY)
322: if (f_sectime)
323: for (i = 11; i < 24; i++)
324: (void)putchar(longstring[i]);
1.20 mycroft 325: else if (ftime + SIXMONTHS > now && ftime - SIXMONTHS < now)
1.1 cgd 326: for (i = 11; i < 16; ++i)
327: (void)putchar(longstring[i]);
328: else {
329: (void)putchar(' ');
330: for (i = 20; i < 24; ++i)
331: (void)putchar(longstring[i]);
332: }
333: (void)putchar(' ');
334: }
335:
1.5 mycroft 336: static int
1.30 ! lukem 337: printtype(u_int mode)
1.1 cgd 338: {
1.11 mycroft 339: switch (mode & S_IFMT) {
1.1 cgd 340: case S_IFDIR:
341: (void)putchar('/');
1.5 mycroft 342: return (1);
1.11 mycroft 343: case S_IFIFO:
344: (void)putchar('|');
345: return (1);
1.1 cgd 346: case S_IFLNK:
347: (void)putchar('@');
1.5 mycroft 348: return (1);
1.1 cgd 349: case S_IFSOCK:
350: (void)putchar('=');
1.12 mycroft 351: return (1);
352: case S_IFWHT:
353: (void)putchar('%');
1.6 jtc 354: return (1);
1.1 cgd 355: }
356: if (mode & (S_IXUSR | S_IXGRP | S_IXOTH)) {
357: (void)putchar('*');
1.5 mycroft 358: return (1);
1.1 cgd 359: }
1.5 mycroft 360: return (0);
1.1 cgd 361: }
362:
1.5 mycroft 363: static void
1.30 ! lukem 364: printlink(FTSENT *p)
1.1 cgd 365: {
366: int lnklen;
1.5 mycroft 367: char name[MAXPATHLEN + 1], path[MAXPATHLEN + 1];
368:
369: if (p->fts_level == FTS_ROOTLEVEL)
370: (void)snprintf(name, sizeof(name), "%s", p->fts_name);
371: else
1.11 mycroft 372: (void)snprintf(name, sizeof(name),
373: "%s/%s", p->fts_parent->fts_accpath, p->fts_name);
374: if ((lnklen = readlink(name, path, sizeof(path) - 1)) == -1) {
1.1 cgd 375: (void)fprintf(stderr, "\nls: %s: %s\n", name, strerror(errno));
376: return;
377: }
378: path[lnklen] = '\0';
1.28 assar 379: (void)printf(" -> ");
380: if (f_nonprint)
381: printescaped(path);
382: else
383: (void)printf("%s", path);
1.1 cgd 384: }
CVSweb <webmaster@jp.NetBSD.org>