print.c revision 102577
11558Srgrimes/* 293492Sphk * Copyright (c) 1989, 1993, 1994 393492Sphk * The Regents of the University of California. All rights reserved. 493492Sphk * 51558Srgrimes * This code is derived from software contributed to Berkeley by 693492Sphk * Michael Fischbein. 793492Sphk * 893492Sphk * Redistribution and use in source and binary forms, with or without 993492Sphk * modification, are permitted provided that the following conditions 1093492Sphk * are met: 111558Srgrimes * 1. Redistributions of source code must retain the above copyright 121558Srgrimes * notice, this list of conditions and the following disclaimer. 131558Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 141558Srgrimes * notice, this list of conditions and the following disclaimer in the 151558Srgrimes * documentation and/or other materials provided with the distribution. 161558Srgrimes * 3. All advertising materials mentioning features or use of this software 171558Srgrimes * must display the following acknowledgement: 181558Srgrimes * This product includes software developed by the University of 1993492Sphk * California, Berkeley and its contributors. 2093492Sphk * 4. Neither the name of the University nor the names of its contributors 2193492Sphk * may be used to endorse or promote products derived from this software 221558Srgrimes * without specific prior written permission. 2393492Sphk * 241558Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 251558Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2693492Sphk * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 271558Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 281558Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 291558Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 301558Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 311558Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 321558Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 331558Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3496049Sfenner * SUCH DAMAGE. 3596049Sfenner */ 3696049Sfenner 3796049Sfenner#if 0 3896049Sfenner#ifndef lint 3996049Sfennerstatic char sccsid[] = "@(#)print.c 8.4 (Berkeley) 4/17/94"; 4096049Sfenner#endif /* not lint */ 4196049Sfenner#endif 4296049Sfenner#include <sys/cdefs.h> 4396049Sfenner__FBSDID("$FreeBSD: head/bin/ls/print.c 102577 2002-08-29 14:29:09Z keramida $"); 4496049Sfenner 4596049Sfenner#include <sys/param.h> 4696049Sfenner#include <sys/stat.h> 4796049Sfenner 4896049Sfenner#include <err.h> 4996049Sfenner#include <errno.h> 5096049Sfenner#include <fts.h> 5196049Sfenner#include <math.h> 5296049Sfenner#include <langinfo.h> 5396049Sfenner#include <stdio.h> 5496049Sfenner#include <stdlib.h> 5596049Sfenner#include <string.h> 5696049Sfenner#include <time.h> 5796049Sfenner#include <unistd.h> 5896049Sfenner#ifdef COLORLS 5996049Sfenner#include <ctype.h> 6096049Sfenner#include <termcap.h> 6196049Sfenner#include <signal.h> 6296049Sfenner#endif 6396049Sfenner 6496049Sfenner#include "ls.h" 651558Srgrimes#include "extern.h" 661558Srgrimes 6795183Scharnierstatic int printaname(FTSENT *, u_long, u_long); 6895183Scharnierstatic void printlink(FTSENT *); 6995183Scharnierstatic void printtime(time_t); 7096049Sfennerstatic int printtype(u_int); 7194580Smarcelstatic void printsize(size_t, off_t); 7294580Smarcel#ifdef COLORLS 7396025Smuxstatic void endcolor(int); 7496025Smuxstatic int colortype(mode_t); 7594580Smarcel#endif 7694580Smarcel 7793492Sphk#define IS_NOPRINT(p) ((p)->fts_number == NO_PRINT) 7893492Sphk 7996025Smux#define KILO_SZ(n) (n) 8096049Sfenner#define MEGA_SZ(n) ((n) * (n)) 8194580Smarcel#define GIGA_SZ(n) ((n) * (n) * (n)) 8294580Smarcel#define TERA_SZ(n) ((n) * (n) * (n) * (n)) 8394580Smarcel#define PETA_SZ(n) ((n) * (n) * (n) * (n) * (n)) 8496049Sfenner 8593492Sphk#define KILO_2_SZ (KILO_SZ(1024ULL)) 8693492Sphk#define MEGA_2_SZ (MEGA_SZ(1024ULL)) 871558Srgrimes#define GIGA_2_SZ (GIGA_SZ(1024ULL)) 8897746Smarcel#define TERA_2_SZ (TERA_SZ(1024ULL)) 8997746Smarcel#define PETA_2_SZ (PETA_SZ(1024ULL)) 9097746Smarcel 91142533Sobrienstatic unsigned long long vals_base2[] = {1, KILO_2_SZ, MEGA_2_SZ, GIGA_2_SZ, TERA_2_SZ, PETA_2_SZ}; 92142533Sobrien 93142533Sobrientypedef enum { 94142359Sobrien NONE, KILO, MEGA, GIGA, TERA, PETA, UNIT_MAX 95133814Sru} unit_t; 96133814Srustatic unit_t unit_adjust(off_t *); 9794580Smarcel 9896049Sfennerstatic int unitp[] = {NONE, KILO, MEGA, GIGA, TERA, PETA}; 9996049Sfenner 10093492Sphk#ifdef COLORLS 10194580Smarcel/* Most of these are taken from <sys/stat.h> */ 102142359Sobrientypedef enum Colors { 1031558Srgrimes C_DIR, /* directory */ 10493717Smarcel C_LNK, /* symbolic link */ 10593492Sphk C_SOCK, /* socket */ 106142359Sobrien C_FIFO, /* pipe */ 1071558Srgrimes C_EXEC, /* executable */ 108142359Sobrien C_BLK, /* block special */ 10993492Sphk C_CHR, /* character special */ 110150818Smaxim C_SUID, /* setuid executable */ 111150818Smaxim C_SGID, /* setgid executable */ 11293717Smarcel C_WSDIR, /* directory writeble to others, with sticky 113142359Sobrien * bit */ 11493717Smarcel C_WDIR, /* directory writeble to others, without 11593717Smarcel * sticky bit */ 11693717Smarcel C_NUMCOLORS /* just a place-holder */ 11793492Sphk} Colors; 11893492Sphk 119142359Sobrienstatic const char *defcolors = "exfxcxdxbxegedabagacad"; 120142359Sobrien 121142359Sobrien/* colors for file types */ 122142359Sobrienstatic struct { 12396049Sfenner int num[2]; 124142359Sobrien int bold; 125142359Sobrien} colors[C_NUMCOLORS]; 126142359Sobrien#endif 127142533Sobrien 128142533Sobrienvoid 129142359Sobrienprintscol(DISPLAY *dp) 130142533Sobrien{ 131142533Sobrien FTSENT *p; 132142359Sobrien 133142533Sobrien for (p = dp->list; p; p = p->fts_link) { 134142359Sobrien if (IS_NOPRINT(p)) 135142359Sobrien continue; 13695039Sphk (void)printaname(p, dp->s_inode, dp->s_block); 1371558Srgrimes (void)putchar('\n'); 1381558Srgrimes } 13996049Sfenner} 14096049Sfenner 14196049Sfenner/* 14296049Sfenner * print name in current style 14396049Sfenner */ 14496049Sfennerstatic int 14596049Sfennerprintname(const char *name) 14696049Sfenner{ 14796049Sfenner if (f_octal || f_octal_escape) 148150105Srwatson return prn_octal(name); 149150105Srwatson else if (f_nonprint) 150147506Sdwhite return prn_printable(name); 15196049Sfenner else 15296049Sfenner return printf("%s", name); 15396049Sfenner} 15496049Sfenner 15596049Sfennervoid 156147506Sdwhiteprintlong(DISPLAY *dp) 15796049Sfenner{ 15896049Sfenner struct stat *sp; 15996049Sfenner FTSENT *p; 16096049Sfenner NAMES *np; 16196049Sfenner char buf[20]; 16296049Sfenner#ifdef COLORLS 163147506Sdwhite int color_printed = 0; 164147506Sdwhite#endif 16596049Sfenner 166147506Sdwhite if (dp->list->fts_level != FTS_ROOTLEVEL && (f_longform || f_size)) 167147506Sdwhite (void)printf("total %lu\n", howmany(dp->btotal, blocksize)); 168147506Sdwhite 16996049Sfenner for (p = dp->list; p; p = p->fts_link) { 17096049Sfenner if (IS_NOPRINT(p)) 17196049Sfenner continue; 172147506Sdwhite sp = p->fts_statp; 17396049Sfenner if (f_inode) 17496049Sfenner (void)printf("%*lu ", dp->s_inode, (u_long)sp->st_ino); 17596049Sfenner if (f_size) 176147506Sdwhite (void)printf("%*lld ", 17796049Sfenner dp->s_block, howmany(sp->st_blocks, blocksize)); 178147506Sdwhite strmode(sp->st_mode, buf); 17996049Sfenner np = p->fts_pointer; 18096049Sfenner (void)printf("%s %*u %-*s %-*s ", buf, dp->s_nlink, 18196049Sfenner sp->st_nlink, dp->s_user, np->user, dp->s_group, 18296025Smux np->group); 18396025Smux if (f_flags) 18496025Smux (void)printf("%-*s ", dp->s_flags, np->flags); 18596025Smux if (f_lomac) 18696025Smux (void)printf("%-*s ", dp->s_lattr, np->lattr); 187146763Sdelphij if (S_ISCHR(sp->st_mode) || S_ISBLK(sp->st_mode)) 18896025Smux if (minor(sp->st_rdev) > 255 || minor(sp->st_rdev) < 0) 18996025Smux (void)printf("%3d, 0x%08x ", 19096049Sfenner major(sp->st_rdev), 19196025Smux (u_int)minor(sp->st_rdev)); 19296025Smux else 19393717Smarcel (void)printf("%3d, %3d ", 19496049Sfenner major(sp->st_rdev), minor(sp->st_rdev)); 19596049Sfenner else if (dp->bcfile) 19696049Sfenner (void)printf("%*s%*lld ", 19796049Sfenner 8 - dp->s_size, "", dp->s_size, sp->st_size); 19896025Smux else 19996025Smux printsize(dp->s_size, sp->st_size); 20096025Smux if (f_accesstime) 20196025Smux printtime(sp->st_atime); 20296025Smux else if (f_statustime) 20396025Smux printtime(sp->st_ctime); 20496025Smux else 20596025Smux printtime(sp->st_mtime); 20696025Smux#ifdef COLORLS 20796025Smux if (f_color) 20896025Smux color_printed = colortype(sp->st_mode); 20996025Smux#endif 21096025Smux (void)printname(p->fts_name); 21196025Smux#ifdef COLORLS 21296049Sfenner if (f_color && color_printed) 21396025Smux endcolor(0); 21496049Sfenner#endif 21596049Sfenner if (f_type) 21696025Smux (void)printtype(sp->st_mode); 21796025Smux if (S_ISLNK(sp->st_mode)) 21896025Smux printlink(p); 21996025Smux (void)putchar('\n'); 22096025Smux } 22196049Sfenner} 22296049Sfenner 22396025Smuxvoid 22496025Smuxprintstream(DISPLAY *dp) 22596025Smux{ 22696049Sfenner FTSENT *p; 22796049Sfenner extern int termwidth; 22896025Smux int chcnt; 229174923Srwatson 230174923Srwatson for (p = dp->list, chcnt = 0; p; p = p->fts_link) { 231174923Srwatson if (p->fts_number == NO_PRINT) 232174923Srwatson continue; 233174923Srwatson if (strlen(p->fts_name) + chcnt + 234174923Srwatson (p->fts_link ? 2 : 0) >= (unsigned)termwidth) { 235174923Srwatson putchar('\n'); 236174923Srwatson chcnt = 0; 237174923Srwatson } 238174923Srwatson chcnt += printaname(p, dp->s_inode, dp->s_block); 239174923Srwatson if (p->fts_link) { 240174923Srwatson printf(", "); 241174923Srwatson chcnt += 2; 242174923Srwatson } 243174923Srwatson } 244174923Srwatson if (chcnt) 245174923Srwatson putchar('\n'); 246174923Srwatson} 247174923Srwatson 248174923Srwatsonvoid 249174923Srwatsonprintcol(DISPLAY *dp) 250174923Srwatson{ 251174923Srwatson extern int termwidth; 252174923Srwatson static FTSENT **array; 253174923Srwatson static int lastentries = -1; 254174923Srwatson FTSENT *p; 255174923Srwatson int base; 256174923Srwatson int chcnt; 257174923Srwatson int cnt; 258174923Srwatson int col; 259174923Srwatson int colwidth; 260174923Srwatson int endcol; 261174923Srwatson int num; 262174923Srwatson int numcols; 263174923Srwatson int numrows; 264174923Srwatson int row; 265174923Srwatson int tabwidth; 266174923Srwatson 267174923Srwatson if (f_notabs) 268174923Srwatson tabwidth = 1; 269174923Srwatson else 270174923Srwatson tabwidth = 8; 271174923Srwatson 272174923Srwatson /* 273174923Srwatson * Have to do random access in the linked list -- build a table 274174923Srwatson * of pointers. 275174923Srwatson */ 276174923Srwatson if (dp->entries > lastentries) { 277174923Srwatson lastentries = dp->entries; 278174923Srwatson if ((array = 279174923Srwatson realloc(array, dp->entries * sizeof(FTSENT *))) == NULL) { 280174923Srwatson warn(NULL); 281174923Srwatson printscol(dp); 282174923Srwatson } 283174923Srwatson } 284174923Srwatson for (p = dp->list, num = 0; p; p = p->fts_link) 285174923Srwatson if (p->fts_number != NO_PRINT) 286174923Srwatson array[num++] = p; 287174923Srwatson 288174923Srwatson colwidth = dp->maxlen; 289174923Srwatson if (f_inode) 290174923Srwatson colwidth += dp->s_inode + 1; 291174923Srwatson if (f_size) 292174923Srwatson colwidth += dp->s_block + 1; 293174923Srwatson if (f_type) 294174923Srwatson colwidth += 1; 295174923Srwatson 296174923Srwatson colwidth = (colwidth + tabwidth) & ~(tabwidth - 1); 297174923Srwatson if (termwidth < 2 * colwidth) { 298174923Srwatson printscol(dp); 299174923Srwatson return; 300174923Srwatson } 301174923Srwatson numcols = termwidth / colwidth; 302174923Srwatson numrows = num / numcols; 303174923Srwatson if (num % numcols) 304174923Srwatson ++numrows; 305174923Srwatson 306174923Srwatson if (dp->list->fts_level != FTS_ROOTLEVEL && (f_longform || f_size)) 307174923Srwatson (void)printf("total %lu\n", howmany(dp->btotal, blocksize)); 308174923Srwatson 309174923Srwatson base = 0; 310174923Srwatson for (row = 0; row < numrows; ++row) { 311174923Srwatson endcol = colwidth; 312174923Srwatson if (!f_sortacross) 313174923Srwatson base = row; 314174923Srwatson for (col = 0, chcnt = 0; col < numcols; ++col) { 315174923Srwatson chcnt += printaname(array[base], dp->s_inode, 316174923Srwatson dp->s_block); 317174923Srwatson if (f_sortacross) 318174923Srwatson base++; 319174923Srwatson else 320174923Srwatson base += numrows; 321174923Srwatson if (base >= num) 322174923Srwatson break; 323174923Srwatson while ((cnt = ((chcnt + tabwidth) & ~(tabwidth - 1))) 324174923Srwatson <= endcol) { 325174923Srwatson if (f_sortacross && col + 1 >= numcols) 326174923Srwatson break; 327174923Srwatson (void)putchar(f_notabs ? ' ' : '\t'); 328174923Srwatson chcnt = cnt; 329174923Srwatson } 330174923Srwatson endcol += colwidth; 331174923Srwatson } 332174923Srwatson (void)putchar('\n'); 333174923Srwatson } 334174923Srwatson} 335174923Srwatson 336174923Srwatson/* 337174923Srwatson * print [inode] [size] name 338174923Srwatson * return # of characters printed, no trailing characters. 339174923Srwatson */ 340174923Srwatsonstatic int 341174923Srwatsonprintaname(FTSENT *p, u_long inodefield, u_long sizefield) 342174923Srwatson{ 343174923Srwatson struct stat *sp; 344174923Srwatson int chcnt; 345174923Srwatson#ifdef COLORLS 346174923Srwatson int color_printed = 0; 347174923Srwatson#endif 348174923Srwatson 349174923Srwatson sp = p->fts_statp; 350174923Srwatson chcnt = 0; 351174923Srwatson if (f_inode) 352174923Srwatson chcnt += printf("%*lu ", (int)inodefield, (u_long)sp->st_ino); 353174923Srwatson if (f_size) 354174923Srwatson chcnt += printf("%*lld ", 355174923Srwatson (int)sizefield, howmany(sp->st_blocks, blocksize)); 356174923Srwatson#ifdef COLORLS 357174923Srwatson if (f_color) 358174923Srwatson color_printed = colortype(sp->st_mode); 359174923Srwatson#endif 360174923Srwatson chcnt += printname(p->fts_name); 361174923Srwatson#ifdef COLORLS 362174923Srwatson if (f_color && color_printed) 36393492Sphk endcolor(0); 364146763Sdelphij#endif 3651558Srgrimes if (f_type) 366174923Srwatson chcnt += printtype(sp->st_mode); 36797340Smarcel return (chcnt); 36894580Smarcel} 369174923Srwatson 37096049Sfennerstatic void 371142533Sobrienprinttime(time_t ftime) 372174923Srwatson{ 373142359Sobrien char longstring[80]; 37494580Smarcel static time_t now; 375174923Srwatson const char *format; 3768871Srgrimes static int d_first = -1; 377142359Sobrien 37896049Sfenner if (d_first < 0) 379142359Sobrien d_first = (*nl_langinfo(D_MD_ORDER) == 'd'); 38096049Sfenner if (now == 0) 38197340Smarcel now = time(NULL); 38297746Smarcel 38397340Smarcel#define SIXMONTHS ((365 / 2) * 86400) 38497340Smarcel if (f_sectime) 38597340Smarcel /* mmm dd hh:mm:ss yyyy || dd mmm hh:mm:ss yyyy */ 38697340Smarcel format = d_first ? "%e %b %T %Y " : "%b %e %T %Y "; 38797340Smarcel else if (ftime + SIXMONTHS > now && ftime < now + SIXMONTHS) 38897340Smarcel /* mmm dd hh:mm || dd mmm hh:mm */ 38994580Smarcel format = d_first ? "%e %b %R " : "%b %e %R "; 39096049Sfenner else 39194580Smarcel /* mmm dd yyyy || dd mmm yyyy */ 39294580Smarcel format = d_first ? "%e %b %Y " : "%b %e %Y "; 39393492Sphk strftime(longstring, sizeof(longstring), format, localtime(&ftime)); 39496049Sfenner fputs(longstring, stdout); 39593492Sphk} 39647095Sluoqi 39797340Smarcelstatic int 39893492Sphkprinttype(u_int mode) 39993492Sphk{ 40093492Sphk 40193492Sphk if (f_slash) { 40296049Sfenner if ((mode & S_IFMT) == S_IFDIR) { 40396049Sfenner (void)putchar('/'); 40494580Smarcel return (1); 4051558Srgrimes } 40694580Smarcel return (0); 40794580Smarcel } 40896049Sfenner 40996049Sfenner switch (mode & S_IFMT) { 41094580Smarcel case S_IFDIR: 41194580Smarcel (void)putchar('/'); 41293492Sphk return (1); 41393492Sphk case S_IFIFO: 41493492Sphk (void)putchar('|'); 41593492Sphk return (1); 41696049Sfenner case S_IFLNK: 41796049Sfenner (void)putchar('@'); 41894580Smarcel return (1); 41994580Smarcel case S_IFSOCK: 4201558Srgrimes (void)putchar('='); 421174923Srwatson return (1); 422174944Srwatson case S_IFWHT: 42394580Smarcel (void)putchar('%'); 424174923Srwatson return (1); 425174923Srwatson default: 426174923Srwatson break; 427174944Srwatson } 428174944Srwatson if (mode & (S_IXUSR | S_IXGRP | S_IXOTH)) { 429174944Srwatson (void)putchar('*'); 430174944Srwatson return (1); 431174944Srwatson } 432174944Srwatson return (0); 433174944Srwatson} 434174944Srwatson 435174944Srwatson#ifdef COLORLS 436174944Srwatsonstatic int 437174944Srwatsonputch(int c) 438174944Srwatson{ 439174944Srwatson (void)putchar(c); 440174944Srwatson return 0; 441174944Srwatson} 442174944Srwatson 443174944Srwatsonstatic int 444174944Srwatsonwritech(int c) 445174944Srwatson{ 446174944Srwatson char tmp = c; 447174944Srwatson 448174923Srwatson (void)write(STDOUT_FILENO, &tmp, 1); 44996049Sfenner return 0; 45094580Smarcel} 45196049Sfenner 452142359Sobrienstatic void 45396049Sfennerprintcolor(Colors c) 45496049Sfenner{ 45596049Sfenner char *ansiseq; 45696049Sfenner 45796049Sfenner if (colors[c].bold) 45896049Sfenner tputs(enter_bold, 1, putch); 45996049Sfenner 46096049Sfenner if (colors[c].num[0] != -1) { 46196049Sfenner ansiseq = tgoto(ansi_fgcol, 0, colors[c].num[0]); 46296049Sfenner if (ansiseq) 46396049Sfenner tputs(ansiseq, 1, putch); 46496049Sfenner } 46596049Sfenner if (colors[c].num[1] != -1) { 466174944Srwatson ansiseq = tgoto(ansi_bgcol, 0, colors[c].num[1]); 467174944Srwatson if (ansiseq) 468174944Srwatson tputs(ansiseq, 1, putch); 469174944Srwatson } 470174944Srwatson} 471174944Srwatson 472174944Srwatsonstatic void 473174944Srwatsonendcolor(int sig) 474174944Srwatson{ 4751558Srgrimes tputs(ansi_coloff, 1, sig ? writech : putch); 476142359Sobrien tputs(attrs_off, 1, sig ? writech : putch); 47794580Smarcel} 47894580Smarcel 47994580Smarcelstatic int 48094580Smarcelcolortype(mode_t mode) 48194580Smarcel{ 48296049Sfenner switch (mode & S_IFMT) { 48396049Sfenner case S_IFDIR: 48496025Smux if (mode & S_IWOTH) 485142359Sobrien if (mode & S_ISTXT) 486142359Sobrien printcolor(C_WSDIR); 487142359Sobrien else 48894580Smarcel printcolor(C_WDIR); 48993717Smarcel else 49093717Smarcel printcolor(C_DIR); 49193492Sphk return (1); 49293492Sphk case S_IFLNK: 49393492Sphk printcolor(C_LNK); 49496049Sfenner return (1); 49596049Sfenner case S_IFSOCK: 49694580Smarcel printcolor(C_SOCK); 49796025Smux return (1); 49894580Smarcel case S_IFIFO: 4991558Srgrimes printcolor(C_FIFO); 500142359Sobrien return (1); 501142359Sobrien case S_IFBLK: 502142359Sobrien printcolor(C_BLK); 503142359Sobrien return (1); 504142359Sobrien case S_IFCHR: 505142359Sobrien printcolor(C_CHR); 506142359Sobrien return (1); 507142359Sobrien } 508142359Sobrien if (mode & (S_IXUSR | S_IXGRP | S_IXOTH)) { 509142359Sobrien if (mode & S_ISUID) 51093492Sphk printcolor(C_SUID); 51196049Sfenner else if (mode & S_ISGID) 51296049Sfenner printcolor(C_SGID); 51396025Smux else 514142359Sobrien printcolor(C_EXEC); 515142359Sobrien return (1); 516142359Sobrien } 517142359Sobrien return (0); 518142359Sobrien} 51966429Sdes 52094580Smarcelvoid 521119734Sdougbparsecolors(const char *cs) 522119734Sdougb{ 523119734Sdougb int i; 524119734Sdougb int j; 525119734Sdougb int len; 526119734Sdougb char c[2]; 52796049Sfenner short legacy_warn = 0; 52896049Sfenner 52996049Sfenner if (cs == NULL) 53096049Sfenner cs = ""; /* LSCOLORS not set */ 53194580Smarcel len = strlen(cs); 53296049Sfenner for (i = 0; i < C_NUMCOLORS; i++) { 53396049Sfenner colors[i].bold = 0; 53496025Smux 53596025Smux if (len <= 2 * i) { 53696025Smux c[0] = defcolors[2 * i]; 53796025Smux c[1] = defcolors[2 * i + 1]; 53896049Sfenner } else { 539147506Sdwhite c[0] = cs[2 * i]; 540147506Sdwhite c[1] = cs[2 * i + 1]; 54196049Sfenner } 54296049Sfenner for (j = 0; j < 2; j++) { 54394580Smarcel /* Legacy colours used 0-7 */ 544142359Sobrien if (c[j] >= '0' && c[j] <= '7') { 54594580Smarcel colors[i].num[j] = c[j] - '0'; 54694580Smarcel if (!legacy_warn) { 54793492Sphk fprintf(stderr, 54896049Sfenner "warn: LSCOLORS should use " 54996025Smux "characters a-h instead of 0-9 (" 55094580Smarcel "see the manual page)\n"); 5511558Srgrimes } 55296049Sfenner legacy_warn = 1; 55396049Sfenner } else if (c[j] >= 'a' && c[j] <= 'h') 554174923Srwatson colors[i].num[j] = c[j] - 'a'; 555174923Srwatson else if (c[j] >= 'A' && c[j] <= 'H') { 556174923Srwatson colors[i].num[j] = c[j] - 'A'; 55796049Sfenner colors[i].bold = 1; 558174923Srwatson } else if (tolower((unsigned char)c[j] == 'x')) 559174923Srwatson colors[i].num[j] = -1; 560174923Srwatson else { 56196049Sfenner fprintf(stderr, 56296049Sfenner "error: invalid character '%c' in LSCOLORS" 563174923Srwatson " env var\n", c[j]); 56494580Smarcel colors[i].num[j] = -1; 56596025Smux } 56694580Smarcel } 56793492Sphk } 56896049Sfenner} 56996049Sfenner 57093492Sphkvoid 57194580Smarcelcolorquit(int sig) 572170054Skevlo{ 573170054Skevlo endcolor(sig); 574170054Skevlo 575170054Skevlo (void)signal(sig, SIG_DFL); 576170054Skevlo (void)kill(getpid(), sig); 577170054Skevlo} 57894580Smarcel 579142359Sobrien#endif /* COLORLS */ 58094580Smarcel 581142359Sobrienstatic void 58296049Sfennerprintlink(FTSENT *p) 58394580Smarcel{ 58496049Sfenner int lnklen; 585174923Srwatson char name[MAXPATHLEN + 1]; 58694580Smarcel char path[MAXPATHLEN + 1]; 587174923Srwatson 588174923Srwatson if (p->fts_level == FTS_ROOTLEVEL) 589174923Srwatson (void)snprintf(name, sizeof(name), "%s", p->fts_name); 59094580Smarcel else 591174923Srwatson (void)snprintf(name, sizeof(name), 592174923Srwatson "%s/%s", p->fts_parent->fts_accpath, p->fts_name); 593174923Srwatson if ((lnklen = readlink(name, path, sizeof(path) - 1)) == -1) { 59494580Smarcel (void)fprintf(stderr, "\nls: %s: %s\n", name, strerror(errno)); 59567264Sdes return; 59696049Sfenner } 59796049Sfenner path[lnklen] = '\0'; 59896049Sfenner (void)printf(" -> "); 59996049Sfenner (void)printname(path); 600174923Srwatson} 60196049Sfenner 60296049Sfennerstatic void 60396049Sfennerprintsize(size_t width, off_t bytes) 60496025Smux{ 60594580Smarcel unit_t unit; 60694580Smarcel 60796049Sfenner if (f_humanval) { 60894580Smarcel unit = unit_adjust(&bytes); 60996049Sfenner 61094580Smarcel if (bytes == 0) 61194580Smarcel (void)printf("%*s ", width, "0B"); 61296049Sfenner else 61396049Sfenner (void)printf("%*lld%c ", width - 1, bytes, 61494580Smarcel "BKMGTPE"[unit]); 61594580Smarcel } else 61694580Smarcel (void)printf("%*lld ", width, bytes); 61796049Sfenner} 61896049Sfenner 61994580Smarcel/* 62094580Smarcel * Output in "human-readable" format. Uses 3 digits max and puts 62194580Smarcel * unit suffixes at the end. Makes output compact and easy to read, 62294580Smarcel * especially on huge disks. 62396049Sfenner * 62496049Sfenner */ 62594580Smarcelunit_t 62696049Sfennerunit_adjust(off_t *val) 62794580Smarcel{ 6281558Srgrimes double abval; 6291558Srgrimes unit_t unit; 63093492Sphk unsigned int unit_sz; 63193492Sphk 6321558Srgrimes abval = fabs((double)*val); 633141611Sru 634141611Sru unit_sz = abval ? ilogb(abval) / 10 : 0; 635141611Sru 636141611Sru if (unit_sz >= UNIT_MAX) { 63793492Sphk unit = NONE; 6381558Srgrimes } else { 6391558Srgrimes unit = unitp[unit_sz]; 64018914Sfenner *val /= (double)vals_base2[unit_sz]; 64193492Sphk } 6421558Srgrimes 643146763Sdelphij return (unit); 644142533Sobrien} 64593492Sphk