print.c revision 102577
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#if 0 381556Srgrimes#ifndef lint 3927967Sstevestatic char sccsid[] = "@(#)print.c 8.4 (Berkeley) 4/17/94"; 4090153Smarkm#endif /* not lint */ 4127967Ssteve#endif 4299109Sobrien#include <sys/cdefs.h> 4399109Sobrien__FBSDID("$FreeBSD: head/bin/ls/print.c 102577 2002-08-29 14:29:09Z keramida $"); 441556Srgrimes 451556Srgrimes#include <sys/param.h> 461556Srgrimes#include <sys/stat.h> 471556Srgrimes 481556Srgrimes#include <err.h> 491556Srgrimes#include <errno.h> 501556Srgrimes#include <fts.h> 5188591Sjoe#include <math.h> 5274566Sache#include <langinfo.h> 531556Srgrimes#include <stdio.h> 541556Srgrimes#include <stdlib.h> 551556Srgrimes#include <string.h> 5691212Sbde#include <time.h> 571556Srgrimes#include <unistd.h> 5861294Sache#ifdef COLORLS 5961294Sache#include <ctype.h> 6061294Sache#include <termcap.h> 6161294Sache#include <signal.h> 6261294Sache#endif 631556Srgrimes 641556Srgrimes#include "ls.h" 651556Srgrimes#include "extern.h" 661556Srgrimes 6790110Simpstatic int printaname(FTSENT *, u_long, u_long); 6890110Simpstatic void printlink(FTSENT *); 6990110Simpstatic void printtime(time_t); 7090110Simpstatic int printtype(u_int); 7190110Simpstatic void printsize(size_t, off_t); 7261321Sache#ifdef COLORLS 7390110Simpstatic void endcolor(int); 7490110Simpstatic int colortype(mode_t); 7561321Sache#endif 761556Srgrimes 771556Srgrimes#define IS_NOPRINT(p) ((p)->fts_number == NO_PRINT) 781556Srgrimes 7988591Sjoe#define KILO_SZ(n) (n) 8088591Sjoe#define MEGA_SZ(n) ((n) * (n)) 8188591Sjoe#define GIGA_SZ(n) ((n) * (n) * (n)) 8288591Sjoe#define TERA_SZ(n) ((n) * (n) * (n) * (n)) 8388591Sjoe#define PETA_SZ(n) ((n) * (n) * (n) * (n) * (n)) 8488591Sjoe 8588591Sjoe#define KILO_2_SZ (KILO_SZ(1024ULL)) 8688591Sjoe#define MEGA_2_SZ (MEGA_SZ(1024ULL)) 8788591Sjoe#define GIGA_2_SZ (GIGA_SZ(1024ULL)) 8888591Sjoe#define TERA_2_SZ (TERA_SZ(1024ULL)) 8988591Sjoe#define PETA_2_SZ (PETA_SZ(1024ULL)) 9088591Sjoe 9190150Smarkmstatic unsigned long long vals_base2[] = {1, KILO_2_SZ, MEGA_2_SZ, GIGA_2_SZ, TERA_2_SZ, PETA_2_SZ}; 9288591Sjoe 9388602Sjoetypedef enum { 9488602Sjoe NONE, KILO, MEGA, GIGA, TERA, PETA, UNIT_MAX 9588602Sjoe} unit_t; 9690110Simpstatic unit_t unit_adjust(off_t *); 9788591Sjoe 9890150Smarkmstatic int unitp[] = {NONE, KILO, MEGA, GIGA, TERA, PETA}; 9988591Sjoe 10061268Sjoe#ifdef COLORLS 10161178Sjoe/* Most of these are taken from <sys/stat.h> */ 10261178Sjoetypedef enum Colors { 10388602Sjoe C_DIR, /* directory */ 10488602Sjoe C_LNK, /* symbolic link */ 10588602Sjoe C_SOCK, /* socket */ 10688602Sjoe C_FIFO, /* pipe */ 10788602Sjoe C_EXEC, /* executable */ 10888602Sjoe C_BLK, /* block special */ 10988602Sjoe C_CHR, /* character special */ 11088602Sjoe C_SUID, /* setuid executable */ 11188602Sjoe C_SGID, /* setgid executable */ 11288602Sjoe C_WSDIR, /* directory writeble to others, with sticky 11388602Sjoe * bit */ 11488602Sjoe C_WDIR, /* directory writeble to others, without 11588602Sjoe * sticky bit */ 11688602Sjoe C_NUMCOLORS /* just a place-holder */ 11788586Sjoe} Colors; 11861178Sjoe 11990150Smarkmstatic const char *defcolors = "exfxcxdxbxegedabagacad"; 12061178Sjoe 12188583Sjoe/* colors for file types */ 12288583Sjoestatic struct { 12388586Sjoe int num[2]; 12488586Sjoe int bold; 12588583Sjoe} colors[C_NUMCOLORS]; 12661268Sjoe#endif 12761178Sjoe 1281556Srgrimesvoid 12990110Simpprintscol(DISPLAY *dp) 1301556Srgrimes{ 13188594Sjoe FTSENT *p; 1321556Srgrimes 1331556Srgrimes for (p = dp->list; p; p = p->fts_link) { 1341556Srgrimes if (IS_NOPRINT(p)) 1351556Srgrimes continue; 1361556Srgrimes (void)printaname(p, dp->s_inode, dp->s_block); 1371556Srgrimes (void)putchar('\n'); 1381556Srgrimes } 1391556Srgrimes} 1401556Srgrimes 14162597Sassar/* 14262597Sassar * print name in current style 14362597Sassar */ 14462597Sassarstatic int 14590110Simpprintname(const char *name) 14662597Sassar{ 14762597Sassar if (f_octal || f_octal_escape) 14862597Sassar return prn_octal(name); 14962597Sassar else if (f_nonprint) 15062597Sassar return prn_printable(name); 15162597Sassar else 15262597Sassar return printf("%s", name); 15362597Sassar} 15462597Sassar 1551556Srgrimesvoid 15690110Simpprintlong(DISPLAY *dp) 1571556Srgrimes{ 1581556Srgrimes struct stat *sp; 15988594Sjoe FTSENT *p; 16088594Sjoe NAMES *np; 16188594Sjoe char buf[20]; 16261292Sache#ifdef COLORLS 16388594Sjoe int color_printed = 0; 16461292Sache#endif 1651556Srgrimes 1661556Srgrimes if (dp->list->fts_level != FTS_ROOTLEVEL && (f_longform || f_size)) 1671556Srgrimes (void)printf("total %lu\n", howmany(dp->btotal, blocksize)); 1681556Srgrimes 1691556Srgrimes for (p = dp->list; p; p = p->fts_link) { 1701556Srgrimes if (IS_NOPRINT(p)) 1711556Srgrimes continue; 1721556Srgrimes sp = p->fts_statp; 1731556Srgrimes if (f_inode) 17420417Ssteve (void)printf("%*lu ", dp->s_inode, (u_long)sp->st_ino); 1751556Srgrimes if (f_size) 17690150Smarkm (void)printf("%*lld ", 1771556Srgrimes dp->s_block, howmany(sp->st_blocks, blocksize)); 17890150Smarkm strmode(sp->st_mode, buf); 1791556Srgrimes np = p->fts_pointer; 1801556Srgrimes (void)printf("%s %*u %-*s %-*s ", buf, dp->s_nlink, 1811556Srgrimes sp->st_nlink, dp->s_user, np->user, dp->s_group, 1821556Srgrimes np->group); 1831556Srgrimes if (f_flags) 1841556Srgrimes (void)printf("%-*s ", dp->s_flags, np->flags); 18586922Sgreen if (f_lomac) 18686922Sgreen (void)printf("%-*s ", dp->s_lattr, np->lattr); 1871556Srgrimes if (S_ISCHR(sp->st_mode) || S_ISBLK(sp->st_mode)) 18855514Sbde if (minor(sp->st_rdev) > 255 || minor(sp->st_rdev) < 0) 18913120Sjoerg (void)printf("%3d, 0x%08x ", 19055514Sbde major(sp->st_rdev), 19155514Sbde (u_int)minor(sp->st_rdev)); 19213120Sjoerg else 19313120Sjoerg (void)printf("%3d, %3d ", 19413120Sjoerg major(sp->st_rdev), minor(sp->st_rdev)); 1951556Srgrimes else if (dp->bcfile) 19690150Smarkm (void)printf("%*s%*lld ", 1971556Srgrimes 8 - dp->s_size, "", dp->s_size, sp->st_size); 1981556Srgrimes else 19988591Sjoe printsize(dp->s_size, sp->st_size); 2001556Srgrimes if (f_accesstime) 2011556Srgrimes printtime(sp->st_atime); 2021556Srgrimes else if (f_statustime) 2031556Srgrimes printtime(sp->st_ctime); 2041556Srgrimes else 2051556Srgrimes printtime(sp->st_mtime); 20661268Sjoe#ifdef COLORLS 20761178Sjoe if (f_color) 20861291Sache color_printed = colortype(sp->st_mode); 20961268Sjoe#endif 21062597Sassar (void)printname(p->fts_name); 21161268Sjoe#ifdef COLORLS 21261291Sache if (f_color && color_printed) 21361321Sache endcolor(0); 21461268Sjoe#endif 2151556Srgrimes if (f_type) 2161556Srgrimes (void)printtype(sp->st_mode); 2171556Srgrimes if (S_ISLNK(sp->st_mode)) 2181556Srgrimes printlink(p); 2191556Srgrimes (void)putchar('\n'); 2201556Srgrimes } 2211556Srgrimes} 2221556Srgrimes 2231556Srgrimesvoid 22496892Stjrprintstream(DISPLAY *dp) 22596892Stjr{ 22696892Stjr FTSENT *p; 22796892Stjr extern int termwidth; 22896892Stjr int chcnt; 22996892Stjr 23096892Stjr for (p = dp->list, chcnt = 0; p; p = p->fts_link) { 23196892Stjr if (p->fts_number == NO_PRINT) 23296892Stjr continue; 23396892Stjr if (strlen(p->fts_name) + chcnt + 23496892Stjr (p->fts_link ? 2 : 0) >= (unsigned)termwidth) { 23596892Stjr putchar('\n'); 23696892Stjr chcnt = 0; 23796892Stjr } 23896892Stjr chcnt += printaname(p, dp->s_inode, dp->s_block); 23996892Stjr if (p->fts_link) { 24096892Stjr printf(", "); 24196892Stjr chcnt += 2; 24296892Stjr } 24396892Stjr } 24496892Stjr if (chcnt) 24596892Stjr putchar('\n'); 24696892Stjr} 24796892Stjr 24896892Stjrvoid 24990110Simpprintcol(DISPLAY *dp) 2501556Srgrimes{ 2511556Srgrimes extern int termwidth; 2521556Srgrimes static FTSENT **array; 2531556Srgrimes static int lastentries = -1; 25488594Sjoe FTSENT *p; 25588594Sjoe int base; 25688594Sjoe int chcnt; 25788594Sjoe int cnt; 25888594Sjoe int col; 25988594Sjoe int colwidth; 26088594Sjoe int endcol; 26188594Sjoe int num; 26288594Sjoe int numcols; 26388594Sjoe int numrows; 26488594Sjoe int row; 26588594Sjoe int tabwidth; 2661556Srgrimes 26737932Shoek if (f_notabs) 26837932Shoek tabwidth = 1; 26937932Shoek else 27037932Shoek tabwidth = 8; 27137932Shoek 2721556Srgrimes /* 2731556Srgrimes * Have to do random access in the linked list -- build a table 2741556Srgrimes * of pointers. 2751556Srgrimes */ 2761556Srgrimes if (dp->entries > lastentries) { 2771556Srgrimes lastentries = dp->entries; 2781556Srgrimes if ((array = 2791556Srgrimes realloc(array, dp->entries * sizeof(FTSENT *))) == NULL) { 2801556Srgrimes warn(NULL); 2811556Srgrimes printscol(dp); 2821556Srgrimes } 2831556Srgrimes } 2841556Srgrimes for (p = dp->list, num = 0; p; p = p->fts_link) 2851556Srgrimes if (p->fts_number != NO_PRINT) 2861556Srgrimes array[num++] = p; 2871556Srgrimes 2881556Srgrimes colwidth = dp->maxlen; 2891556Srgrimes if (f_inode) 2901556Srgrimes colwidth += dp->s_inode + 1; 2911556Srgrimes if (f_size) 2921556Srgrimes colwidth += dp->s_block + 1; 2931556Srgrimes if (f_type) 2941556Srgrimes colwidth += 1; 2951556Srgrimes 29637932Shoek colwidth = (colwidth + tabwidth) & ~(tabwidth - 1); 2971556Srgrimes if (termwidth < 2 * colwidth) { 2981556Srgrimes printscol(dp); 2991556Srgrimes return; 3001556Srgrimes } 3011556Srgrimes numcols = termwidth / colwidth; 3021556Srgrimes numrows = num / numcols; 3031556Srgrimes if (num % numcols) 3041556Srgrimes ++numrows; 3051556Srgrimes 3061556Srgrimes if (dp->list->fts_level != FTS_ROOTLEVEL && (f_longform || f_size)) 3071556Srgrimes (void)printf("total %lu\n", howmany(dp->btotal, blocksize)); 30896892Stjr 309102577Skeramida base = 0; 3101556Srgrimes for (row = 0; row < numrows; ++row) { 3111556Srgrimes endcol = colwidth; 31296892Stjr if (!f_sortacross) 31396892Stjr base = row; 31496892Stjr for (col = 0, chcnt = 0; col < numcols; ++col) { 3151556Srgrimes chcnt += printaname(array[base], dp->s_inode, 3161556Srgrimes dp->s_block); 31796892Stjr if (f_sortacross) 31896892Stjr base++; 31996892Stjr else 32096892Stjr base += numrows; 32196892Stjr if (base >= num) 3221556Srgrimes break; 32337932Shoek while ((cnt = ((chcnt + tabwidth) & ~(tabwidth - 1))) 32488595Sjoe <= endcol) { 32596892Stjr if (f_sortacross && col + 1 >= numcols) 32696892Stjr break; 32737932Shoek (void)putchar(f_notabs ? ' ' : '\t'); 3281556Srgrimes chcnt = cnt; 3291556Srgrimes } 3301556Srgrimes endcol += colwidth; 3311556Srgrimes } 3321556Srgrimes (void)putchar('\n'); 3331556Srgrimes } 3341556Srgrimes} 3351556Srgrimes 3361556Srgrimes/* 3371556Srgrimes * print [inode] [size] name 3381556Srgrimes * return # of characters printed, no trailing characters. 3391556Srgrimes */ 3401556Srgrimesstatic int 34190110Simpprintaname(FTSENT *p, u_long inodefield, u_long sizefield) 3421556Srgrimes{ 3431556Srgrimes struct stat *sp; 34488594Sjoe int chcnt; 34561292Sache#ifdef COLORLS 34688594Sjoe int color_printed = 0; 34761292Sache#endif 3481556Srgrimes 3491556Srgrimes sp = p->fts_statp; 3501556Srgrimes chcnt = 0; 3511556Srgrimes if (f_inode) 35220417Ssteve chcnt += printf("%*lu ", (int)inodefield, (u_long)sp->st_ino); 3531556Srgrimes if (f_size) 35490150Smarkm chcnt += printf("%*lld ", 3551556Srgrimes (int)sizefield, howmany(sp->st_blocks, blocksize)); 35661268Sjoe#ifdef COLORLS 35761178Sjoe if (f_color) 35861291Sache color_printed = colortype(sp->st_mode); 35961268Sjoe#endif 36062597Sassar chcnt += printname(p->fts_name); 36161268Sjoe#ifdef COLORLS 36261291Sache if (f_color && color_printed) 36361321Sache endcolor(0); 36461268Sjoe#endif 3651556Srgrimes if (f_type) 3661556Srgrimes chcnt += printtype(sp->st_mode); 3671556Srgrimes return (chcnt); 3681556Srgrimes} 3691556Srgrimes 3701556Srgrimesstatic void 37190110Simpprinttime(time_t ftime) 3721556Srgrimes{ 37388594Sjoe char longstring[80]; 37488594Sjoe static time_t now; 37588594Sjoe const char *format; 37688594Sjoe static int d_first = -1; 3771556Srgrimes 37874566Sache if (d_first < 0) 37974566Sache d_first = (*nl_langinfo(D_MD_ORDER) == 'd'); 38021545Smpp if (now == 0) 38121545Smpp now = time(NULL); 38221545Smpp 3839987Swollman#define SIXMONTHS ((365 / 2) * 86400) 3841556Srgrimes if (f_sectime) 38561920Sjoe /* mmm dd hh:mm:ss yyyy || dd mmm hh:mm:ss yyyy */ 38674566Sache format = d_first ? "%e %b %T %Y " : "%b %e %T %Y "; 38721545Smpp else if (ftime + SIXMONTHS > now && ftime < now + SIXMONTHS) 38861920Sjoe /* mmm dd hh:mm || dd mmm hh:mm */ 38974566Sache format = d_first ? "%e %b %R " : "%b %e %R "; 39061814Sjoe else 39161920Sjoe /* mmm dd yyyy || dd mmm yyyy */ 39274566Sache format = d_first ? "%e %b %Y " : "%b %e %Y "; 39361814Sjoe strftime(longstring, sizeof(longstring), format, localtime(&ftime)); 39461814Sjoe fputs(longstring, stdout); 3951556Srgrimes} 3961556Srgrimes 3971556Srgrimesstatic int 39890110Simpprinttype(u_int mode) 3991556Srgrimes{ 40096892Stjr 40196892Stjr if (f_slash) { 40296892Stjr if ((mode & S_IFMT) == S_IFDIR) { 40396892Stjr (void)putchar('/'); 40496892Stjr return (1); 40596892Stjr } 40696892Stjr return (0); 40796892Stjr } 40896892Stjr 4091556Srgrimes switch (mode & S_IFMT) { 4101556Srgrimes case S_IFDIR: 4111556Srgrimes (void)putchar('/'); 4121556Srgrimes return (1); 4131556Srgrimes case S_IFIFO: 4141556Srgrimes (void)putchar('|'); 4151556Srgrimes return (1); 4161556Srgrimes case S_IFLNK: 4171556Srgrimes (void)putchar('@'); 4181556Srgrimes return (1); 4191556Srgrimes case S_IFSOCK: 4201556Srgrimes (void)putchar('='); 4211556Srgrimes return (1); 42220417Ssteve case S_IFWHT: 42320417Ssteve (void)putchar('%'); 42420417Ssteve return (1); 42590150Smarkm default: 42696681Sbillf break; 4271556Srgrimes } 4281556Srgrimes if (mode & (S_IXUSR | S_IXGRP | S_IXOTH)) { 4291556Srgrimes (void)putchar('*'); 4301556Srgrimes return (1); 4311556Srgrimes } 4321556Srgrimes return (0); 4331556Srgrimes} 4341556Srgrimes 43561268Sjoe#ifdef COLORLS 43661323Sachestatic int 43790110Simpputch(int c) 43861291Sache{ 43988602Sjoe (void)putchar(c); 44061321Sache return 0; 44161291Sache} 44261291Sache 44361323Sachestatic int 44490110Simpwritech(int c) 44561321Sache{ 44688594Sjoe char tmp = c; 44761291Sache 44888602Sjoe (void)write(STDOUT_FILENO, &tmp, 1); 44961321Sache return 0; 45061321Sache} 45161321Sache 45261323Sachestatic void 45390110Simpprintcolor(Colors c) 45461178Sjoe{ 45588594Sjoe char *ansiseq; 45661268Sjoe 45788583Sjoe if (colors[c].bold) 45888583Sjoe tputs(enter_bold, 1, putch); 45988583Sjoe 46088583Sjoe if (colors[c].num[0] != -1) { 46188583Sjoe ansiseq = tgoto(ansi_fgcol, 0, colors[c].num[0]); 46261321Sache if (ansiseq) 46361291Sache tputs(ansiseq, 1, putch); 46461178Sjoe } 46588583Sjoe if (colors[c].num[1] != -1) { 46688583Sjoe ansiseq = tgoto(ansi_bgcol, 0, colors[c].num[1]); 46761321Sache if (ansiseq) 46861291Sache tputs(ansiseq, 1, putch); 46961268Sjoe } 47061178Sjoe} 47161178Sjoe 47261321Sachestatic void 47390110Simpendcolor(int sig) 47461268Sjoe{ 47561321Sache tputs(ansi_coloff, 1, sig ? writech : putch); 47688583Sjoe tputs(attrs_off, 1, sig ? writech : putch); 47761268Sjoe} 47861268Sjoe 47961321Sachestatic int 48090110Simpcolortype(mode_t mode) 48161178Sjoe{ 48288602Sjoe switch (mode & S_IFMT) { 48388595Sjoe case S_IFDIR: 48461178Sjoe if (mode & S_IWOTH) 48588595Sjoe if (mode & S_ISTXT) 48688595Sjoe printcolor(C_WSDIR); 48788595Sjoe else 48888595Sjoe printcolor(C_WDIR); 48961178Sjoe else 49088595Sjoe printcolor(C_DIR); 49188602Sjoe return (1); 49288595Sjoe case S_IFLNK: 49361178Sjoe printcolor(C_LNK); 49488602Sjoe return (1); 49588595Sjoe case S_IFSOCK: 49661178Sjoe printcolor(C_SOCK); 49788602Sjoe return (1); 49888595Sjoe case S_IFIFO: 49961178Sjoe printcolor(C_FIFO); 50088602Sjoe return (1); 50188595Sjoe case S_IFBLK: 50261178Sjoe printcolor(C_BLK); 50388602Sjoe return (1); 50488595Sjoe case S_IFCHR: 50561178Sjoe printcolor(C_CHR); 50688602Sjoe return (1); 50761178Sjoe } 50861178Sjoe if (mode & (S_IXUSR | S_IXGRP | S_IXOTH)) { 50961178Sjoe if (mode & S_ISUID) 51088595Sjoe printcolor(C_SUID); 51161178Sjoe else if (mode & S_ISGID) 51288595Sjoe printcolor(C_SGID); 51361178Sjoe else 51488595Sjoe printcolor(C_EXEC); 51588602Sjoe return (1); 51661178Sjoe } 51788602Sjoe return (0); 51861178Sjoe} 51961178Sjoe 52061178Sjoevoid 52190110Simpparsecolors(const char *cs) 52261178Sjoe{ 52388594Sjoe int i; 52488594Sjoe int j; 52588594Sjoe int len; 52688594Sjoe char c[2]; 52788594Sjoe short legacy_warn = 0; 52861321Sache 52988586Sjoe if (cs == NULL) 53088602Sjoe cs = ""; /* LSCOLORS not set */ 53161178Sjoe len = strlen(cs); 53288602Sjoe for (i = 0; i < C_NUMCOLORS; i++) { 53388583Sjoe colors[i].bold = 0; 53488583Sjoe 53588586Sjoe if (len <= 2 * i) { 53688586Sjoe c[0] = defcolors[2 * i]; 53788586Sjoe c[1] = defcolors[2 * i + 1]; 53888602Sjoe } else { 53988586Sjoe c[0] = cs[2 * i]; 54088586Sjoe c[1] = cs[2 * i + 1]; 54161178Sjoe } 54288602Sjoe for (j = 0; j < 2; j++) { 54388583Sjoe /* Legacy colours used 0-7 */ 54488583Sjoe if (c[j] >= '0' && c[j] <= '7') { 54588583Sjoe colors[i].num[j] = c[j] - '0'; 54688583Sjoe if (!legacy_warn) { 54788583Sjoe fprintf(stderr, 54888668Sjoe "warn: LSCOLORS should use " 54988588Sjoe "characters a-h instead of 0-9 (" 55088588Sjoe "see the manual page)\n"); 55188583Sjoe } 55288583Sjoe legacy_warn = 1; 55388583Sjoe } else if (c[j] >= 'a' && c[j] <= 'h') 55488583Sjoe colors[i].num[j] = c[j] - 'a'; 55588583Sjoe else if (c[j] >= 'A' && c[j] <= 'H') { 55688583Sjoe colors[i].num[j] = c[j] - 'A'; 55788583Sjoe colors[i].bold = 1; 55888583Sjoe } else if (tolower((unsigned char)c[j] == 'x')) 55988583Sjoe colors[i].num[j] = -1; 56088583Sjoe else { 56161178Sjoe fprintf(stderr, 56288583Sjoe "error: invalid character '%c' in LSCOLORS" 56388583Sjoe " env var\n", c[j]); 56488584Sjoe colors[i].num[j] = -1; 56561178Sjoe } 56661178Sjoe } 56761178Sjoe } 56861178Sjoe} 56961291Sache 57061323Sachevoid 57190110Simpcolorquit(int sig) 57261291Sache{ 57361321Sache endcolor(sig); 57461294Sache 57588602Sjoe (void)signal(sig, SIG_DFL); 57688602Sjoe (void)kill(getpid(), sig); 57761291Sache} 57888602Sjoe 57988602Sjoe#endif /* COLORLS */ 58088602Sjoe 5811556Srgrimesstatic void 58290110Simpprintlink(FTSENT *p) 5831556Srgrimes{ 58488594Sjoe int lnklen; 58588594Sjoe char name[MAXPATHLEN + 1]; 58688594Sjoe char path[MAXPATHLEN + 1]; 5871556Srgrimes 5881556Srgrimes if (p->fts_level == FTS_ROOTLEVEL) 5891556Srgrimes (void)snprintf(name, sizeof(name), "%s", p->fts_name); 5908855Srgrimes else 5911556Srgrimes (void)snprintf(name, sizeof(name), 5921556Srgrimes "%s/%s", p->fts_parent->fts_accpath, p->fts_name); 5931556Srgrimes if ((lnklen = readlink(name, path, sizeof(path) - 1)) == -1) { 5941556Srgrimes (void)fprintf(stderr, "\nls: %s: %s\n", name, strerror(errno)); 5951556Srgrimes return; 5961556Srgrimes } 5971556Srgrimes path[lnklen] = '\0'; 59862597Sassar (void)printf(" -> "); 59990150Smarkm (void)printname(path); 6001556Srgrimes} 60188591Sjoe 60288591Sjoestatic void 60390110Simpprintsize(size_t width, off_t bytes) 60488591Sjoe{ 60588591Sjoe unit_t unit; 60688602Sjoe 60788591Sjoe if (f_humanval) { 60888591Sjoe unit = unit_adjust(&bytes); 60988591Sjoe 61088591Sjoe if (bytes == 0) 61188591Sjoe (void)printf("%*s ", width, "0B"); 61288591Sjoe else 61390150Smarkm (void)printf("%*lld%c ", width - 1, bytes, 61488602Sjoe "BKMGTPE"[unit]); 61588602Sjoe } else 61690150Smarkm (void)printf("%*lld ", width, bytes); 61788591Sjoe} 61888591Sjoe 61988591Sjoe/* 62088591Sjoe * Output in "human-readable" format. Uses 3 digits max and puts 62188591Sjoe * unit suffixes at the end. Makes output compact and easy to read, 62288591Sjoe * especially on huge disks. 62388591Sjoe * 62488591Sjoe */ 62588591Sjoeunit_t 62690110Simpunit_adjust(off_t *val) 62788591Sjoe{ 62888595Sjoe double abval; 62988595Sjoe unit_t unit; 63088595Sjoe unsigned int unit_sz; 63188591Sjoe 63290150Smarkm abval = fabs((double)*val); 63388591Sjoe 63488595Sjoe unit_sz = abval ? ilogb(abval) / 10 : 0; 63588591Sjoe 63688595Sjoe if (unit_sz >= UNIT_MAX) { 63788595Sjoe unit = NONE; 63888595Sjoe } else { 63988595Sjoe unit = unitp[unit_sz]; 64088595Sjoe *val /= (double)vals_base2[unit_sz]; 64188595Sjoe } 64288591Sjoe 64388595Sjoe return (unit); 64488591Sjoe} 645