Convert ls(1) to use libxo(3).

Obtained from:	Phil Shafer <phil@juniper.net>
Sponsored by:	Juniper Networks, Inc.
This commit is contained in:
Marcel Moolenaar 2015-06-10 01:27:38 +00:00
parent 458f2175ca
commit 52e4a08c45
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=284198
6 changed files with 190 additions and 104 deletions

View File

@ -10,7 +10,7 @@ LIBADD= util
.if !defined(RELEASE_CRUNCH) && \
${MK_LS_COLORS} != no
CFLAGS+= -DCOLORLS
LIBADD+= termcapw
LIBADD+= termcapw xo
.endif
.include <bsd.prog.mk>

View File

@ -45,14 +45,17 @@ int revsizecmp(const FTSENT *, const FTSENT *);
void printcol(const DISPLAY *);
void printlong(const DISPLAY *);
int printname(const char *);
int printname(const char *, const char *);
void printscol(const DISPLAY *);
void printstream(const DISPLAY *);
void usage(void);
int prn_normal(const char *);
int prn_normal(const char *, const char *);
char * getname(const char *);
size_t len_octal(const char *, int);
int prn_octal(const char *);
int prn_printable(const char *);
int prn_octal(const char *, const char *);
char * get_octal(const char *);
int prn_printable(const char *, const char *);
char * get_printable(const char *);
#ifdef COLORLS
void parsecolors(const char *cs);
void colorquit(int);

View File

@ -32,7 +32,7 @@
.\" @(#)ls.1 8.7 (Berkeley) 7/29/94
.\" $FreeBSD$
.\"
.Dd April 4, 2014
.Dd June 8, 2015
.Dt LS 1
.Os
.Sh NAME
@ -40,6 +40,7 @@
.Nd list directory contents
.Sh SYNOPSIS
.Nm
.Op Fl -libxo
.Op Fl ABCFGHILPRSTUWZabcdfghiklmnopqrstuwxy1,
.Op Fl D Ar format
.Op Ar
@ -797,9 +798,11 @@ specification.
.Xr getfacl 1 ,
.Xr sort 1 ,
.Xr xterm 1 ,
.Xr libxo 3 ,
.Xr localeconv 3 ,
.Xr strftime 3 ,
.Xr strmode 3 ,
.Xr xo_parse_args 3 ,
.Xr termcap 5 ,
.Xr maclabel 7 ,
.Xr sticky 7 ,

View File

@ -66,6 +66,7 @@ __FBSDID("$FreeBSD$");
#include <termcap.h>
#include <signal.h>
#endif
#include <libxo/xo.h>
#include "ls.h"
#include "extern.h"
@ -185,6 +186,12 @@ main(int argc, char *argv[])
fts_options = FTS_PHYSICAL;
if (getenv("LS_SAMESORT"))
f_samesort = 1;
argc = xo_parse_args(argc, argv);
if (argc < 0)
return (1);
xo_set_flags(NULL, XOF_COLUMNS);
while ((ch = getopt(argc, argv,
"1ABCD:FGHILPRSTUWXZabcdfghiklmnopqrstuwxy,")) != -1) {
switch (ch) {
@ -381,7 +388,7 @@ main(int argc, char *argv[])
f_color = 1;
}
#else
warnx("color support not compiled in");
xo_warnx("color support not compiled in");
#endif /*COLORLS*/
#ifdef COLORLS
@ -479,10 +486,13 @@ main(int argc, char *argv[])
else
printfcn = printcol;
xo_open_container("file-information");
if (argc)
traverse(argc, argv, fts_options);
else
traverse(1, dotav, fts_options);
xo_close_container("file-information");
xo_finish();
exit(rval);
}
@ -500,10 +510,11 @@ traverse(int argc, char *argv[], int options)
FTS *ftsp;
FTSENT *p, *chp;
int ch_options;
int first = 1;
if ((ftsp =
fts_open(argv, options, f_nosort ? NULL : mastercmp)) == NULL)
err(1, "fts_open");
xo_err(1, "fts_open");
/*
* We ignore errors from fts_children here since they will be
@ -525,11 +536,11 @@ traverse(int argc, char *argv[], int options)
while ((p = fts_read(ftsp)) != NULL)
switch (p->fts_info) {
case FTS_DC:
warnx("%s: directory causes a cycle", p->fts_name);
xo_warnx("%s: directory causes a cycle", p->fts_name);
break;
case FTS_DNR:
case FTS_ERR:
warnx("%s: %s", p->fts_path, strerror(p->fts_errno));
xo_warnx("%s: %s", p->fts_path, strerror(p->fts_errno));
rval = 1;
break;
case FTS_D:
@ -537,31 +548,40 @@ traverse(int argc, char *argv[], int options)
p->fts_name[0] == '.' && !f_listdot)
break;
if (first) {
first = 0;
xo_open_list("directory");
}
xo_open_instance("directory");
/*
* If already output something, put out a newline as
* a separator. If multiple arguments, precede each
* directory with its name.
*/
if (output) {
putchar('\n');
(void)printname(p->fts_path);
puts(":");
xo_emit("\n");
(void)printname("path", p->fts_path);
xo_emit(":\n");
} else if (argc > 1) {
(void)printname(p->fts_path);
puts(":");
(void)printname("path", p->fts_path);
xo_emit(":\n");
output = 1;
}
chp = fts_children(ftsp, ch_options);
display(p, chp, options);
xo_close_instance("directory");
if (!f_recursive && chp != NULL)
(void)fts_set(ftsp, p, FTS_SKIP);
break;
default:
break;
}
if (!first)
xo_close_list("directory");
if (errno)
err(1, "fts_read");
xo_err(1, "fts_read");
}
/*
@ -608,7 +628,7 @@ display(const FTSENT *p, FTSENT *list, int options)
/* Fill-in "::" as "0:0:0" for the sake of scanf. */
jinitmax = malloc(strlen(initmax) * 2 + 2);
if (jinitmax == NULL)
err(1, "malloc");
xo_err(1, "malloc");
initmax2 = jinitmax;
if (*initmax == ':')
strcpy(initmax2, "0:"), initmax2 += 2;
@ -679,7 +699,7 @@ display(const FTSENT *p, FTSENT *list, int options)
flags = NULL;
for (cur = list, entries = 0; cur; cur = cur->fts_link) {
if (cur->fts_info == FTS_ERR || cur->fts_info == FTS_NS) {
warnx("%s: %s",
xo_warnx("%s: %s",
cur->fts_name, strerror(cur->fts_errno));
cur->fts_number = NO_PRINT;
rval = 1;
@ -745,7 +765,7 @@ display(const FTSENT *p, FTSENT *list, int options)
flags = strdup("-");
}
if (flags == NULL)
err(1, "fflagstostr");
xo_err(1, "fflagstostr");
flen = strlen(flags);
if (flen > (size_t)maxflags)
maxflags = flen;
@ -759,7 +779,7 @@ display(const FTSENT *p, FTSENT *list, int options)
error = mac_prepare_file_label(&label);
if (error == -1) {
warn("MAC label for %s/%s",
xo_warn("MAC label for %s/%s",
cur->fts_parent->fts_path,
cur->fts_name);
goto label_out;
@ -780,7 +800,7 @@ display(const FTSENT *p, FTSENT *list, int options)
error = mac_get_link(name,
label);
if (error == -1) {
warn("MAC label for %s/%s",
xo_warn("MAC label for %s/%s",
cur->fts_parent->fts_path,
cur->fts_name);
mac_free(label);
@ -790,7 +810,7 @@ display(const FTSENT *p, FTSENT *list, int options)
error = mac_to_text(label,
&labelstr);
if (error == -1) {
warn("MAC label for %s/%s",
xo_warn("MAC label for %s/%s",
cur->fts_parent->fts_path,
cur->fts_name);
mac_free(label);
@ -808,7 +828,7 @@ display(const FTSENT *p, FTSENT *list, int options)
if ((np = malloc(sizeof(NAMES) + labelstrlen +
ulen + glen + flen + 4)) == NULL)
err(1, "malloc");
xo_err(1, "malloc");
np->user = &np->data[0];
(void)strcpy(np->user, user);

View File

@ -58,6 +58,7 @@ __FBSDID("$FreeBSD$");
#include <termcap.h>
#include <signal.h>
#endif
#include <libxo/xo.h>
#include "ls.h"
#include "extern.h"
@ -65,9 +66,9 @@ __FBSDID("$FreeBSD$");
static int printaname(const FTSENT *, u_long, u_long);
static void printdev(size_t, dev_t);
static void printlink(const FTSENT *);
static void printtime(time_t);
static void printtime(const char *, time_t);
static int printtype(u_int);
static void printsize(size_t, off_t);
static void printsize(const char *, size_t, off_t);
#ifdef COLORLS
static void endcolor(int);
static int colortype(mode_t);
@ -109,26 +110,46 @@ printscol(const DISPLAY *dp)
{
FTSENT *p;
xo_open_list("entry");
for (p = dp->list; p; p = p->fts_link) {
if (IS_NOPRINT(p))
continue;
xo_open_instance("entry");
(void)printaname(p, dp->s_inode, dp->s_block);
(void)putchar('\n');
xo_close_instance("entry");
xo_emit("\n");
}
xo_close_list("entry");
}
/*
* print name in current style
*/
int
printname(const char *name)
printname(const char *field, const char *name)
{
char fmt[BUFSIZ];
char *s = getname(name);
int rc;
snprintf(fmt, sizeof(fmt), "{:%s/%%hs}", field);
rc = xo_emit(fmt, s);
free(s);
return rc;
}
/*
* print name in current style
*/
char *
getname(const char *name)
{
if (f_octal || f_octal_escape)
return prn_octal(name);
return get_octal(name);
else if (f_nonprint)
return prn_printable(name);
return get_printable(name);
else
return prn_normal(name);
return strdup(name);
}
void
@ -144,46 +165,59 @@ printlong(const DISPLAY *dp)
if ((dp->list == NULL || dp->list->fts_level != FTS_ROOTLEVEL) &&
(f_longform || f_size)) {
(void)printf("total %lu\n", howmany(dp->btotal, blocksize));
xo_emit("{L:total} {:total-blocks/%lu}\n",
howmany(dp->btotal, blocksize));
}
xo_open_list("entry");
for (p = dp->list; p; p = p->fts_link) {
char *name;
if (IS_NOPRINT(p))
continue;
xo_open_instance("entry");
sp = p->fts_statp;
name = getname(p->fts_name);
if (name)
xo_emit("{ke:name}", name);
if (f_inode)
(void)printf("%*ju ",
xo_emit("{:inode/%*ju} ",
dp->s_inode, (uintmax_t)sp->st_ino);
if (f_size)
(void)printf("%*jd ",
xo_emit("{:blocks/%*jd} ",
dp->s_block, howmany(sp->st_blocks, blocksize));
strmode(sp->st_mode, buf);
aclmode(buf, p);
np = p->fts_pointer;
(void)printf("%s %*u %-*s %-*s ", buf, dp->s_nlink,
sp->st_nlink, dp->s_user, np->user, dp->s_group,
np->group);
xo_attr("value", "%03o", (int) sp->st_mode & ALLPERMS);
xo_emit("{t:mode/%s} {:links/%*u} {:user/%-*s} {:group/%-*s} ",
buf, dp->s_nlink, sp->st_nlink,
dp->s_user, np->user, dp->s_group, np->group);
if (f_flags)
(void)printf("%-*s ", dp->s_flags, np->flags);
xo_emit("{:flags/%-*s} ", dp->s_flags, np->flags);
if (f_label)
(void)printf("%-*s ", dp->s_label, np->label);
xo_emit("{:label/%-*s} ", dp->s_label, np->label);
if (S_ISCHR(sp->st_mode) || S_ISBLK(sp->st_mode))
printdev(dp->s_size, sp->st_rdev);
else
printsize(dp->s_size, sp->st_size);
printsize("size", dp->s_size, sp->st_size);
if (f_accesstime)
printtime(sp->st_atime);
printtime("access-time", sp->st_atime);
else if (f_birthtime)
printtime(sp->st_birthtime);
printtime("birth-time", sp->st_birthtime);
else if (f_statustime)
printtime(sp->st_ctime);
printtime("change-time", sp->st_ctime);
else
printtime(sp->st_mtime);
printtime("modify-time", sp->st_mtime);
#ifdef COLORLS
if (f_color)
color_printed = colortype(sp->st_mode);
#endif
(void)printname(p->fts_name);
if (name) {
xo_emit("{dk:name}", name);
free(name);
}
#ifdef COLORLS
if (f_color && color_printed)
endcolor(0);
@ -192,8 +226,10 @@ printlong(const DISPLAY *dp)
(void)printtype(sp->st_mode);
if (S_ISLNK(sp->st_mode))
printlink(p);
(void)putchar('\n');
xo_close_instance("entry");
xo_emit("\n");
}
xo_close_list("entry");
}
void
@ -208,17 +244,17 @@ printstream(const DISPLAY *dp)
/* XXX strlen does not take octal escapes into account. */
if (strlen(p->fts_name) + chcnt +
(p->fts_link ? 2 : 0) >= (unsigned)termwidth) {
putchar('\n');
xo_emit("\n");
chcnt = 0;
}
chcnt += printaname(p, dp->s_inode, dp->s_block);
if (p->fts_link) {
printf(", ");
xo_emit(", ");
chcnt += 2;
}
}
if (chcnt)
putchar('\n');
xo_emit("\n");
}
void
@ -252,7 +288,7 @@ printcol(const DISPLAY *dp)
if (dp->entries > lastentries) {
if ((narray =
realloc(array, dp->entries * sizeof(FTSENT *))) == NULL) {
warn(NULL);
xo_warn(NULL);
printscol(dp);
return;
}
@ -283,17 +319,21 @@ printcol(const DISPLAY *dp)
if ((dp->list == NULL || dp->list->fts_level != FTS_ROOTLEVEL) &&
(f_longform || f_size)) {
(void)printf("total %lu\n", howmany(dp->btotal, blocksize));
xo_emit("{L:total} {:total-blocks/%lu}\n",
howmany(dp->btotal, blocksize));
}
xo_open_list("entry");
base = 0;
for (row = 0; row < numrows; ++row) {
endcol = colwidth;
if (!f_sortacross)
base = row;
for (col = 0, chcnt = 0; col < numcols; ++col) {
xo_open_instance("entry");
chcnt += printaname(array[base], dp->s_inode,
dp->s_block);
xo_close_instance("entry");
if (f_sortacross)
base++;
else
@ -304,13 +344,14 @@ printcol(const DISPLAY *dp)
<= endcol) {
if (f_sortacross && col + 1 >= numcols)
break;
(void)putchar(f_notabs ? ' ' : '\t');
xo_emit(f_notabs ? " " : "\t");
chcnt = cnt;
}
endcol += colwidth;
}
(void)putchar('\n');
xo_emit("\n");
}
xo_close_list("entry");
}
/*
@ -329,16 +370,16 @@ printaname(const FTSENT *p, u_long inodefield, u_long sizefield)
sp = p->fts_statp;
chcnt = 0;
if (f_inode)
chcnt += printf("%*ju ",
chcnt += xo_emit("{:inode/%*ju} ",
(int)inodefield, (uintmax_t)sp->st_ino);
if (f_size)
chcnt += printf("%*jd ",
chcnt += xo_emit("{:size/%*jd} ",
(int)sizefield, howmany(sp->st_blocks, blocksize));
#ifdef COLORLS
if (f_color)
color_printed = colortype(sp->st_mode);
#endif
chcnt += printname(p->fts_name);
chcnt += printname("name", p->fts_name);
#ifdef COLORLS
if (f_color && color_printed)
endcolor(0);
@ -354,14 +395,14 @@ printaname(const FTSENT *p, u_long inodefield, u_long sizefield)
static void
printdev(size_t width, dev_t dev)
{
(void)printf("%#*jx ", (u_int)width, (uintmax_t)dev);
xo_emit("{:device/%#*jx} ", (u_int)width, (uintmax_t)dev);
}
static void
printtime(time_t ftime)
printtime(const char *field, time_t ftime)
{
char longstring[80];
char fmt[BUFSIZ];
static time_t now = 0;
const char *format;
static int d_first = -1;
@ -384,8 +425,10 @@ printtime(time_t ftime)
/* mmm dd yyyy || dd mmm yyyy */
format = d_first ? "%e %b %Y" : "%b %e %Y";
strftime(longstring, sizeof(longstring), format, localtime(&ftime));
fputs(longstring, stdout);
fputc(' ', stdout);
snprintf(fmt, sizeof(fmt), "{:%s/%%s} ", field);
xo_attr("value", "%ld", (long) ftime);
xo_emit(fmt, longstring);
}
static int
@ -394,7 +437,7 @@ printtype(u_int mode)
if (f_slash) {
if ((mode & S_IFMT) == S_IFDIR) {
(void)putchar('/');
xo_emit("{D:\\/}{e:type/directory}");
return (1);
}
return (0);
@ -402,25 +445,25 @@ printtype(u_int mode)
switch (mode & S_IFMT) {
case S_IFDIR:
(void)putchar('/');
xo_emit("{D:/\\/}{e:type/directory}");
return (1);
case S_IFIFO:
(void)putchar('|');
xo_emit("{D:|}{e:type/fifo}");
return (1);
case S_IFLNK:
(void)putchar('@');
xo_emit("{D:@}{e:type/link}");
return (1);
case S_IFSOCK:
(void)putchar('=');
xo_emit("{D:=}{e:type/socket}");
return (1);
case S_IFWHT:
(void)putchar('%');
xo_emit("{D:%}{e:type/whiteout}");
return (1);
default:
break;
}
if (mode & (S_IXUSR | S_IXGRP | S_IXOTH)) {
(void)putchar('*');
xo_emit("{D:*}{e:executable/}");
return (1);
}
return (0);
@ -430,7 +473,7 @@ printtype(u_int mode)
static int
putch(int c)
{
(void)putchar(c);
xo_emit("{D:/%c}", c);
return 0;
}
@ -539,7 +582,7 @@ parsecolors(const char *cs)
if (c[j] >= '0' && c[j] <= '7') {
colors[i].num[j] = c[j] - '0';
if (!legacy_warn) {
warnx("LSCOLORS should use "
xo_warnx("LSCOLORS should use "
"characters a-h instead of 0-9 ("
"see the manual page)");
}
@ -552,7 +595,7 @@ parsecolors(const char *cs)
} else if (tolower((unsigned char)c[j]) == 'x')
colors[i].num[j] = -1;
else {
warnx("invalid character '%c' in LSCOLORS"
xo_warnx("invalid character '%c' in LSCOLORS"
" env var", c[j]);
colors[i].num[j] = -1;
}
@ -584,18 +627,19 @@ printlink(const FTSENT *p)
(void)snprintf(name, sizeof(name),
"%s/%s", p->fts_parent->fts_accpath, p->fts_name);
if ((lnklen = readlink(name, path, sizeof(path) - 1)) == -1) {
(void)fprintf(stderr, "\nls: %s: %s\n", name, strerror(errno));
xo_error("\nls: %s: %s\n", name, strerror(errno));
return;
}
path[lnklen] = '\0';
(void)printf(" -> ");
(void)printname(path);
xo_emit(" -> ");
(void)printname("target", path);
}
static void
printsize(size_t width, off_t bytes)
printsize(const char *field, size_t width, off_t bytes)
{
char fmt[BUFSIZ];
if (f_humanval) {
/*
* Reserve one space before the size and allocate room for
@ -605,13 +649,15 @@ printsize(size_t width, off_t bytes)
humanize_number(buf, sizeof(buf), (int64_t)bytes, "",
HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL);
(void)printf("%*s ", (u_int)width, buf);
} else if (f_thousands) { /* with commas */
snprintf(fmt, sizeof(fmt), "{:%s/%%%ds} ", field, (int) width);
xo_attr("value", "%jd", (intmax_t) bytes);
xo_emit(fmt, buf);
} else { /* with commas */
/* This format assignment needed to work round gcc bug. */
const char *format = "%*j'd ";
(void)printf(format, (u_int)width, bytes);
} else
(void)printf("%*jd ", (u_int)width, bytes);
snprintf(fmt, sizeof(fmt), "{:%s/%%%dj%sd} ",
field, (int) width, f_thousands ? "'" : "");
xo_emit(fmt, (intmax_t) bytes);
}
}
/*
@ -654,7 +700,7 @@ aclmode(char *buf, const FTSENT *p)
type = ACL_TYPE_NFS4;
supports_acls = 1;
} else if (ret < 0 && errno != EINVAL) {
warn("%s", name);
xo_warn("%s", name);
return;
}
if (supports_acls == 0) {
@ -663,7 +709,7 @@ aclmode(char *buf, const FTSENT *p)
type = ACL_TYPE_ACCESS;
supports_acls = 1;
} else if (ret < 0 && errno != EINVAL) {
warn("%s", name);
xo_warn("%s", name);
return;
}
}
@ -672,12 +718,12 @@ aclmode(char *buf, const FTSENT *p)
return;
facl = acl_get_link_np(name, type);
if (facl == NULL) {
warn("%s", name);
xo_warn("%s", name);
return;
}
if (acl_is_trivial_np(facl, &trivial)) {
acl_free(facl);
warn("%s", name);
xo_warn("%s", name);
return;
}
if (!trivial)

View File

@ -50,13 +50,19 @@ __FBSDID("$FreeBSD$");
#include <string.h>
#include <wchar.h>
#include <wctype.h>
#include <libxo/xo.h>
#include "ls.h"
#include "extern.h"
int
prn_normal(const char *s)
prn_normal(const char *field, const char *s)
{
char fmt[_POSIX2_LINE_MAX];
snprintf(fmt, sizeof(fmt), "{:%s/%%hs}", field);
return xo_emit(fmt, s);
#if 0
mbstate_t mbs;
wchar_t wc;
int i, n;
@ -83,43 +89,47 @@ prn_normal(const char *s)
n += wcwidth(wc);
}
return (n);
#endif
}
int
prn_printable(const char *s)
char *
get_printable(const char *s)
{
mbstate_t mbs;
wchar_t wc;
int i, n;
size_t clen;
int slen = strlen(s);
char *buf = alloca(slen + 1), *bp = buf;
memset(&mbs, 0, sizeof(mbs));
n = 0;
while ((clen = mbrtowc(&wc, s, MB_LEN_MAX, &mbs)) != 0) {
if (clen == (size_t)-1) {
putchar('?');
*bp++ = '?';
s++;
n++;
memset(&mbs, 0, sizeof(mbs));
continue;
}
if (clen == (size_t)-2) {
putchar('?');
*bp++ = '?';
n++;
break;
}
if (!iswprint(wc)) {
putchar('?');
*bp++ = '?';
s += clen;
n++;
continue;
}
for (i = 0; i < (int)clen; i++)
putchar((unsigned char)s[i]);
*bp++ = (unsigned char)s[i];
s += clen;
n += wcwidth(wc);
}
return (n);
*bp = '\0';
return strdup(buf);
}
/*
@ -165,8 +175,8 @@ len_octal(const char *s, int len)
return (r);
}
int
prn_octal(const char *s)
char *
get_octal(const char *s)
{
static const char esc[] = "\\\\\"\"\aa\bb\ff\nn\rr\tt\vv";
const char *p;
@ -175,6 +185,8 @@ prn_octal(const char *s)
size_t clen;
unsigned char ch;
int goodchar, i, len, prtlen;
int slen = strlen(s);
char *buf = alloca(slen * 4 + 1), *bp = buf;
memset(&mbs, 0, sizeof(mbs));
len = 0;
@ -182,7 +194,7 @@ prn_octal(const char *s)
goodchar = clen != (size_t)-1 && clen != (size_t)-2;
if (goodchar && iswprint(wc) && wc != L'\"' && wc != L'\\') {
for (i = 0; i < (int)clen; i++)
putchar((unsigned char)s[i]);
*bp++ = (unsigned char)s[i];
len += wcwidth(wc);
} else if (goodchar && f_octal_escape &&
#if WCHAR_MIN < 0
@ -190,8 +202,8 @@ prn_octal(const char *s)
#endif
wc <= (wchar_t)UCHAR_MAX &&
(p = strchr(esc, (char)wc)) != NULL) {
putchar('\\');
putchar(p[1]);
*bp ++ = '\\';
*bp++ = p[1];
len += 2;
} else {
if (goodchar)
@ -202,10 +214,10 @@ prn_octal(const char *s)
prtlen = strlen(s);
for (i = 0; i < prtlen; i++) {
ch = (unsigned char)s[i];
putchar('\\');
putchar('0' + (ch >> 6));
putchar('0' + ((ch >> 3) & 7));
putchar('0' + (ch & 7));
*bp++ = '\\';
*bp++ = '0' + (ch >> 6);
*bp++ = '0' + ((ch >> 3) & 7);
*bp++ = '0' + (ch & 7);
len += 4;
}
}
@ -217,13 +229,15 @@ prn_octal(const char *s)
} else
s += clen;
}
return (len);
*bp = '\0';
return strdup(buf);
}
void
usage(void)
{
(void)fprintf(stderr,
xo_error(
#ifdef COLORLS
"usage: ls [-ABCFGHILPRSTUWZabcdfghiklmnopqrstuwxy1,] [-D format]"
#else