print.c revision 96681
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 3790153Smarkm#include <sys/cdefs.h> 3890153Smarkm 3990153Smarkm__FBSDID("$FreeBSD: head/bin/ls/print.c 96681 2002-05-15 18:53:56Z billf $"); 4090153Smarkm 4190153Smarkm#if 0 421556Srgrimes#ifndef lint 4327967Sstevestatic char sccsid[] = "@(#)print.c 8.4 (Berkeley) 4/17/94"; 4490153Smarkm#endif /* not lint */ 4527967Ssteve#endif 461556Srgrimes 471556Srgrimes#include <sys/param.h> 481556Srgrimes#include <sys/stat.h> 491556Srgrimes 501556Srgrimes#include <err.h> 511556Srgrimes#include <errno.h> 521556Srgrimes#include <fts.h> 5388591Sjoe#include <math.h> 5474566Sache#include <langinfo.h> 551556Srgrimes#include <stdio.h> 561556Srgrimes#include <stdlib.h> 571556Srgrimes#include <string.h> 5891212Sbde#include <time.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: 38496681Sbillf break; 3851556Srgrimes } 3861556Srgrimes if (mode & (S_IXUSR | S_IXGRP | S_IXOTH)) { 3871556Srgrimes (void)putchar('*'); 3881556Srgrimes return (1); 3891556Srgrimes } 3901556Srgrimes return (0); 3911556Srgrimes} 3921556Srgrimes 39361268Sjoe#ifdef COLORLS 39461323Sachestatic int 39590110Simpputch(int c) 39661291Sache{ 39788602Sjoe (void)putchar(c); 39861321Sache return 0; 39961291Sache} 40061291Sache 40161323Sachestatic int 40290110Simpwritech(int c) 40361321Sache{ 40488594Sjoe char tmp = c; 40561291Sache 40688602Sjoe (void)write(STDOUT_FILENO, &tmp, 1); 40761321Sache return 0; 40861321Sache} 40961321Sache 41061323Sachestatic void 41190110Simpprintcolor(Colors c) 41261178Sjoe{ 41388594Sjoe char *ansiseq; 41461268Sjoe 41588583Sjoe if (colors[c].bold) 41688583Sjoe tputs(enter_bold, 1, putch); 41788583Sjoe 41888583Sjoe if (colors[c].num[0] != -1) { 41988583Sjoe ansiseq = tgoto(ansi_fgcol, 0, colors[c].num[0]); 42061321Sache if (ansiseq) 42161291Sache tputs(ansiseq, 1, putch); 42261178Sjoe } 42388583Sjoe if (colors[c].num[1] != -1) { 42488583Sjoe ansiseq = tgoto(ansi_bgcol, 0, colors[c].num[1]); 42561321Sache if (ansiseq) 42661291Sache tputs(ansiseq, 1, putch); 42761268Sjoe } 42861178Sjoe} 42961178Sjoe 43061321Sachestatic void 43190110Simpendcolor(int sig) 43261268Sjoe{ 43361321Sache tputs(ansi_coloff, 1, sig ? writech : putch); 43488583Sjoe tputs(attrs_off, 1, sig ? writech : putch); 43561268Sjoe} 43661268Sjoe 43761321Sachestatic int 43890110Simpcolortype(mode_t mode) 43961178Sjoe{ 44088602Sjoe switch (mode & S_IFMT) { 44188595Sjoe case S_IFDIR: 44261178Sjoe if (mode & S_IWOTH) 44388595Sjoe if (mode & S_ISTXT) 44488595Sjoe printcolor(C_WSDIR); 44588595Sjoe else 44688595Sjoe printcolor(C_WDIR); 44761178Sjoe else 44888595Sjoe printcolor(C_DIR); 44988602Sjoe return (1); 45088595Sjoe case S_IFLNK: 45161178Sjoe printcolor(C_LNK); 45288602Sjoe return (1); 45388595Sjoe case S_IFSOCK: 45461178Sjoe printcolor(C_SOCK); 45588602Sjoe return (1); 45688595Sjoe case S_IFIFO: 45761178Sjoe printcolor(C_FIFO); 45888602Sjoe return (1); 45988595Sjoe case S_IFBLK: 46061178Sjoe printcolor(C_BLK); 46188602Sjoe return (1); 46288595Sjoe case S_IFCHR: 46361178Sjoe printcolor(C_CHR); 46488602Sjoe return (1); 46561178Sjoe } 46661178Sjoe if (mode & (S_IXUSR | S_IXGRP | S_IXOTH)) { 46761178Sjoe if (mode & S_ISUID) 46888595Sjoe printcolor(C_SUID); 46961178Sjoe else if (mode & S_ISGID) 47088595Sjoe printcolor(C_SGID); 47161178Sjoe else 47288595Sjoe printcolor(C_EXEC); 47388602Sjoe return (1); 47461178Sjoe } 47588602Sjoe return (0); 47661178Sjoe} 47761178Sjoe 47861178Sjoevoid 47990110Simpparsecolors(const char *cs) 48061178Sjoe{ 48188594Sjoe int i; 48288594Sjoe int j; 48388594Sjoe int len; 48488594Sjoe char c[2]; 48588594Sjoe short legacy_warn = 0; 48661321Sache 48788586Sjoe if (cs == NULL) 48888602Sjoe cs = ""; /* LSCOLORS not set */ 48961178Sjoe len = strlen(cs); 49088602Sjoe for (i = 0; i < C_NUMCOLORS; i++) { 49188583Sjoe colors[i].bold = 0; 49288583Sjoe 49388586Sjoe if (len <= 2 * i) { 49488586Sjoe c[0] = defcolors[2 * i]; 49588586Sjoe c[1] = defcolors[2 * i + 1]; 49688602Sjoe } else { 49788586Sjoe c[0] = cs[2 * i]; 49888586Sjoe c[1] = cs[2 * i + 1]; 49961178Sjoe } 50088602Sjoe for (j = 0; j < 2; j++) { 50188583Sjoe /* Legacy colours used 0-7 */ 50288583Sjoe if (c[j] >= '0' && c[j] <= '7') { 50388583Sjoe colors[i].num[j] = c[j] - '0'; 50488583Sjoe if (!legacy_warn) { 50588583Sjoe fprintf(stderr, 50688668Sjoe "warn: LSCOLORS should use " 50788588Sjoe "characters a-h instead of 0-9 (" 50888588Sjoe "see the manual page)\n"); 50988583Sjoe } 51088583Sjoe legacy_warn = 1; 51188583Sjoe } else if (c[j] >= 'a' && c[j] <= 'h') 51288583Sjoe colors[i].num[j] = c[j] - 'a'; 51388583Sjoe else if (c[j] >= 'A' && c[j] <= 'H') { 51488583Sjoe colors[i].num[j] = c[j] - 'A'; 51588583Sjoe colors[i].bold = 1; 51688583Sjoe } else if (tolower((unsigned char)c[j] == 'x')) 51788583Sjoe colors[i].num[j] = -1; 51888583Sjoe else { 51961178Sjoe fprintf(stderr, 52088583Sjoe "error: invalid character '%c' in LSCOLORS" 52188583Sjoe " env var\n", c[j]); 52288584Sjoe colors[i].num[j] = -1; 52361178Sjoe } 52461178Sjoe } 52561178Sjoe } 52661178Sjoe} 52761291Sache 52861323Sachevoid 52990110Simpcolorquit(int sig) 53061291Sache{ 53161321Sache endcolor(sig); 53261294Sache 53388602Sjoe (void)signal(sig, SIG_DFL); 53488602Sjoe (void)kill(getpid(), sig); 53561291Sache} 53688602Sjoe 53788602Sjoe#endif /* COLORLS */ 53888602Sjoe 5391556Srgrimesstatic void 54090110Simpprintlink(FTSENT *p) 5411556Srgrimes{ 54288594Sjoe int lnklen; 54388594Sjoe char name[MAXPATHLEN + 1]; 54488594Sjoe char path[MAXPATHLEN + 1]; 5451556Srgrimes 5461556Srgrimes if (p->fts_level == FTS_ROOTLEVEL) 5471556Srgrimes (void)snprintf(name, sizeof(name), "%s", p->fts_name); 5488855Srgrimes else 5491556Srgrimes (void)snprintf(name, sizeof(name), 5501556Srgrimes "%s/%s", p->fts_parent->fts_accpath, p->fts_name); 5511556Srgrimes if ((lnklen = readlink(name, path, sizeof(path) - 1)) == -1) { 5521556Srgrimes (void)fprintf(stderr, "\nls: %s: %s\n", name, strerror(errno)); 5531556Srgrimes return; 5541556Srgrimes } 5551556Srgrimes path[lnklen] = '\0'; 55662597Sassar (void)printf(" -> "); 55790150Smarkm (void)printname(path); 5581556Srgrimes} 55988591Sjoe 56088591Sjoestatic void 56190110Simpprintsize(size_t width, off_t bytes) 56288591Sjoe{ 56388591Sjoe unit_t unit; 56488602Sjoe 56588591Sjoe if (f_humanval) { 56688591Sjoe unit = unit_adjust(&bytes); 56788591Sjoe 56888591Sjoe if (bytes == 0) 56988591Sjoe (void)printf("%*s ", width, "0B"); 57088591Sjoe else 57190150Smarkm (void)printf("%*lld%c ", width - 1, bytes, 57288602Sjoe "BKMGTPE"[unit]); 57388602Sjoe } else 57490150Smarkm (void)printf("%*lld ", width, bytes); 57588591Sjoe} 57688591Sjoe 57788591Sjoe/* 57888591Sjoe * Output in "human-readable" format. Uses 3 digits max and puts 57988591Sjoe * unit suffixes at the end. Makes output compact and easy to read, 58088591Sjoe * especially on huge disks. 58188591Sjoe * 58288591Sjoe */ 58388591Sjoeunit_t 58490110Simpunit_adjust(off_t *val) 58588591Sjoe{ 58688595Sjoe double abval; 58788595Sjoe unit_t unit; 58888595Sjoe unsigned int unit_sz; 58988591Sjoe 59090150Smarkm abval = fabs((double)*val); 59188591Sjoe 59288595Sjoe unit_sz = abval ? ilogb(abval) / 10 : 0; 59388591Sjoe 59488595Sjoe if (unit_sz >= UNIT_MAX) { 59588595Sjoe unit = NONE; 59688595Sjoe } else { 59788595Sjoe unit = unitp[unit_sz]; 59888595Sjoe *val /= (double)vals_base2[unit_sz]; 59988595Sjoe } 60088591Sjoe 60188595Sjoe return (unit); 60288591Sjoe} 603