print.c revision 61294
167754Smsmith/* 267754Smsmith * Copyright (c) 1989, 1993, 1994 367754Smsmith * The Regents of the University of California. All rights reserved. 477424Smsmith * 5114237Snjl * This code is derived from software contributed to Berkeley by 667754Smsmith * Michael Fischbein. 767754Smsmith * 867754Smsmith * Redistribution and use in source and binary forms, with or without 967754Smsmith * modification, are permitted provided that the following conditions 1067754Smsmith * are met: 1167754Smsmith * 1. Redistributions of source code must retain the above copyright 1267754Smsmith * notice, this list of conditions and the following disclaimer. 13114237Snjl * 2. Redistributions in binary form must reproduce the above copyright 1470243Smsmith * notice, this list of conditions and the following disclaimer in the 1567754Smsmith * documentation and/or other materials provided with the distribution. 1667754Smsmith * 3. All advertising materials mentioning features or use of this software 1767754Smsmith * must display the following acknowledgement: 1867754Smsmith * This product includes software developed by the University of 1967754Smsmith * California, Berkeley and its contributors. 2067754Smsmith * 4. Neither the name of the University nor the names of its contributors 2167754Smsmith * may be used to endorse or promote products derived from this software 2267754Smsmith * without specific prior written permission. 2367754Smsmith * 2467754Smsmith * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2567754Smsmith * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2667754Smsmith * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2767754Smsmith * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2867754Smsmith * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2967754Smsmith * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3067754Smsmith * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3167754Smsmith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3267754Smsmith * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3367754Smsmith * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3467754Smsmith * SUCH DAMAGE. 3567754Smsmith */ 3667754Smsmith 3767754Smsmith#ifndef lint 3867754Smsmith#if 0 3967754Smsmithstatic char sccsid[] = "@(#)print.c 8.4 (Berkeley) 4/17/94"; 4067754Smsmith#else 4167754Smsmithstatic const char rcsid[] = 4267754Smsmith "$FreeBSD: head/bin/ls/print.c 61294 2000-06-05 20:08:50Z ache $"; 4367754Smsmith#endif 4467754Smsmith#endif /* not lint */ 4567754Smsmith 4667754Smsmith#include <sys/param.h> 4767754Smsmith#include <sys/stat.h> 4867754Smsmith 4967754Smsmith#include <err.h> 5067754Smsmith#include <errno.h> 5167754Smsmith#include <fts.h> 5267754Smsmith#include <grp.h> 5367754Smsmith#include <pwd.h> 5467754Smsmith#include <stdio.h> 5567754Smsmith#include <stdlib.h> 5667754Smsmith#include <string.h> 5767754Smsmith#include <time.h> 5867754Smsmith#include <unistd.h> 5967754Smsmith#ifdef COLORLS 6067754Smsmith#include <ctype.h> 6167754Smsmith#include <termcap.h> 6267754Smsmith#include <term.h> /* for tparm */ 6367754Smsmith#include <signal.h> 6467754Smsmith#endif 6567754Smsmith 6667754Smsmith#include "ls.h" 6767754Smsmith#include "extern.h" 6867754Smsmith 6967754Smsmithstatic int printaname __P((FTSENT *, u_long, u_long)); 7067754Smsmithstatic void printlink __P((FTSENT *)); 7167754Smsmithstatic void printtime __P((time_t)); 7267754Smsmithstatic int printtype __P((u_int)); 7367754Smsmith 7467754Smsmith#define IS_NOPRINT(p) ((p)->fts_number == NO_PRINT) 7567754Smsmith 7667754Smsmith#ifdef COLORLS 7767754Smsmith/* Most of these are taken from <sys/stat.h> */ 7867754Smsmithtypedef enum Colors { 7967754Smsmith C_DIR, /* directory */ 8067754Smsmith C_LNK, /* symbolic link */ 8167754Smsmith C_SOCK, /* socket */ 8267754Smsmith C_FIFO, /* pipe */ 8367754Smsmith C_EXEC, /* executable */ 8467754Smsmith C_BLK, /* block special */ 8567754Smsmith C_CHR, /* character special */ 8667754Smsmith C_SUID, /* setuid executable */ 8767754Smsmith C_SGID, /* setgid executable */ 8867754Smsmith C_WSDIR, /* directory writeble to others, with sticky bit */ 8967754Smsmith C_WDIR, /* directory writeble to others, without sticky bit */ 9067754Smsmith C_NUMCOLORS /* just a place-holder */ 9167754Smsmith} Colors ; 9267754Smsmith 9367754Smsmithchar *defcolors = "4x5x2x3x1x464301060203"; 9467754Smsmith 9567754Smsmithstatic int colors[C_NUMCOLORS][2]; 9667754Smsmith#endif 9767754Smsmith 9867754Smsmithvoid 9967754Smsmithprintscol(dp) 10067754Smsmith DISPLAY *dp; 10167754Smsmith{ 10267754Smsmith FTSENT *p; 10367754Smsmith 10467754Smsmith for (p = dp->list; p; p = p->fts_link) { 10567754Smsmith if (IS_NOPRINT(p)) 10667754Smsmith continue; 10767754Smsmith (void)printaname(p, dp->s_inode, dp->s_block); 10867754Smsmith (void)putchar('\n'); 10967754Smsmith } 11067754Smsmith} 11167754Smsmith 11267754Smsmithvoid 11367754Smsmithprintlong(dp) 11467754Smsmith DISPLAY *dp; 11567754Smsmith{ 11667754Smsmith struct stat *sp; 11767754Smsmith FTSENT *p; 11877424Smsmith NAMES *np; 11967754Smsmith char buf[20]; 12067754Smsmith#ifdef COLORLS 12167754Smsmith int color_printed = 0; 12267754Smsmith#endif 12367754Smsmith 12467754Smsmith if (dp->list->fts_level != FTS_ROOTLEVEL && (f_longform || f_size)) 12567754Smsmith (void)printf("total %lu\n", howmany(dp->btotal, blocksize)); 12677424Smsmith 12791116Smsmith for (p = dp->list; p; p = p->fts_link) { 12867754Smsmith if (IS_NOPRINT(p)) 12967754Smsmith continue; 13067754Smsmith sp = p->fts_statp; 13167754Smsmith if (f_inode) 13277424Smsmith (void)printf("%*lu ", dp->s_inode, (u_long)sp->st_ino); 13369746Smsmith if (f_size) 13469746Smsmith (void)printf("%*qd ", 13569746Smsmith dp->s_block, howmany(sp->st_blocks, blocksize)); 13669746Smsmith (void)strmode(sp->st_mode, buf); 13769746Smsmith np = p->fts_pointer; 13869746Smsmith (void)printf("%s %*u %-*s %-*s ", buf, dp->s_nlink, 13969746Smsmith sp->st_nlink, dp->s_user, np->user, dp->s_group, 14069746Smsmith np->group); 14169746Smsmith if (f_flags) 14269746Smsmith (void)printf("%-*s ", dp->s_flags, np->flags); 14369746Smsmith if (S_ISCHR(sp->st_mode) || S_ISBLK(sp->st_mode)) 14469746Smsmith if (minor(sp->st_rdev) > 255 || minor(sp->st_rdev) < 0) 14577424Smsmith (void)printf("%3d, 0x%08x ", 14669746Smsmith major(sp->st_rdev), 14769746Smsmith (u_int)minor(sp->st_rdev)); 14869746Smsmith else 14969746Smsmith (void)printf("%3d, %3d ", 15091116Smsmith major(sp->st_rdev), minor(sp->st_rdev)); 15169746Smsmith else if (dp->bcfile) 15283174Smsmith (void)printf("%*s%*qd ", 15369746Smsmith 8 - dp->s_size, "", dp->s_size, sp->st_size); 15469746Smsmith else 15569746Smsmith (void)printf("%*qd ", dp->s_size, sp->st_size); 15669746Smsmith if (f_accesstime) 15769746Smsmith printtime(sp->st_atime); 15869746Smsmith else if (f_statustime) 15969746Smsmith printtime(sp->st_ctime); 160107325Siwasaki else 16199679Siwasaki printtime(sp->st_mtime); 16299679Siwasaki#ifdef COLORLS 16399679Siwasaki if (f_color) 16499679Siwasaki color_printed = colortype(sp->st_mode); 16599679Siwasaki#endif 16699679Siwasaki if (f_octal || f_octal_escape) (void)prn_octal(p->fts_name); 16799679Siwasaki else (void)printf("%s", p->fts_name); 16899679Siwasaki#ifdef COLORLS 16999679Siwasaki if (f_color && color_printed) 17099679Siwasaki endcolor(); 17199679Siwasaki#endif 17299679Siwasaki if (f_type) 17399679Siwasaki (void)printtype(sp->st_mode); 17469746Smsmith if (S_ISLNK(sp->st_mode)) 17569746Smsmith printlink(p); 17699146Siwasaki (void)putchar('\n'); 17782367Smsmith } 17877424Smsmith} 17977424Smsmith 18069746Smsmithvoid 18169746Smsmithprintcol(dp) 18269746Smsmith DISPLAY *dp; 18369746Smsmith{ 18469746Smsmith extern int termwidth; 18569746Smsmith static FTSENT **array; 18669746Smsmith static int lastentries = -1; 18769746Smsmith FTSENT *p; 18869746Smsmith int base, chcnt, cnt, col, colwidth, num; 18969746Smsmith int endcol, numcols, numrows, row; 19077424Smsmith int tabwidth; 19167754Smsmith 19291116Smsmith if (f_notabs) 19391116Smsmith tabwidth = 1; 19491116Smsmith else 19599679Siwasaki tabwidth = 8; 19667754Smsmith 19767754Smsmith /* 19867754Smsmith * Have to do random access in the linked list -- build a table 19991116Smsmith * of pointers. 20091116Smsmith */ 20167754Smsmith if (dp->entries > lastentries) { 20299679Siwasaki lastentries = dp->entries; 203102550Siwasaki if ((array = 204102550Siwasaki realloc(array, dp->entries * sizeof(FTSENT *))) == NULL) { 20599679Siwasaki warn(NULL); 20667754Smsmith printscol(dp); 20767754Smsmith } 20867754Smsmith } 20967754Smsmith for (p = dp->list, num = 0; p; p = p->fts_link) 21077424Smsmith if (p->fts_number != NO_PRINT) 21167754Smsmith array[num++] = p; 21267754Smsmith 21367754Smsmith colwidth = dp->maxlen; 21467754Smsmith if (f_inode) 21567754Smsmith colwidth += dp->s_inode + 1; 21667754Smsmith if (f_size) 21767754Smsmith colwidth += dp->s_block + 1; 21877424Smsmith if (f_type) 21967754Smsmith colwidth += 1; 22083174Smsmith 22167754Smsmith colwidth = (colwidth + tabwidth) & ~(tabwidth - 1); 22269746Smsmith if (termwidth < 2 * colwidth) { 22367754Smsmith printscol(dp); 22467754Smsmith return; 22591116Smsmith } 22667754Smsmith 22767754Smsmith numcols = termwidth / colwidth; 22867754Smsmith numrows = num / numcols; 22985756Smsmith if (num % numcols) 23067754Smsmith ++numrows; 23167754Smsmith 23267754Smsmith if (dp->list->fts_level != FTS_ROOTLEVEL && (f_longform || f_size)) 23367754Smsmith (void)printf("total %lu\n", howmany(dp->btotal, blocksize)); 23467754Smsmith for (row = 0; row < numrows; ++row) { 23567754Smsmith endcol = colwidth; 23667754Smsmith for (base = row, chcnt = col = 0; col < numcols; ++col) { 23783174Smsmith chcnt += printaname(array[base], dp->s_inode, 23877424Smsmith dp->s_block); 23969746Smsmith if ((base += numrows) >= num) 24069746Smsmith break; 24167754Smsmith#ifdef COLORLS 24267754Smsmith /* 24399146Siwasaki * some terminals get confused if we mix tabs 24499146Siwasaki * with color sequences 24567754Smsmith */ 24677424Smsmith if (f_color) 24777424Smsmith while ((cnt = (chcnt + 1)) <= endcol) { 24867754Smsmith (void)putchar(' '); 24977424Smsmith chcnt = cnt; 25077424Smsmith } 25177424Smsmith else 25267754Smsmith#endif 25367754Smsmith while ((cnt = ((chcnt + tabwidth) & ~(tabwidth - 1))) 25467754Smsmith <= endcol){ 25567754Smsmith (void)putchar(f_notabs ? ' ' : '\t'); 25667754Smsmith chcnt = cnt; 25785756Smsmith } 25877424Smsmith endcol += colwidth; 25969746Smsmith } 26069746Smsmith (void)putchar('\n'); 26167754Smsmith } 26267754Smsmith} 26367754Smsmith 26467754Smsmith/* 26567754Smsmith * print [inode] [size] name 26667754Smsmith * return # of characters printed, no trailing characters. 26767754Smsmith */ 26867754Smsmithstatic int 26991116Smsmithprintaname(p, inodefield, sizefield) 27067754Smsmith FTSENT *p; 27191116Smsmith u_long sizefield, inodefield; 27291116Smsmith{ 27367754Smsmith struct stat *sp; 27467754Smsmith int chcnt; 27567754Smsmith#ifdef COLORLS 27691116Smsmith int color_printed = 0; 27767754Smsmith#endif 27891116Smsmith 27999679Siwasaki sp = p->fts_statp; 28091116Smsmith chcnt = 0; 28167754Smsmith if (f_inode) 28267754Smsmith chcnt += printf("%*lu ", (int)inodefield, (u_long)sp->st_ino); 28399679Siwasaki if (f_size) 28467754Smsmith chcnt += printf("%*qd ", 28567754Smsmith (int)sizefield, howmany(sp->st_blocks, blocksize)); 28667754Smsmith#ifdef COLORLS 287107325Siwasaki if (f_color) 28867754Smsmith color_printed = colortype(sp->st_mode); 28982367Smsmith#endif 29067754Smsmith chcnt += (f_octal || f_octal_escape) ? prn_octal(p->fts_name) 29169746Smsmith : printf("%s", p->fts_name); 29269746Smsmith#ifdef COLORLS 29367754Smsmith if (f_color && color_printed) 29467754Smsmith endcolor(); 295107325Siwasaki#endif 29667754Smsmith if (f_type) 29767754Smsmith chcnt += printtype(sp->st_mode); 29867754Smsmith return (chcnt); 29967754Smsmith} 30067754Smsmith 30185756Smsmithstatic void 30267754Smsmithprinttime(ftime) 30367754Smsmith time_t ftime; 30467754Smsmith{ 30567754Smsmith int i; 30677424Smsmith char longstring[80]; 30767754Smsmith static time_t now; 30867754Smsmith 30967754Smsmith if (now == 0) 31067754Smsmith now = time(NULL); 311100966Siwasaki 31267754Smsmith strftime(longstring, sizeof(longstring), "%c", localtime(&ftime)); 31367754Smsmith for (i = 4; i < 11; ++i) 31467754Smsmith (void)putchar(longstring[i]); 31599146Siwasaki 31682367Smsmith#define SIXMONTHS ((365 / 2) * 86400) 31767754Smsmith if (f_sectime) 31867754Smsmith for (i = 11; i < 24; i++) 31967754Smsmith (void)putchar(longstring[i]); 32091116Smsmith else if (ftime + SIXMONTHS > now && ftime < now + SIXMONTHS) 32199679Siwasaki for (i = 11; i < 16; ++i) 32277424Smsmith (void)putchar(longstring[i]); 32367754Smsmith else { 32469746Smsmith (void)putchar(' '); 32567754Smsmith for (i = 20; i < 24; ++i) 32667754Smsmith (void)putchar(longstring[i]); 32791116Smsmith } 32867754Smsmith (void)putchar(' '); 32991116Smsmith} 33091116Smsmith 33191116Smsmithstatic int 33267754Smsmithprinttype(mode) 33367754Smsmith u_int mode; 33482367Smsmith{ 33582367Smsmith switch (mode & S_IFMT) { 33691116Smsmith case S_IFDIR: 33767754Smsmith (void)putchar('/'); 33869746Smsmith return (1); 33967754Smsmith case S_IFIFO: 34067754Smsmith (void)putchar('|'); 34167754Smsmith return (1); 34267754Smsmith case S_IFLNK: 34369746Smsmith (void)putchar('@'); 34467754Smsmith return (1); 34567754Smsmith case S_IFSOCK: 34667754Smsmith (void)putchar('='); 34767754Smsmith return (1); 34869746Smsmith case S_IFWHT: 34970243Smsmith (void)putchar('%'); 35070243Smsmith return (1); 35169746Smsmith } 35267754Smsmith if (mode & (S_IXUSR | S_IXGRP | S_IXOTH)) { 35367754Smsmith (void)putchar('*'); 35491116Smsmith return (1); 35567754Smsmith } 35699679Siwasaki return (0); 35791116Smsmith} 35891116Smsmith 35991116Smsmith#ifdef COLORLS 36091116Smsmithint putch(c) 36191116Smsmith int c; 36291116Smsmith{ 36391116Smsmith return putc(c, stdout); 36491116Smsmith} 36591116Smsmith 36691116Smsmith 36799679Siwasakivoid 36891116Smsmithprintcolor(c) 36991116Smsmith Colors c; 37071867Smsmith{ 37171867Smsmith char *ansiseq; 37271867Smsmith 37391116Smsmith if (colors[c][0] != -1) { 37471867Smsmith ansiseq = tparm(ansi_fgcol, colors[c][0]); 37591116Smsmith if (ansiseq) 37667754Smsmith tputs(ansiseq, 1, putch); 377107325Siwasaki } 37867754Smsmith 37991116Smsmith if (colors[c][1] != -1) { 38067754Smsmith ansiseq = tparm(ansi_bgcol, colors[c][1]); 38169746Smsmith if (ansiseq) 38267754Smsmith tputs(ansiseq, 1, putch); 38367754Smsmith } 384107325Siwasaki} 38569746Smsmith 38669746Smsmithvoid 38767754Smsmithendcolor() 38869746Smsmith{ 38967754Smsmith tputs(ansi_coloff, 1, putch); 39067754Smsmith} 39177424Smsmith 39267754Smsmithint 39367754Smsmithcolortype(mode) 39467754Smsmith mode_t mode; 39567754Smsmith{ 39667754Smsmith switch(mode & S_IFMT) { 39777424Smsmith case S_IFDIR: 39877424Smsmith if (mode & S_IWOTH) 39977424Smsmith if (mode & S_ISTXT) 40067754Smsmith printcolor(C_WSDIR); 40169746Smsmith else 40267754Smsmith printcolor(C_WDIR); 40367754Smsmith else 40469746Smsmith printcolor(C_DIR); 40567754Smsmith return(1); 40669746Smsmith case S_IFLNK: 40769746Smsmith printcolor(C_LNK); 40869746Smsmith return(1); 40969746Smsmith case S_IFSOCK: 41069746Smsmith printcolor(C_SOCK); 41169746Smsmith return(1); 41269746Smsmith case S_IFIFO: 413107325Siwasaki printcolor(C_FIFO); 41477424Smsmith return(1); 41567754Smsmith case S_IFBLK: 41669746Smsmith printcolor(C_BLK); 41767754Smsmith return(1); 41867754Smsmith case S_IFCHR: 41999679Siwasaki printcolor(C_CHR); 42099679Siwasaki return(1); 42199679Siwasaki } 42299679Siwasaki if (mode & (S_IXUSR | S_IXGRP | S_IXOTH)) { 42369746Smsmith if (mode & S_ISUID) 42467754Smsmith printcolor(C_SUID); 42567754Smsmith else if (mode & S_ISGID) 42669746Smsmith printcolor(C_SGID); 42769746Smsmith else 42869746Smsmith printcolor(C_EXEC); 42977424Smsmith return(1); 43069746Smsmith } 43169746Smsmith return(0); 43269746Smsmith} 43369746Smsmith 43467754Smsmithvoid 435104470Siwasakiparsecolors(cs) 436104470Siwasakichar *cs; 437104470Siwasaki{ 438104470Siwasaki int i, j, len; 43969746Smsmith char c[2]; 44069746Smsmith if (cs == NULL) cs = ""; /* LSCOLORS not set */ 44169746Smsmith len = strlen(cs); 44269746Smsmith for (i = 0 ; i < C_NUMCOLORS ; i++) { 44369746Smsmith if (len <= 2*i) { 44469746Smsmith c[0] = defcolors[2*i]; 44569746Smsmith c[1] = defcolors[2*i+1]; 44669746Smsmith } 44769746Smsmith else { 44867754Smsmith c[0] = cs[2*i]; 44967754Smsmith c[1] = cs[2*i+1]; 45067754Smsmith } 45167754Smsmith for (j = 0 ; j < 2 ; j++) { 45269746Smsmith if ((c[j] < '0' || c[j] > '7') && 45367754Smsmith tolower((unsigned char)c[j]) != 'x') { 45467754Smsmith fprintf(stderr, 45567754Smsmith "error: invalid character '%c' in LSCOLORS env var\n", 45667754Smsmith c[j]); 45767754Smsmith c[j] = defcolors[2*i+j]; 45867754Smsmith } 45969746Smsmith if (c[j] == 'x') 46067754Smsmith colors[i][j] = -1; 46167754Smsmith else 46267754Smsmith colors[i][j] = c[j]-'0'; 46367754Smsmith } 46467754Smsmith } 46567754Smsmith} 46669746Smsmith 46769746Smsmithvoid colorquit(sig) 46867754Smsmith int sig; 46969746Smsmith{ 47069746Smsmith endcolor(); 47169746Smsmith fflush(stdout); 47269746Smsmith 47369746Smsmith (void) signal(sig, SIG_DFL); 47467754Smsmith (void) kill(getpid(), sig); 47567754Smsmith} 47667754Smsmith#endif /*COLORLS*/ 47769746Smsmith 47869746Smsmithstatic void 47969746Smsmithprintlink(p) 48071867Smsmith FTSENT *p; 48171867Smsmith{ 48271867Smsmith int lnklen; 48371867Smsmith char name[MAXPATHLEN + 1], path[MAXPATHLEN + 1]; 48471867Smsmith 485104470Siwasaki if (p->fts_level == FTS_ROOTLEVEL) 48671867Smsmith (void)snprintf(name, sizeof(name), "%s", p->fts_name); 487104470Siwasaki else 48871867Smsmith (void)snprintf(name, sizeof(name), 48971867Smsmith "%s/%s", p->fts_parent->fts_accpath, p->fts_name); 49071867Smsmith if ((lnklen = readlink(name, path, sizeof(path) - 1)) == -1) { 49171867Smsmith (void)fprintf(stderr, "\nls: %s: %s\n", name, strerror(errno)); 49291116Smsmith return; 49382367Smsmith } 494104470Siwasaki path[lnklen] = '\0'; 49571867Smsmith if (f_octal || f_octal_escape) { 49671867Smsmith (void)printf(" -> "); 49771867Smsmith (void)prn_octal(path); 49871867Smsmith } 49971867Smsmith else (void)printf(" -> %s", path); 50071867Smsmith} 50171867Smsmith