print.c revision 90150
11556Srgrimes/* 21556Srgrimes * Copyright (c) 1989, 1993, 1994 31556Srgrimes * The Regents of the University of California. All rights reserved. 41556Srgrimes * 51556Srgrimes * This code is derived from software contributed to Berkeley by 61556Srgrimes * Michael Fischbein. 71556Srgrimes * 81556Srgrimes * Redistribution and use in source and binary forms, with or without 91556Srgrimes * modification, are permitted provided that the following conditions 101556Srgrimes * are met: 111556Srgrimes * 1. Redistributions of source code must retain the above copyright 121556Srgrimes * notice, this list of conditions and the following disclaimer. 131556Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 141556Srgrimes * notice, this list of conditions and the following disclaimer in the 151556Srgrimes * documentation and/or other materials provided with the distribution. 161556Srgrimes * 3. All advertising materials mentioning features or use of this software 171556Srgrimes * must display the following acknowledgement: 181556Srgrimes * This product includes software developed by the University of 191556Srgrimes * California, Berkeley and its contributors. 201556Srgrimes * 4. Neither the name of the University nor the names of its contributors 211556Srgrimes * may be used to endorse or promote products derived from this software 221556Srgrimes * without specific prior written permission. 231556Srgrimes * 241556Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 251556Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 261556Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 271556Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 281556Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 291556Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 301556Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 311556Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 321556Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 331556Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 341556Srgrimes * SUCH DAMAGE. 351556Srgrimes */ 361556Srgrimes 371556Srgrimes#ifndef lint 3827967Ssteve#if 0 3927967Sstevestatic char sccsid[] = "@(#)print.c 8.4 (Berkeley) 4/17/94"; 4027967Ssteve#else 4127958Sstevestatic const char rcsid[] = 4250471Speter "$FreeBSD: head/bin/ls/print.c 90150 2002-02-03 19:11:32Z markm $"; 4327967Ssteve#endif 441556Srgrimes#endif /* not lint */ 451556Srgrimes 461556Srgrimes#include <sys/param.h> 471556Srgrimes#include <sys/stat.h> 481556Srgrimes 491556Srgrimes#include <err.h> 501556Srgrimes#include <errno.h> 511556Srgrimes#include <fts.h> 521556Srgrimes#include <grp.h> 5388591Sjoe#include <math.h> 5474566Sache#include <langinfo.h> 551556Srgrimes#include <pwd.h> 561556Srgrimes#include <stdio.h> 571556Srgrimes#include <stdlib.h> 581556Srgrimes#include <string.h> 591556Srgrimes#include <unistd.h> 6061294Sache#ifdef COLORLS 6161294Sache#include <ctype.h> 6261294Sache#include <termcap.h> 6361294Sache#include <signal.h> 6461294Sache#endif 651556Srgrimes 661556Srgrimes#include "ls.h" 671556Srgrimes#include "extern.h" 681556Srgrimes 6990110Simpstatic int printaname(FTSENT *, u_long, u_long); 7090110Simpstatic void printlink(FTSENT *); 7190110Simpstatic void printtime(time_t); 7290110Simpstatic int printtype(u_int); 7390110Simpstatic void printsize(size_t, off_t); 7461321Sache#ifdef COLORLS 7590110Simpstatic void endcolor(int); 7690110Simpstatic int colortype(mode_t); 7761321Sache#endif 781556Srgrimes 791556Srgrimes#define IS_NOPRINT(p) ((p)->fts_number == NO_PRINT) 801556Srgrimes 8188591Sjoe#define KILO_SZ(n) (n) 8288591Sjoe#define MEGA_SZ(n) ((n) * (n)) 8388591Sjoe#define GIGA_SZ(n) ((n) * (n) * (n)) 8488591Sjoe#define TERA_SZ(n) ((n) * (n) * (n) * (n)) 8588591Sjoe#define PETA_SZ(n) ((n) * (n) * (n) * (n) * (n)) 8688591Sjoe 8788591Sjoe#define KILO_2_SZ (KILO_SZ(1024ULL)) 8888591Sjoe#define MEGA_2_SZ (MEGA_SZ(1024ULL)) 8988591Sjoe#define GIGA_2_SZ (GIGA_SZ(1024ULL)) 9088591Sjoe#define TERA_2_SZ (TERA_SZ(1024ULL)) 9188591Sjoe#define PETA_2_SZ (PETA_SZ(1024ULL)) 9288591Sjoe 9390150Smarkmstatic unsigned long long vals_base2[] = {1, KILO_2_SZ, MEGA_2_SZ, GIGA_2_SZ, TERA_2_SZ, PETA_2_SZ}; 9488591Sjoe 9588602Sjoetypedef enum { 9688602Sjoe NONE, KILO, MEGA, GIGA, TERA, PETA, UNIT_MAX 9788602Sjoe} unit_t; 9890110Simpstatic unit_t unit_adjust(off_t *); 9988591Sjoe 10090150Smarkmstatic int unitp[] = {NONE, KILO, MEGA, GIGA, TERA, PETA}; 10188591Sjoe 10261268Sjoe#ifdef COLORLS 10361178Sjoe/* Most of these are taken from <sys/stat.h> */ 10461178Sjoetypedef enum Colors { 10588602Sjoe C_DIR, /* directory */ 10688602Sjoe C_LNK, /* symbolic link */ 10788602Sjoe C_SOCK, /* socket */ 10888602Sjoe C_FIFO, /* pipe */ 10988602Sjoe C_EXEC, /* executable */ 11088602Sjoe C_BLK, /* block special */ 11188602Sjoe C_CHR, /* character special */ 11288602Sjoe C_SUID, /* setuid executable */ 11388602Sjoe C_SGID, /* setgid executable */ 11488602Sjoe C_WSDIR, /* directory writeble to others, with sticky 11588602Sjoe * bit */ 11688602Sjoe C_WDIR, /* directory writeble to others, without 11788602Sjoe * sticky bit */ 11888602Sjoe C_NUMCOLORS /* just a place-holder */ 11988586Sjoe} Colors; 12061178Sjoe 12190150Smarkmstatic const char *defcolors = "exfxcxdxbxegedabagacad"; 12261178Sjoe 12388583Sjoe/* colors for file types */ 12488583Sjoestatic struct { 12588586Sjoe int num[2]; 12688586Sjoe int bold; 12788583Sjoe} colors[C_NUMCOLORS]; 12861268Sjoe#endif 12961178Sjoe 1301556Srgrimesvoid 13190110Simpprintscol(DISPLAY *dp) 1321556Srgrimes{ 13388594Sjoe FTSENT *p; 1341556Srgrimes 1351556Srgrimes for (p = dp->list; p; p = p->fts_link) { 1361556Srgrimes if (IS_NOPRINT(p)) 1371556Srgrimes continue; 1381556Srgrimes (void)printaname(p, dp->s_inode, dp->s_block); 1391556Srgrimes (void)putchar('\n'); 1401556Srgrimes } 1411556Srgrimes} 1421556Srgrimes 14362597Sassar/* 14462597Sassar * print name in current style 14562597Sassar */ 14662597Sassarstatic int 14790110Simpprintname(const char *name) 14862597Sassar{ 14962597Sassar if (f_octal || f_octal_escape) 15062597Sassar return prn_octal(name); 15162597Sassar else if (f_nonprint) 15262597Sassar return prn_printable(name); 15362597Sassar else 15462597Sassar return printf("%s", name); 15562597Sassar} 15662597Sassar 1571556Srgrimesvoid 15890110Simpprintlong(DISPLAY *dp) 1591556Srgrimes{ 1601556Srgrimes struct stat *sp; 16188594Sjoe FTSENT *p; 16288594Sjoe NAMES *np; 16388594Sjoe char buf[20]; 16461292Sache#ifdef COLORLS 16588594Sjoe int color_printed = 0; 16661292Sache#endif 1671556Srgrimes 1681556Srgrimes if (dp->list->fts_level != FTS_ROOTLEVEL && (f_longform || f_size)) 1691556Srgrimes (void)printf("total %lu\n", howmany(dp->btotal, blocksize)); 1701556Srgrimes 1711556Srgrimes for (p = dp->list; p; p = p->fts_link) { 1721556Srgrimes if (IS_NOPRINT(p)) 1731556Srgrimes continue; 1741556Srgrimes sp = p->fts_statp; 1751556Srgrimes if (f_inode) 17620417Ssteve (void)printf("%*lu ", dp->s_inode, (u_long)sp->st_ino); 1771556Srgrimes if (f_size) 17890150Smarkm (void)printf("%*lld ", 1791556Srgrimes dp->s_block, howmany(sp->st_blocks, blocksize)); 18090150Smarkm strmode(sp->st_mode, buf); 1811556Srgrimes np = p->fts_pointer; 1821556Srgrimes (void)printf("%s %*u %-*s %-*s ", buf, dp->s_nlink, 1831556Srgrimes sp->st_nlink, dp->s_user, np->user, dp->s_group, 1841556Srgrimes np->group); 1851556Srgrimes if (f_flags) 1861556Srgrimes (void)printf("%-*s ", dp->s_flags, np->flags); 18786922Sgreen if (f_lomac) 18886922Sgreen (void)printf("%-*s ", dp->s_lattr, np->lattr); 1891556Srgrimes if (S_ISCHR(sp->st_mode) || S_ISBLK(sp->st_mode)) 19055514Sbde if (minor(sp->st_rdev) > 255 || minor(sp->st_rdev) < 0) 19113120Sjoerg (void)printf("%3d, 0x%08x ", 19255514Sbde major(sp->st_rdev), 19355514Sbde (u_int)minor(sp->st_rdev)); 19413120Sjoerg else 19513120Sjoerg (void)printf("%3d, %3d ", 19613120Sjoerg major(sp->st_rdev), minor(sp->st_rdev)); 1971556Srgrimes else if (dp->bcfile) 19890150Smarkm (void)printf("%*s%*lld ", 1991556Srgrimes 8 - dp->s_size, "", dp->s_size, sp->st_size); 2001556Srgrimes else 20188591Sjoe printsize(dp->s_size, sp->st_size); 2021556Srgrimes if (f_accesstime) 2031556Srgrimes printtime(sp->st_atime); 2041556Srgrimes else if (f_statustime) 2051556Srgrimes printtime(sp->st_ctime); 2061556Srgrimes else 2071556Srgrimes printtime(sp->st_mtime); 20861268Sjoe#ifdef COLORLS 20961178Sjoe if (f_color) 21061291Sache color_printed = colortype(sp->st_mode); 21161268Sjoe#endif 21262597Sassar (void)printname(p->fts_name); 21361268Sjoe#ifdef COLORLS 21461291Sache if (f_color && color_printed) 21561321Sache endcolor(0); 21661268Sjoe#endif 2171556Srgrimes if (f_type) 2181556Srgrimes (void)printtype(sp->st_mode); 2191556Srgrimes if (S_ISLNK(sp->st_mode)) 2201556Srgrimes printlink(p); 2211556Srgrimes (void)putchar('\n'); 2221556Srgrimes } 2231556Srgrimes} 2241556Srgrimes 2251556Srgrimesvoid 22690110Simpprintcol(DISPLAY *dp) 2271556Srgrimes{ 2281556Srgrimes extern int termwidth; 2291556Srgrimes static FTSENT **array; 2301556Srgrimes static int lastentries = -1; 23188594Sjoe FTSENT *p; 23288594Sjoe int base; 23388594Sjoe int chcnt; 23488594Sjoe int cnt; 23588594Sjoe int col; 23688594Sjoe int colwidth; 23788594Sjoe int endcol; 23888594Sjoe int num; 23988594Sjoe int numcols; 24088594Sjoe int numrows; 24188594Sjoe int row; 24288594Sjoe int tabwidth; 2431556Srgrimes 24437932Shoek if (f_notabs) 24537932Shoek tabwidth = 1; 24637932Shoek else 24737932Shoek tabwidth = 8; 24837932Shoek 2491556Srgrimes /* 2501556Srgrimes * Have to do random access in the linked list -- build a table 2511556Srgrimes * of pointers. 2521556Srgrimes */ 2531556Srgrimes if (dp->entries > lastentries) { 2541556Srgrimes lastentries = dp->entries; 2551556Srgrimes if ((array = 2561556Srgrimes realloc(array, dp->entries * sizeof(FTSENT *))) == NULL) { 2571556Srgrimes warn(NULL); 2581556Srgrimes printscol(dp); 2591556Srgrimes } 2601556Srgrimes } 2611556Srgrimes for (p = dp->list, num = 0; p; p = p->fts_link) 2621556Srgrimes if (p->fts_number != NO_PRINT) 2631556Srgrimes array[num++] = p; 2641556Srgrimes 2651556Srgrimes colwidth = dp->maxlen; 2661556Srgrimes if (f_inode) 2671556Srgrimes colwidth += dp->s_inode + 1; 2681556Srgrimes if (f_size) 2691556Srgrimes colwidth += dp->s_block + 1; 2701556Srgrimes if (f_type) 2711556Srgrimes colwidth += 1; 2721556Srgrimes 27337932Shoek colwidth = (colwidth + tabwidth) & ~(tabwidth - 1); 2741556Srgrimes if (termwidth < 2 * colwidth) { 2751556Srgrimes printscol(dp); 2761556Srgrimes return; 2771556Srgrimes } 2781556Srgrimes numcols = termwidth / colwidth; 2791556Srgrimes numrows = num / numcols; 2801556Srgrimes if (num % numcols) 2811556Srgrimes ++numrows; 2821556Srgrimes 2831556Srgrimes if (dp->list->fts_level != FTS_ROOTLEVEL && (f_longform || f_size)) 2841556Srgrimes (void)printf("total %lu\n", howmany(dp->btotal, blocksize)); 2851556Srgrimes for (row = 0; row < numrows; ++row) { 2861556Srgrimes endcol = colwidth; 2871556Srgrimes for (base = row, chcnt = col = 0; col < numcols; ++col) { 2881556Srgrimes chcnt += printaname(array[base], dp->s_inode, 2891556Srgrimes dp->s_block); 2901556Srgrimes if ((base += numrows) >= num) 2911556Srgrimes break; 29237932Shoek while ((cnt = ((chcnt + tabwidth) & ~(tabwidth - 1))) 29388595Sjoe <= endcol) { 29437932Shoek (void)putchar(f_notabs ? ' ' : '\t'); 2951556Srgrimes chcnt = cnt; 2961556Srgrimes } 2971556Srgrimes endcol += colwidth; 2981556Srgrimes } 2991556Srgrimes (void)putchar('\n'); 3001556Srgrimes } 3011556Srgrimes} 3021556Srgrimes 3031556Srgrimes/* 3041556Srgrimes * print [inode] [size] name 3051556Srgrimes * return # of characters printed, no trailing characters. 3061556Srgrimes */ 3071556Srgrimesstatic int 30890110Simpprintaname(FTSENT *p, u_long inodefield, u_long sizefield) 3091556Srgrimes{ 3101556Srgrimes struct stat *sp; 31188594Sjoe int chcnt; 31261292Sache#ifdef COLORLS 31388594Sjoe int color_printed = 0; 31461292Sache#endif 3151556Srgrimes 3161556Srgrimes sp = p->fts_statp; 3171556Srgrimes chcnt = 0; 3181556Srgrimes if (f_inode) 31920417Ssteve chcnt += printf("%*lu ", (int)inodefield, (u_long)sp->st_ino); 3201556Srgrimes if (f_size) 32190150Smarkm chcnt += printf("%*lld ", 3221556Srgrimes (int)sizefield, howmany(sp->st_blocks, blocksize)); 32361268Sjoe#ifdef COLORLS 32461178Sjoe if (f_color) 32561291Sache color_printed = colortype(sp->st_mode); 32661268Sjoe#endif 32762597Sassar chcnt += printname(p->fts_name); 32861268Sjoe#ifdef COLORLS 32961291Sache if (f_color && color_printed) 33061321Sache endcolor(0); 33161268Sjoe#endif 3321556Srgrimes if (f_type) 3331556Srgrimes chcnt += printtype(sp->st_mode); 3341556Srgrimes return (chcnt); 3351556Srgrimes} 3361556Srgrimes 3371556Srgrimesstatic void 33890110Simpprinttime(time_t ftime) 3391556Srgrimes{ 34088594Sjoe char longstring[80]; 34188594Sjoe static time_t now; 34288594Sjoe const char *format; 34388594Sjoe static int d_first = -1; 3441556Srgrimes 34574566Sache if (d_first < 0) 34674566Sache d_first = (*nl_langinfo(D_MD_ORDER) == 'd'); 34721545Smpp if (now == 0) 34821545Smpp now = time(NULL); 34921545Smpp 3509987Swollman#define SIXMONTHS ((365 / 2) * 86400) 3511556Srgrimes if (f_sectime) 35261920Sjoe /* mmm dd hh:mm:ss yyyy || dd mmm hh:mm:ss yyyy */ 35374566Sache format = d_first ? "%e %b %T %Y " : "%b %e %T %Y "; 35421545Smpp else if (ftime + SIXMONTHS > now && ftime < now + SIXMONTHS) 35561920Sjoe /* mmm dd hh:mm || dd mmm hh:mm */ 35674566Sache format = d_first ? "%e %b %R " : "%b %e %R "; 35761814Sjoe else 35861920Sjoe /* mmm dd yyyy || dd mmm yyyy */ 35974566Sache format = d_first ? "%e %b %Y " : "%b %e %Y "; 36061814Sjoe strftime(longstring, sizeof(longstring), format, localtime(&ftime)); 36161814Sjoe fputs(longstring, stdout); 3621556Srgrimes} 3631556Srgrimes 3641556Srgrimesstatic int 36590110Simpprinttype(u_int mode) 3661556Srgrimes{ 3671556Srgrimes switch (mode & S_IFMT) { 3681556Srgrimes case S_IFDIR: 3691556Srgrimes (void)putchar('/'); 3701556Srgrimes return (1); 3711556Srgrimes case S_IFIFO: 3721556Srgrimes (void)putchar('|'); 3731556Srgrimes return (1); 3741556Srgrimes case S_IFLNK: 3751556Srgrimes (void)putchar('@'); 3761556Srgrimes return (1); 3771556Srgrimes case S_IFSOCK: 3781556Srgrimes (void)putchar('='); 3791556Srgrimes return (1); 38020417Ssteve case S_IFWHT: 38120417Ssteve (void)putchar('%'); 38220417Ssteve return (1); 38390150Smarkm default: 3841556Srgrimes } 3851556Srgrimes if (mode & (S_IXUSR | S_IXGRP | S_IXOTH)) { 3861556Srgrimes (void)putchar('*'); 3871556Srgrimes return (1); 3881556Srgrimes } 3891556Srgrimes return (0); 3901556Srgrimes} 3911556Srgrimes 39261268Sjoe#ifdef COLORLS 39361323Sachestatic int 39490110Simpputch(int c) 39561291Sache{ 39688602Sjoe (void)putchar(c); 39761321Sache return 0; 39861291Sache} 39961291Sache 40061323Sachestatic int 40190110Simpwritech(int c) 40261321Sache{ 40388594Sjoe char tmp = c; 40461291Sache 40588602Sjoe (void)write(STDOUT_FILENO, &tmp, 1); 40661321Sache return 0; 40761321Sache} 40861321Sache 40961323Sachestatic void 41090110Simpprintcolor(Colors c) 41161178Sjoe{ 41288594Sjoe char *ansiseq; 41361268Sjoe 41488583Sjoe if (colors[c].bold) 41588583Sjoe tputs(enter_bold, 1, putch); 41688583Sjoe 41788583Sjoe if (colors[c].num[0] != -1) { 41888583Sjoe ansiseq = tgoto(ansi_fgcol, 0, colors[c].num[0]); 41961321Sache if (ansiseq) 42061291Sache tputs(ansiseq, 1, putch); 42161178Sjoe } 42288583Sjoe if (colors[c].num[1] != -1) { 42388583Sjoe ansiseq = tgoto(ansi_bgcol, 0, colors[c].num[1]); 42461321Sache if (ansiseq) 42561291Sache tputs(ansiseq, 1, putch); 42661268Sjoe } 42761178Sjoe} 42861178Sjoe 42961321Sachestatic void 43090110Simpendcolor(int sig) 43161268Sjoe{ 43261321Sache tputs(ansi_coloff, 1, sig ? writech : putch); 43388583Sjoe tputs(attrs_off, 1, sig ? writech : putch); 43461268Sjoe} 43561268Sjoe 43661321Sachestatic int 43790110Simpcolortype(mode_t mode) 43861178Sjoe{ 43988602Sjoe switch (mode & S_IFMT) { 44088595Sjoe case S_IFDIR: 44161178Sjoe if (mode & S_IWOTH) 44288595Sjoe if (mode & S_ISTXT) 44388595Sjoe printcolor(C_WSDIR); 44488595Sjoe else 44588595Sjoe printcolor(C_WDIR); 44661178Sjoe else 44788595Sjoe printcolor(C_DIR); 44888602Sjoe return (1); 44988595Sjoe case S_IFLNK: 45061178Sjoe printcolor(C_LNK); 45188602Sjoe return (1); 45288595Sjoe case S_IFSOCK: 45361178Sjoe printcolor(C_SOCK); 45488602Sjoe return (1); 45588595Sjoe case S_IFIFO: 45661178Sjoe printcolor(C_FIFO); 45788602Sjoe return (1); 45888595Sjoe case S_IFBLK: 45961178Sjoe printcolor(C_BLK); 46088602Sjoe return (1); 46188595Sjoe case S_IFCHR: 46261178Sjoe printcolor(C_CHR); 46388602Sjoe return (1); 46461178Sjoe } 46561178Sjoe if (mode & (S_IXUSR | S_IXGRP | S_IXOTH)) { 46661178Sjoe if (mode & S_ISUID) 46788595Sjoe printcolor(C_SUID); 46861178Sjoe else if (mode & S_ISGID) 46988595Sjoe printcolor(C_SGID); 47061178Sjoe else 47188595Sjoe printcolor(C_EXEC); 47288602Sjoe return (1); 47361178Sjoe } 47488602Sjoe return (0); 47561178Sjoe} 47661178Sjoe 47761178Sjoevoid 47890110Simpparsecolors(const char *cs) 47961178Sjoe{ 48088594Sjoe int i; 48188594Sjoe int j; 48288594Sjoe int len; 48388594Sjoe char c[2]; 48488594Sjoe short legacy_warn = 0; 48561321Sache 48688586Sjoe if (cs == NULL) 48788602Sjoe cs = ""; /* LSCOLORS not set */ 48861178Sjoe len = strlen(cs); 48988602Sjoe for (i = 0; i < C_NUMCOLORS; i++) { 49088583Sjoe colors[i].bold = 0; 49188583Sjoe 49288586Sjoe if (len <= 2 * i) { 49388586Sjoe c[0] = defcolors[2 * i]; 49488586Sjoe c[1] = defcolors[2 * i + 1]; 49588602Sjoe } else { 49688586Sjoe c[0] = cs[2 * i]; 49788586Sjoe c[1] = cs[2 * i + 1]; 49861178Sjoe } 49988602Sjoe for (j = 0; j < 2; j++) { 50088583Sjoe /* Legacy colours used 0-7 */ 50188583Sjoe if (c[j] >= '0' && c[j] <= '7') { 50288583Sjoe colors[i].num[j] = c[j] - '0'; 50388583Sjoe if (!legacy_warn) { 50488583Sjoe fprintf(stderr, 50588668Sjoe "warn: LSCOLORS should use " 50688588Sjoe "characters a-h instead of 0-9 (" 50788588Sjoe "see the manual page)\n"); 50888583Sjoe } 50988583Sjoe legacy_warn = 1; 51088583Sjoe } else if (c[j] >= 'a' && c[j] <= 'h') 51188583Sjoe colors[i].num[j] = c[j] - 'a'; 51288583Sjoe else if (c[j] >= 'A' && c[j] <= 'H') { 51388583Sjoe colors[i].num[j] = c[j] - 'A'; 51488583Sjoe colors[i].bold = 1; 51588583Sjoe } else if (tolower((unsigned char)c[j] == 'x')) 51688583Sjoe colors[i].num[j] = -1; 51788583Sjoe else { 51861178Sjoe fprintf(stderr, 51988583Sjoe "error: invalid character '%c' in LSCOLORS" 52088583Sjoe " env var\n", c[j]); 52188584Sjoe colors[i].num[j] = -1; 52261178Sjoe } 52361178Sjoe } 52461178Sjoe } 52561178Sjoe} 52661291Sache 52761323Sachevoid 52890110Simpcolorquit(int sig) 52961291Sache{ 53061321Sache endcolor(sig); 53161294Sache 53288602Sjoe (void)signal(sig, SIG_DFL); 53388602Sjoe (void)kill(getpid(), sig); 53461291Sache} 53588602Sjoe 53688602Sjoe#endif /* COLORLS */ 53788602Sjoe 5381556Srgrimesstatic void 53990110Simpprintlink(FTSENT *p) 5401556Srgrimes{ 54188594Sjoe int lnklen; 54288594Sjoe char name[MAXPATHLEN + 1]; 54388594Sjoe char path[MAXPATHLEN + 1]; 5441556Srgrimes 5451556Srgrimes if (p->fts_level == FTS_ROOTLEVEL) 5461556Srgrimes (void)snprintf(name, sizeof(name), "%s", p->fts_name); 5478855Srgrimes else 5481556Srgrimes (void)snprintf(name, sizeof(name), 5491556Srgrimes "%s/%s", p->fts_parent->fts_accpath, p->fts_name); 5501556Srgrimes if ((lnklen = readlink(name, path, sizeof(path) - 1)) == -1) { 5511556Srgrimes (void)fprintf(stderr, "\nls: %s: %s\n", name, strerror(errno)); 5521556Srgrimes return; 5531556Srgrimes } 5541556Srgrimes path[lnklen] = '\0'; 55562597Sassar (void)printf(" -> "); 55690150Smarkm (void)printname(path); 5571556Srgrimes} 55888591Sjoe 55988591Sjoestatic void 56090110Simpprintsize(size_t width, off_t bytes) 56188591Sjoe{ 56288591Sjoe unit_t unit; 56388602Sjoe 56488591Sjoe if (f_humanval) { 56588591Sjoe unit = unit_adjust(&bytes); 56688591Sjoe 56788591Sjoe if (bytes == 0) 56888591Sjoe (void)printf("%*s ", width, "0B"); 56988591Sjoe else 57090150Smarkm (void)printf("%*lld%c ", width - 1, bytes, 57188602Sjoe "BKMGTPE"[unit]); 57288602Sjoe } else 57390150Smarkm (void)printf("%*lld ", width, bytes); 57488591Sjoe} 57588591Sjoe 57688591Sjoe/* 57788591Sjoe * Output in "human-readable" format. Uses 3 digits max and puts 57888591Sjoe * unit suffixes at the end. Makes output compact and easy to read, 57988591Sjoe * especially on huge disks. 58088591Sjoe * 58188591Sjoe */ 58288591Sjoeunit_t 58390110Simpunit_adjust(off_t *val) 58488591Sjoe{ 58588595Sjoe double abval; 58688595Sjoe unit_t unit; 58788595Sjoe unsigned int unit_sz; 58888591Sjoe 58990150Smarkm abval = fabs((double)*val); 59088591Sjoe 59188595Sjoe unit_sz = abval ? ilogb(abval) / 10 : 0; 59288591Sjoe 59388595Sjoe if (unit_sz >= UNIT_MAX) { 59488595Sjoe unit = NONE; 59588595Sjoe } else { 59688595Sjoe unit = unitp[unit_sz]; 59788595Sjoe *val /= (double)vals_base2[unit_sz]; 59888595Sjoe } 59988591Sjoe 60088595Sjoe return (unit); 60188591Sjoe} 602