]> git.saurik.com Git - apple/network_cmds.git/blame_incremental - ftpd.tproj/print.c
network_cmds-85.tar.gz
[apple/network_cmds.git] / ftpd.tproj / print.c
... / ...
CommitLineData
1/*
2 * Copyright (c) 1989, 1993, 1994
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Michael Fischbein.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 */
36
37#ifndef lint
38#if 0
39static char sccsid[] = "@(#)print.c 8.4 (Berkeley) 4/17/94";
40#else
41static const char rcsid[] =
42 "$FreeBSD: src/bin/ls/print.c,v 1.38 2001/03/21 15:14:47 ache Exp $";
43#endif
44#endif /* not lint */
45
46#include <sys/param.h>
47#include <sys/stat.h>
48
49#include <err.h>
50#include <errno.h>
51#include <fts.h>
52#include <grp.h>
53//#include <langinfo.h>
54#include <pwd.h>
55#include <stdio.h>
56#include <stdlib.h>
57#include <string.h>
58#include <time.h>
59#include <unistd.h>
60#ifdef COLORLS
61#include <ctype.h>
62#include <termcap.h>
63#include <signal.h>
64#endif
65
66#include "ls.h"
67#include "ls_extern.h"
68
69static int printaname __P((FTSENT *, u_long, u_long));
70static void printlink __P((FTSENT *));
71static void printtime __P((time_t));
72static int printtype __P((u_int));
73#ifdef COLORLS
74static void endcolor __P((int));
75static int colortype __P((mode_t));
76#endif
77
78#define IS_NOPRINT(p) ((p)->fts_number == NO_PRINT)
79
80#ifdef COLORLS
81/* Most of these are taken from <sys/stat.h> */
82typedef enum Colors {
83 C_DIR, /* directory */
84 C_LNK, /* symbolic link */
85 C_SOCK, /* socket */
86 C_FIFO, /* pipe */
87 C_EXEC, /* executable */
88 C_BLK, /* block special */
89 C_CHR, /* character special */
90 C_SUID, /* setuid executable */
91 C_SGID, /* setgid executable */
92 C_WSDIR, /* directory writeble to others, with sticky bit */
93 C_WDIR, /* directory writeble to others, without sticky bit */
94 C_NUMCOLORS /* just a place-holder */
95} Colors ;
96
97char *defcolors = "4x5x2x3x1x464301060203";
98
99static int colors[C_NUMCOLORS][2];
100#endif
101
102void
103printscol(dp)
104 DISPLAY *dp;
105{
106 FTSENT *p;
107
108 for (p = dp->list; p; p = p->fts_link) {
109 if (IS_NOPRINT(p))
110 continue;
111 (void)printaname(p, dp->s_inode, dp->s_block);
112 (void)putchar('\n');
113 }
114}
115
116/*
117 * print name in current style
118 */
119static int
120printname(name)
121 const char *name;
122{
123 if (f_octal || f_octal_escape)
124 return prn_octal(name);
125 else if (f_nonprint)
126 return prn_printable(name);
127 else
128 return printf("%s", name);
129}
130
131void
132printlong(dp)
133 DISPLAY *dp;
134{
135 struct stat *sp;
136 FTSENT *p;
137 NAMES *np;
138 char buf[20];
139#ifdef COLORLS
140 int color_printed = 0;
141#endif
142
143 if (dp->list->fts_level != FTS_ROOTLEVEL && (f_longform || f_size))
144 (void)printf("total %lu\n", howmany(dp->btotal, blocksize));
145
146 for (p = dp->list; p; p = p->fts_link) {
147 if (IS_NOPRINT(p))
148 continue;
149 sp = p->fts_statp;
150 if (f_inode)
151 (void)printf("%*lu ", dp->s_inode, (u_long)sp->st_ino);
152 if (f_size)
153 (void)printf("%*qd ",
154 dp->s_block, howmany(sp->st_blocks, blocksize));
155 (void)strmode(sp->st_mode, buf);
156 np = p->fts_pointer;
157 (void)printf("%s %*u %-*s %-*s ", buf, dp->s_nlink,
158 sp->st_nlink, dp->s_user, np->user, dp->s_group,
159 np->group);
160 if (f_flags)
161 (void)printf("%-*s ", dp->s_flags, np->flags);
162 if (S_ISCHR(sp->st_mode) || S_ISBLK(sp->st_mode))
163 if (minor(sp->st_rdev) > 255 || minor(sp->st_rdev) < 0)
164 (void)printf("%3d, 0x%08x ",
165 major(sp->st_rdev),
166 (u_int)minor(sp->st_rdev));
167 else
168 (void)printf("%3d, %3d ",
169 major(sp->st_rdev), minor(sp->st_rdev));
170 else if (dp->bcfile)
171 (void)printf("%*s%*qd ",
172 8 - dp->s_size, "", dp->s_size, sp->st_size);
173 else
174 (void)printf("%*qd ", dp->s_size, sp->st_size);
175 if (f_accesstime)
176 printtime(sp->st_atime);
177 else if (f_statustime)
178 printtime(sp->st_ctime);
179 else
180 printtime(sp->st_mtime);
181#ifdef COLORLS
182 if (f_color)
183 color_printed = colortype(sp->st_mode);
184#endif
185 (void)printname(p->fts_name);
186#ifdef COLORLS
187 if (f_color && color_printed)
188 endcolor(0);
189#endif
190 if (f_type)
191 (void)printtype(sp->st_mode);
192 if (S_ISLNK(sp->st_mode))
193 printlink(p);
194 (void)putchar('\n');
195 }
196}
197
198void
199printcol(dp)
200 DISPLAY *dp;
201{
202 extern int termwidth;
203 static FTSENT **array;
204 static int lastentries = -1;
205 FTSENT *p;
206 int base, chcnt, cnt, col, colwidth, num;
207 int endcol, numcols, numrows, row;
208 int tabwidth;
209
210 if (f_notabs)
211 tabwidth = 1;
212 else
213 tabwidth = 8;
214
215 /*
216 * Have to do random access in the linked list -- build a table
217 * of pointers.
218 */
219 if (dp->entries > lastentries) {
220 lastentries = dp->entries;
221 if ((array =
222 realloc(array, dp->entries * sizeof(FTSENT *))) == NULL) {
223 warn(NULL);
224 printscol(dp);
225 }
226 }
227 for (p = dp->list, num = 0; p; p = p->fts_link)
228 if (p->fts_number != NO_PRINT)
229 array[num++] = p;
230
231 colwidth = dp->maxlen;
232 if (f_inode)
233 colwidth += dp->s_inode + 1;
234 if (f_size)
235 colwidth += dp->s_block + 1;
236 if (f_type)
237 colwidth += 1;
238
239 colwidth = (colwidth + tabwidth) & ~(tabwidth - 1);
240 if (termwidth < 2 * colwidth) {
241 printscol(dp);
242 return;
243 }
244
245 numcols = termwidth / colwidth;
246 numrows = num / numcols;
247 if (num % numcols)
248 ++numrows;
249
250 if (dp->list->fts_level != FTS_ROOTLEVEL && (f_longform || f_size))
251 (void)printf("total %lu\n", howmany(dp->btotal, blocksize));
252 for (row = 0; row < numrows; ++row) {
253 endcol = colwidth;
254 for (base = row, chcnt = col = 0; col < numcols; ++col) {
255 chcnt += printaname(array[base], dp->s_inode,
256 dp->s_block);
257 if ((base += numrows) >= num)
258 break;
259 while ((cnt = ((chcnt + tabwidth) & ~(tabwidth - 1)))
260 <= endcol){
261 (void)putchar(f_notabs ? ' ' : '\t');
262 chcnt = cnt;
263 }
264 endcol += colwidth;
265 }
266 (void)putchar('\n');
267 }
268}
269
270/*
271 * print [inode] [size] name
272 * return # of characters printed, no trailing characters.
273 */
274static int
275printaname(p, inodefield, sizefield)
276 FTSENT *p;
277 u_long sizefield, inodefield;
278{
279 struct stat *sp;
280 int chcnt;
281#ifdef COLORLS
282 int color_printed = 0;
283#endif
284
285 sp = p->fts_statp;
286 chcnt = 0;
287 if (f_inode)
288 chcnt += printf("%*lu ", (int)inodefield, (u_long)sp->st_ino);
289 if (f_size)
290 chcnt += printf("%*qd ",
291 (int)sizefield, howmany(sp->st_blocks, blocksize));
292#ifdef COLORLS
293 if (f_color)
294 color_printed = colortype(sp->st_mode);
295#endif
296 chcnt += printname(p->fts_name);
297#ifdef COLORLS
298 if (f_color && color_printed)
299 endcolor(0);
300#endif
301 if (f_type)
302 chcnt += printtype(sp->st_mode);
303 return (chcnt);
304}
305
306static void
307printtime(ftime)
308 time_t ftime;
309{
310 char longstring[80];
311 static time_t now;
312 const char *format;
313 static int d_first = -1;
314
315 if (d_first < 0)
316#if defined(HAVE_LANGINFO)
317 d_first = (*nl_langinfo(D_MD_ORDER) == 'd');
318#else
319 d_first = 0;
320#endif
321 if (now == 0)
322 now = time(NULL);
323
324#define SIXMONTHS ((365 / 2) * 86400)
325 if (f_sectime)
326 /* mmm dd hh:mm:ss yyyy || dd mmm hh:mm:ss yyyy */
327 format = d_first ? "%e %b %T %Y " : "%b %e %T %Y ";
328 else if (ftime + SIXMONTHS > now && ftime < now + SIXMONTHS)
329 /* mmm dd hh:mm || dd mmm hh:mm */
330 format = d_first ? "%e %b %R " : "%b %e %R ";
331 else
332 /* mmm dd yyyy || dd mmm yyyy */
333 format = d_first ? "%e %b %Y " : "%b %e %Y ";
334 strftime(longstring, sizeof(longstring), format, localtime(&ftime));
335 fputs(longstring, stdout);
336}
337
338static int
339printtype(mode)
340 u_int mode;
341{
342 switch (mode & S_IFMT) {
343 case S_IFDIR:
344 (void)putchar('/');
345 return (1);
346 case S_IFIFO:
347 (void)putchar('|');
348 return (1);
349 case S_IFLNK:
350 (void)putchar('@');
351 return (1);
352 case S_IFSOCK:
353 (void)putchar('=');
354 return (1);
355 case S_IFWHT:
356 (void)putchar('%');
357 return (1);
358 }
359 if (mode & (S_IXUSR | S_IXGRP | S_IXOTH)) {
360 (void)putchar('*');
361 return (1);
362 }
363 return (0);
364}
365
366#ifdef COLORLS
367static int
368putch(c)
369 int c;
370{
371 (void) putchar(c);
372 return 0;
373}
374
375static int
376writech(c)
377 int c;
378{
379 char tmp = c;
380
381 (void) write(STDOUT_FILENO, &tmp, 1);
382 return 0;
383}
384
385static void
386printcolor(c)
387 Colors c;
388{
389 char *ansiseq;
390
391 if (colors[c][0] != -1) {
392 ansiseq = tgoto(ansi_fgcol, 0, colors[c][0]);
393 if (ansiseq)
394 tputs(ansiseq, 1, putch);
395 }
396
397 if (colors[c][1] != -1) {
398 ansiseq = tgoto(ansi_bgcol, 0, colors[c][1]);
399 if (ansiseq)
400 tputs(ansiseq, 1, putch);
401 }
402}
403
404static void
405endcolor(sig)
406 int sig;
407{
408 tputs(ansi_coloff, 1, sig ? writech : putch);
409}
410
411static int
412colortype(mode)
413 mode_t mode;
414{
415 switch(mode & S_IFMT) {
416 case S_IFDIR:
417 if (mode & S_IWOTH)
418 if (mode & S_ISTXT)
419 printcolor(C_WSDIR);
420 else
421 printcolor(C_WDIR);
422 else
423 printcolor(C_DIR);
424 return(1);
425 case S_IFLNK:
426 printcolor(C_LNK);
427 return(1);
428 case S_IFSOCK:
429 printcolor(C_SOCK);
430 return(1);
431 case S_IFIFO:
432 printcolor(C_FIFO);
433 return(1);
434 case S_IFBLK:
435 printcolor(C_BLK);
436 return(1);
437 case S_IFCHR:
438 printcolor(C_CHR);
439 return(1);
440 }
441 if (mode & (S_IXUSR | S_IXGRP | S_IXOTH)) {
442 if (mode & S_ISUID)
443 printcolor(C_SUID);
444 else if (mode & S_ISGID)
445 printcolor(C_SGID);
446 else
447 printcolor(C_EXEC);
448 return(1);
449 }
450 return(0);
451}
452
453void
454parsecolors(cs)
455char *cs;
456{
457 int i, j, len;
458 char c[2];
459
460 if (cs == NULL) cs = ""; /* LSCOLORS not set */
461 len = strlen(cs);
462 for (i = 0 ; i < C_NUMCOLORS ; i++) {
463 if (len <= 2*i) {
464 c[0] = defcolors[2*i];
465 c[1] = defcolors[2*i+1];
466 }
467 else {
468 c[0] = cs[2*i];
469 c[1] = cs[2*i+1];
470 }
471 for (j = 0 ; j < 2 ; j++) {
472 if ((c[j] < '0' || c[j] > '7') &&
473 tolower((unsigned char)c[j]) != 'x') {
474 fprintf(stderr,
475 "error: invalid character '%c' in LSCOLORS env var\n",
476 c[j]);
477 c[j] = defcolors[2*i+j];
478 }
479 if (tolower((unsigned char)c[j]) == 'x')
480 colors[i][j] = -1;
481 else
482 colors[i][j] = c[j]-'0';
483 }
484 }
485}
486
487void
488colorquit(sig)
489 int sig;
490{
491 endcolor(sig);
492
493 (void) signal(sig, SIG_DFL);
494 (void) kill(getpid(), sig);
495}
496#endif /*COLORLS*/
497
498static void
499printlink(p)
500 FTSENT *p;
501{
502 int lnklen;
503 char name[MAXPATHLEN + 1], path[MAXPATHLEN + 1];
504
505 if (p->fts_level == FTS_ROOTLEVEL)
506 (void)snprintf(name, sizeof(name), "%s", p->fts_name);
507 else
508 (void)snprintf(name, sizeof(name),
509 "%s/%s", p->fts_parent->fts_accpath, p->fts_name);
510 if ((lnklen = readlink(name, path, sizeof(path) - 1)) == -1) {
511 (void)fprintf(stderr, "\nls: %s: %s\n", name, strerror(errno));
512 return;
513 }
514 path[lnklen] = '\0';
515 (void)printf(" -> ");
516 printname(path);
517}