17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
52236845bSakaplan * Common Development and Distribution License (the "License").
62236845bSakaplan * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
215e1c72e1SJason King
225e1c72e1SJason King /*
2327dd1e87SMark Shellenbaum * Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved.
2491bbe3fdSBill Pijewski * Copyright (c) 2012, Joyent, Inc. All rights reserved.
25b9c81738SGary Mills * Copyright 2015 Gary Mills
26*fab57d1bSGordon Ross * Copyright 2016 Nexenta Systems, Inc. All rights reserved.
276027b860SPeter Tribble * Copyright 2020 Peter Tribble
285e1c72e1SJason King */
295e1c72e1SJason King
307c478bd9Sstevel@tonic-gate /*
310a055120SJason King * Copyright 2017 Jason King. All rights reserved.
327c478bd9Sstevel@tonic-gate * Use is subject to license terms.
337c478bd9Sstevel@tonic-gate */
347c478bd9Sstevel@tonic-gate
357c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
361418cdc0SToomas Soome /* All Rights Reserved */
377c478bd9Sstevel@tonic-gate
387c478bd9Sstevel@tonic-gate /* Copyright (c) 1987, 1988 Microsoft Corporation */
397c478bd9Sstevel@tonic-gate /* All Rights Reserved */
407c478bd9Sstevel@tonic-gate
417c478bd9Sstevel@tonic-gate /*
427c478bd9Sstevel@tonic-gate * List files or directories
437c478bd9Sstevel@tonic-gate */
447c478bd9Sstevel@tonic-gate
457c478bd9Sstevel@tonic-gate #include <sys/param.h>
467c478bd9Sstevel@tonic-gate #include <sys/types.h>
477c478bd9Sstevel@tonic-gate #include <sys/mkdev.h>
487c478bd9Sstevel@tonic-gate #include <sys/stat.h>
497c478bd9Sstevel@tonic-gate #include <sys/acl.h>
507c478bd9Sstevel@tonic-gate
517c478bd9Sstevel@tonic-gate #include <wchar.h>
527c478bd9Sstevel@tonic-gate #include <stdio.h>
537c478bd9Sstevel@tonic-gate #include <ctype.h>
547c478bd9Sstevel@tonic-gate #include <dirent.h>
557c478bd9Sstevel@tonic-gate #include <string.h>
567c478bd9Sstevel@tonic-gate #include <locale.h>
577c478bd9Sstevel@tonic-gate #include <curses.h>
585e1c72e1SJason King #include <term.h>
597c478bd9Sstevel@tonic-gate #include <termios.h>
607c478bd9Sstevel@tonic-gate #include <stdlib.h>
617c478bd9Sstevel@tonic-gate #include <widec.h>
627c478bd9Sstevel@tonic-gate #include <locale.h>
637c478bd9Sstevel@tonic-gate #include <wctype.h>
647c478bd9Sstevel@tonic-gate #include <pwd.h>
657c478bd9Sstevel@tonic-gate #include <grp.h>
667c478bd9Sstevel@tonic-gate #include <limits.h>
677c478bd9Sstevel@tonic-gate #include <fcntl.h>
687c478bd9Sstevel@tonic-gate #include <unistd.h>
697c478bd9Sstevel@tonic-gate #include <libgen.h>
707c478bd9Sstevel@tonic-gate #include <errno.h>
71fa9e4066Sahrens #include <aclutils.h>
72da6c28aaSamw #include <libnvpair.h>
73da6c28aaSamw #include <libcmdutils.h>
74da6c28aaSamw #include <attr.h>
755e1c72e1SJason King #include <getopt.h>
765e1c72e1SJason King #include <inttypes.h>
777c478bd9Sstevel@tonic-gate
787c478bd9Sstevel@tonic-gate #ifndef STANDALONE
797c478bd9Sstevel@tonic-gate #define TERMINFO
807c478bd9Sstevel@tonic-gate #endif
817c478bd9Sstevel@tonic-gate
827c478bd9Sstevel@tonic-gate /*
837c478bd9Sstevel@tonic-gate * -DNOTERMINFO can be defined on the cc command line to prevent
847c478bd9Sstevel@tonic-gate * the use of terminfo. This should be done on systems not having
85da6c28aaSamw * the terminfo feature(pre 6.0 systems ?).
867c478bd9Sstevel@tonic-gate * As a result, columnar listings assume 80 columns for output,
877c478bd9Sstevel@tonic-gate * unless told otherwise via the COLUMNS environment variable.
887c478bd9Sstevel@tonic-gate */
897c478bd9Sstevel@tonic-gate #ifdef NOTERMINFO
907c478bd9Sstevel@tonic-gate #undef TERMINFO
917c478bd9Sstevel@tonic-gate #endif
927c478bd9Sstevel@tonic-gate
937c478bd9Sstevel@tonic-gate #include <term.h>
947c478bd9Sstevel@tonic-gate
957c478bd9Sstevel@tonic-gate #define BFSIZE 16
967c478bd9Sstevel@tonic-gate /* this bit equals 1 in lflags of structure lbuf if *namep is to be used */
977c478bd9Sstevel@tonic-gate #define ISARG 0100000
987c478bd9Sstevel@tonic-gate
997c478bd9Sstevel@tonic-gate /*
1007c478bd9Sstevel@tonic-gate * this flag has been added to manipulate the display of S instead of 'l' when
1017c478bd9Sstevel@tonic-gate * the file is not a regular file and when group execution bit is off
1027c478bd9Sstevel@tonic-gate */
1037c478bd9Sstevel@tonic-gate #define LS_NOTREG 010000
1047c478bd9Sstevel@tonic-gate
1057c478bd9Sstevel@tonic-gate
1067c478bd9Sstevel@tonic-gate /*
1077c478bd9Sstevel@tonic-gate * Date and time formats
1087c478bd9Sstevel@tonic-gate *
1097c478bd9Sstevel@tonic-gate * b --- abbreviated month name
1107c478bd9Sstevel@tonic-gate * e --- day number
1117c478bd9Sstevel@tonic-gate * Y --- year in the form ccyy
1127c478bd9Sstevel@tonic-gate * H --- hour(24-hour version)
1137c478bd9Sstevel@tonic-gate * M --- minute
1147c478bd9Sstevel@tonic-gate * F --- yyyy-mm-dd
1157c478bd9Sstevel@tonic-gate * T --- hh:mm:ss
1167c478bd9Sstevel@tonic-gate * z --- time zone as hours displacement from UTC
1177c478bd9Sstevel@tonic-gate * note that %F and %z are from the ISO C99 standard and are
1187c478bd9Sstevel@tonic-gate * not present in older C libraries
1197c478bd9Sstevel@tonic-gate */
1205e1c72e1SJason King #define FORMAT_OLD " %b %e %Y "
1215e1c72e1SJason King #define FORMAT_NEW " %b %e %H:%M "
1225e1c72e1SJason King #define FORMAT_LONG " %b %e %T %Y "
1235e1c72e1SJason King #define FORMAT_ISO_FULL " %%F %%T.%.09ld %%z "
1245e1c72e1SJason King #define FORMAT_ISO_LONG " %F %R "
1255e1c72e1SJason King #define FORMAT_ISO_NEW " %m-%d %H:%M "
1265e1c72e1SJason King #define FORMAT_ISO_OLD " %F "
1277c478bd9Sstevel@tonic-gate
1287c478bd9Sstevel@tonic-gate #undef BUFSIZ
1297c478bd9Sstevel@tonic-gate #define BUFSIZ 4096
1307c478bd9Sstevel@tonic-gate #define FMTSIZE 50
1317c478bd9Sstevel@tonic-gate
1327c478bd9Sstevel@tonic-gate struct ditem {
1337c478bd9Sstevel@tonic-gate dev_t dev; /* directory items device number */
1347c478bd9Sstevel@tonic-gate ino_t ino; /* directory items inode number */
1357c478bd9Sstevel@tonic-gate struct ditem *parent; /* dir items ptr to its parent's info */
1367c478bd9Sstevel@tonic-gate };
137da6c28aaSamw /* Holds boolean extended system attributes */
138da6c28aaSamw struct attrb {
139da6c28aaSamw char *name;
140da6c28aaSamw };
141da6c28aaSamw /* Holds timestamp extended system attributes */
142da6c28aaSamw struct attrtm {
143da6c28aaSamw char *name;
144da6c28aaSamw uint64_t stm;
145da6c28aaSamw uint64_t nstm;
146da6c28aaSamw };
1477c478bd9Sstevel@tonic-gate
1485e1c72e1SJason King #define LSA_NONE (0)
1495e1c72e1SJason King #define LSA_BOLD (1L << 0)
1505e1c72e1SJason King #define LSA_UNDERSCORE (1L << 1)
1515e1c72e1SJason King #define LSA_BLINK (1L << 2)
1525e1c72e1SJason King #define LSA_REVERSE (1L << 3)
1535e1c72e1SJason King #define LSA_CONCEALED (1L << 4)
1545e1c72e1SJason King
1555e1c72e1SJason King /* these should be ordered most general to most specific */
1565e1c72e1SJason King typedef enum LS_CFTYPE {
1575e1c72e1SJason King LS_NORMAL,
1585e1c72e1SJason King LS_FILE,
1595e1c72e1SJason King LS_EXEC,
1605e1c72e1SJason King LS_DIR,
1615e1c72e1SJason King LS_LINK,
1625e1c72e1SJason King LS_FIFO,
1635e1c72e1SJason King LS_SOCK,
1645e1c72e1SJason King LS_DOOR,
1655e1c72e1SJason King LS_BLK,
1665e1c72e1SJason King LS_CHR,
1675e1c72e1SJason King LS_PORT,
1685e1c72e1SJason King LS_STICKY,
1695e1c72e1SJason King LS_ORPHAN,
1705e1c72e1SJason King LS_SETGID,
1715e1c72e1SJason King LS_SETUID,
1725e1c72e1SJason King LS_OTHER_WRITABLE,
1735e1c72e1SJason King LS_STICKY_OTHER_WRITABLE,
1745e1c72e1SJason King LS_PAT
1755e1c72e1SJason King } ls_cftype_t;
1765e1c72e1SJason King
1771b628248SJason King typedef struct {
1785e1c72e1SJason King char *sfx;
1795e1c72e1SJason King ls_cftype_t ftype;
1805e1c72e1SJason King int attr;
1815e1c72e1SJason King int fg;
1825e1c72e1SJason King int bg;
1835e1c72e1SJason King } ls_color_t;
1845e1c72e1SJason King
1851b628248SJason King struct lbuf {
1861b628248SJason King union {
1871b628248SJason King char lname[MAXNAMLEN]; /* used for filename in a directory */
1881b628248SJason King char *namep; /* for name in ls-command; */
1891b628248SJason King } ln;
1901b628248SJason King char ltype; /* filetype */
1911b628248SJason King ino_t lnum; /* inode number of file */
1921418cdc0SToomas Soome mode_t lflags; /* 0777 bits used as r,w,x permissions */
1931b628248SJason King nlink_t lnl; /* number of links to file */
1941b628248SJason King uid_t luid;
1951b628248SJason King gid_t lgid;
1961b628248SJason King off_t lsize; /* filesize or major/minor dev numbers */
1971b628248SJason King blkcnt_t lblocks; /* number of file blocks */
1981b628248SJason King timestruc_t lmtime;
1991b628248SJason King timestruc_t lat;
2001b628248SJason King timestruc_t lct;
2011b628248SJason King timestruc_t lmt;
2021b628248SJason King char *flinkto; /* symbolic link contents */
2031418cdc0SToomas Soome char acl; /* indicate there are additional acl entries */
2041b628248SJason King int cycle; /* cycle detected flag */
2051b628248SJason King struct ditem *ancinfo; /* maintains ancestor info */
2061b628248SJason King acl_t *aclp; /* ACL if present */
2071b628248SJason King struct attrb *exttr; /* boolean extended system attributes */
2081b628248SJason King struct attrtm *extm; /* timestamp extended system attributes */
2091b628248SJason King ls_color_t *color; /* color for entry */
2101b628248SJason King ls_color_t *link_color; /* color for symlink */
2111b628248SJason King };
2121b628248SJason King
2131b628248SJason King struct dchain {
2141b628248SJason King char *dc_name; /* path name */
2151b628248SJason King int cycle_detected; /* cycle detected visiting this directory */
2161b628248SJason King struct ditem *myancinfo; /* this directory's ancestry info */
2171b628248SJason King struct dchain *dc_next; /* next directory in the chain */
2181b628248SJason King };
2191b628248SJason King
2207c478bd9Sstevel@tonic-gate static struct dchain *dfirst; /* start of the dir chain */
2217c478bd9Sstevel@tonic-gate static struct dchain *cdfirst; /* start of the current dir chain */
2227c478bd9Sstevel@tonic-gate static struct dchain *dtemp; /* temporary - used for linking */
2237c478bd9Sstevel@tonic-gate static char *curdir; /* the current directory */
2247c478bd9Sstevel@tonic-gate
2257c478bd9Sstevel@tonic-gate static int first = 1; /* true if first line is not yet printed */
2267c478bd9Sstevel@tonic-gate static int nfiles = 0; /* number of flist entries in current use */
2277c478bd9Sstevel@tonic-gate static int nargs = 0; /* number of flist entries used for arguments */
2287c478bd9Sstevel@tonic-gate static int maxfils = 0; /* number of flist/lbuf entries allocated */
2297c478bd9Sstevel@tonic-gate static int maxn = 0; /* number of flist entries with lbufs asigned */
2307c478bd9Sstevel@tonic-gate static int quantn = 64; /* allocation growth quantum */
2317c478bd9Sstevel@tonic-gate
2327c478bd9Sstevel@tonic-gate static struct lbuf *nxtlbf; /* ptr to next lbuf to be assigned */
2337c478bd9Sstevel@tonic-gate static struct lbuf **flist; /* ptr to list of lbuf pointers */
2347c478bd9Sstevel@tonic-gate static struct lbuf *gstat(char *, int, struct ditem *);
2357c478bd9Sstevel@tonic-gate static char *getname(uid_t);
2367c478bd9Sstevel@tonic-gate static char *getgroup(gid_t);
237*fab57d1bSGordon Ross static char *getusid(uid_t);
238*fab57d1bSGordon Ross static char *getgsid(gid_t);
2397c478bd9Sstevel@tonic-gate static char *makename(char *, char *);
2407c478bd9Sstevel@tonic-gate static void pentry(struct lbuf *);
2417c478bd9Sstevel@tonic-gate static void column(void);
2427c478bd9Sstevel@tonic-gate static void pmode(mode_t aflag);
2437c478bd9Sstevel@tonic-gate static void selection(int *);
2447c478bd9Sstevel@tonic-gate static void new_line(void);
2457c478bd9Sstevel@tonic-gate static void rddir(char *, struct ditem *);
2467c478bd9Sstevel@tonic-gate static int strcol(unsigned char *);
2477c478bd9Sstevel@tonic-gate static void pem(struct lbuf **, struct lbuf **, int);
2487c478bd9Sstevel@tonic-gate static void pdirectory(char *, int, int, int, struct ditem *);
2497c478bd9Sstevel@tonic-gate static struct cachenode *findincache(struct cachenode **, long);
2507c478bd9Sstevel@tonic-gate static void csi_pprintf(unsigned char *);
2517c478bd9Sstevel@tonic-gate static void pprintf(char *, char *);
2527c478bd9Sstevel@tonic-gate static int compar(struct lbuf **pp1, struct lbuf **pp2);
2537c478bd9Sstevel@tonic-gate static void record_ancestry(char *, struct stat *, struct lbuf *,
2547c478bd9Sstevel@tonic-gate int, struct ditem *);
2555e1c72e1SJason King static void ls_color_init(void);
2561b628248SJason King static ls_color_t *ls_color_find(const char *, mode_t);
2571b628248SJason King static void ls_start_color(ls_color_t *);
2585e1c72e1SJason King static void ls_end_color(void);
2597c478bd9Sstevel@tonic-gate
2607c478bd9Sstevel@tonic-gate static int aflg;
2617c478bd9Sstevel@tonic-gate static int atflg;
2627c478bd9Sstevel@tonic-gate static int bflg;
2637c478bd9Sstevel@tonic-gate static int cflg;
2647c478bd9Sstevel@tonic-gate static int dflg;
2657c478bd9Sstevel@tonic-gate static int eflg;
2667c478bd9Sstevel@tonic-gate static int fflg;
2677c478bd9Sstevel@tonic-gate static int gflg;
2687c478bd9Sstevel@tonic-gate static int hflg;
2697c478bd9Sstevel@tonic-gate static int iflg;
2707c478bd9Sstevel@tonic-gate static int lflg;
2717c478bd9Sstevel@tonic-gate static int mflg;
2727c478bd9Sstevel@tonic-gate static int nflg;
2737c478bd9Sstevel@tonic-gate static int oflg;
2747c478bd9Sstevel@tonic-gate static int pflg;
2757c478bd9Sstevel@tonic-gate static int qflg;
2767c478bd9Sstevel@tonic-gate static int rflg = 1; /* init to 1 for special use in compar */
2777c478bd9Sstevel@tonic-gate static int sflg;
2787c478bd9Sstevel@tonic-gate static int tflg;
2797c478bd9Sstevel@tonic-gate static int uflg;
2805e1c72e1SJason King static int Uflg;
2815e1c72e1SJason King static int wflg;
2827c478bd9Sstevel@tonic-gate static int xflg;
2837c478bd9Sstevel@tonic-gate static int Aflg;
2845e1c72e1SJason King static int Bflg;
2857c478bd9Sstevel@tonic-gate static int Cflg;
2867c478bd9Sstevel@tonic-gate static int Eflg;
2877c478bd9Sstevel@tonic-gate static int Fflg;
2887c478bd9Sstevel@tonic-gate static int Hflg;
2897c478bd9Sstevel@tonic-gate static int Lflg;
2907c478bd9Sstevel@tonic-gate static int Rflg;
2917c478bd9Sstevel@tonic-gate static int Sflg;
292fa9e4066Sahrens static int vflg;
2935a5eeccaSmarks static int Vflg;
294da6c28aaSamw static int saflg; /* boolean extended system attr. */
295da6c28aaSamw static int sacnt; /* number of extended system attr. */
296da6c28aaSamw static int copt;
297da6c28aaSamw static int vopt;
298da6c28aaSamw static int tmflg; /* create time ext. system attr. */
299da6c28aaSamw static int ctm;
300da6c28aaSamw static int atm;
301da6c28aaSamw static int mtm;
302da6c28aaSamw static int crtm;
303da6c28aaSamw static int alltm;
3040a055120SJason King static uint_t nicenum_flags;
3057c478bd9Sstevel@tonic-gate static mode_t flags;
3067c478bd9Sstevel@tonic-gate static int err = 0; /* Contains return code */
3075e1c72e1SJason King static int colorflg;
3085e1c72e1SJason King static int file_typeflg;
30991bbe3fdSBill Pijewski static int noflist = 0;
3107c478bd9Sstevel@tonic-gate
3117c478bd9Sstevel@tonic-gate static uid_t lastuid = (uid_t)-1;
3127c478bd9Sstevel@tonic-gate static gid_t lastgid = (gid_t)-1;
3137c478bd9Sstevel@tonic-gate static char *lastuname = NULL;
3147c478bd9Sstevel@tonic-gate static char *lastgname = NULL;
3157c478bd9Sstevel@tonic-gate
3165e1c72e1SJason King /* statreq > 0 if any of sflg, (n)lflg, tflg, Sflg, colorflg are on */
3177c478bd9Sstevel@tonic-gate static int statreq;
3187c478bd9Sstevel@tonic-gate
3195e1c72e1SJason King static uint64_t block_size = 1;
3207c478bd9Sstevel@tonic-gate static char *dotp = ".";
3217c478bd9Sstevel@tonic-gate
3221418cdc0SToomas Soome static u_longlong_t tblocks; /* number of blocks of files in a directory */
3236027b860SPeter Tribble static time_t year, now, starttime;
3247c478bd9Sstevel@tonic-gate
3257c478bd9Sstevel@tonic-gate static int num_cols = 80;
3267c478bd9Sstevel@tonic-gate static int colwidth;
3277c478bd9Sstevel@tonic-gate static int filewidth;
3287c478bd9Sstevel@tonic-gate static int fixedwidth;
3297c478bd9Sstevel@tonic-gate static int nomocore;
3307c478bd9Sstevel@tonic-gate static int curcol;
3317c478bd9Sstevel@tonic-gate
3327c478bd9Sstevel@tonic-gate static struct winsize win;
3337c478bd9Sstevel@tonic-gate
3345e1c72e1SJason King /* if time_fmt_new is left NULL, time_fmt_old is used for all times */
3355e1c72e1SJason King static const char *time_fmt_old = FORMAT_OLD; /* non-recent files */
3365e1c72e1SJason King static const char *time_fmt_new = FORMAT_NEW; /* recent files */
3375e1c72e1SJason King static int time_custom; /* != 0 if a custom format */
338da6c28aaSamw static char time_buf[FMTSIZE]; /* array to hold day and time */
3397c478bd9Sstevel@tonic-gate
3405e1c72e1SJason King static int lsc_debug;
3415e1c72e1SJason King static ls_color_t *lsc_match;
3425e1c72e1SJason King static ls_color_t *lsc_colors;
3435e1c72e1SJason King static size_t lsc_ncolors;
3445e1c72e1SJason King static char *lsc_bold;
3455e1c72e1SJason King static char *lsc_underline;
3465e1c72e1SJason King static char *lsc_blink;
3475e1c72e1SJason King static char *lsc_reverse;
3485e1c72e1SJason King static char *lsc_concealed;
3495e1c72e1SJason King static char *lsc_none;
3505e1c72e1SJason King static char *lsc_setfg;
3515e1c72e1SJason King static char *lsc_setbg;
3521b628248SJason King static ls_color_t *lsc_orphan;
3535e1c72e1SJason King
3547c478bd9Sstevel@tonic-gate #define NOTWORKINGDIR(d, l) (((l) < 2) || \
3557c478bd9Sstevel@tonic-gate (strcmp((d) + (l) - 2, "/.") != 0))
3567c478bd9Sstevel@tonic-gate
3577c478bd9Sstevel@tonic-gate #define NOTPARENTDIR(d, l) (((l) < 3) || \
3587c478bd9Sstevel@tonic-gate (strcmp((d) + (l) - 3, "/..") != 0))
359da6c28aaSamw /* Extended system attributes support */
360da6c28aaSamw static int get_sysxattr(char *, struct lbuf *);
361da6c28aaSamw static void set_sysattrb_display(char *, boolean_t, struct lbuf *);
362da6c28aaSamw static void set_sysattrtm_display(char *, struct lbuf *);
3635e1c72e1SJason King static void format_time(time_t, time_t);
364da6c28aaSamw static void print_time(struct lbuf *);
365da6c28aaSamw static void format_attrtime(struct lbuf *);
366da6c28aaSamw static void *xmalloc(size_t, struct lbuf *);
367da6c28aaSamw static void free_sysattr(struct lbuf *);
368da6c28aaSamw static nvpair_t *pair;
369da6c28aaSamw static nvlist_t *response;
37056798e90Sbasabi static int acl_err;
3717c478bd9Sstevel@tonic-gate
3725e1c72e1SJason King const struct option long_options[] = {
3735e1c72e1SJason King { "all", no_argument, NULL, 'a' },
3745e1c72e1SJason King { "almost-all", no_argument, NULL, 'A' },
3755e1c72e1SJason King { "escape", no_argument, NULL, 'b' },
3765e1c72e1SJason King { "classify", no_argument, NULL, 'F' },
3775e1c72e1SJason King { "human-readable", no_argument, NULL, 'h' },
3785e1c72e1SJason King { "dereference", no_argument, NULL, 'L' },
3795e1c72e1SJason King { "dereference-command-line", no_argument, NULL, 'H' },
3805e1c72e1SJason King { "ignore-backups", no_argument, NULL, 'B' },
3815e1c72e1SJason King { "inode", no_argument, NULL, 'i' },
3825e1c72e1SJason King { "numeric-uid-gid", no_argument, NULL, 'n' },
3835e1c72e1SJason King { "no-group", no_argument, NULL, 'o' },
3845e1c72e1SJason King { "hide-control-chars", no_argument, NULL, 'q' },
3855e1c72e1SJason King { "reverse", no_argument, NULL, 'r' },
3865e1c72e1SJason King { "recursive", no_argument, NULL, 'R' },
3875e1c72e1SJason King { "size", no_argument, NULL, 's' },
3885e1c72e1SJason King { "width", required_argument, NULL, 'w' },
3895e1c72e1SJason King
3905e1c72e1SJason King /* no short options for these */
3915e1c72e1SJason King { "block-size", required_argument, NULL, 0 },
3925e1c72e1SJason King { "full-time", no_argument, NULL, 0 },
3935e1c72e1SJason King { "si", no_argument, NULL, 0 },
3945e1c72e1SJason King { "color", optional_argument, NULL, 0 },
3955e1c72e1SJason King { "colour", optional_argument, NULL, 0},
3965e1c72e1SJason King { "file-type", no_argument, NULL, 0 },
3975e1c72e1SJason King { "time-style", required_argument, NULL, 0 },
3985e1c72e1SJason King
3995e1c72e1SJason King {0, 0, 0, 0}
4005e1c72e1SJason King };
4015e1c72e1SJason King
4027c478bd9Sstevel@tonic-gate int
main(int argc,char * argv[])4037c478bd9Sstevel@tonic-gate main(int argc, char *argv[])
4047c478bd9Sstevel@tonic-gate {
4057c478bd9Sstevel@tonic-gate int c;
4067c478bd9Sstevel@tonic-gate int i;
4077c478bd9Sstevel@tonic-gate int width;
4087c478bd9Sstevel@tonic-gate int amino = 0;
4097c478bd9Sstevel@tonic-gate int opterr = 0;
4105e1c72e1SJason King int option_index = 0;
4117c478bd9Sstevel@tonic-gate struct lbuf *ep;
4127c478bd9Sstevel@tonic-gate struct lbuf lb;
41329e6ab97SIgor Kozhukhov struct ditem *myinfo = NULL;
4147c478bd9Sstevel@tonic-gate
4157c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, "");
4167c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
4177c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */
4187c478bd9Sstevel@tonic-gate #endif
4197c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN);
4207c478bd9Sstevel@tonic-gate #ifdef STANDALONE
4217c478bd9Sstevel@tonic-gate if (argv[0][0] == '\0')
4227c478bd9Sstevel@tonic-gate argc = getargv("ls", &argv, 0);
4237c478bd9Sstevel@tonic-gate #endif
4247c478bd9Sstevel@tonic-gate
4256027b860SPeter Tribble lb.lmtime.tv_sec = starttime = time(NULL);
4267c478bd9Sstevel@tonic-gate lb.lmtime.tv_nsec = 0;
4277c478bd9Sstevel@tonic-gate year = lb.lmtime.tv_sec - 6L*30L*24L*60L*60L; /* 6 months ago */
4287c478bd9Sstevel@tonic-gate now = lb.lmtime.tv_sec + 60;
4297c478bd9Sstevel@tonic-gate if (isatty(1)) {
4307c478bd9Sstevel@tonic-gate Cflg = 1;
4317c478bd9Sstevel@tonic-gate mflg = 0;
4327c478bd9Sstevel@tonic-gate }
4337c478bd9Sstevel@tonic-gate
4345e1c72e1SJason King while ((c = getopt_long(argc, argv,
4355e1c72e1SJason King "+aAbBcCdeEfFghHiklLmnopqrRsStuUw:x1@vV/:%:", long_options,
4365e1c72e1SJason King &option_index)) != -1)
4377c478bd9Sstevel@tonic-gate switch (c) {
4385e1c72e1SJason King case 0:
4395e1c72e1SJason King /* non-short options */
4405e1c72e1SJason King if (strcmp(long_options[option_index].name,
4415e1c72e1SJason King "color") == 0 ||
4425e1c72e1SJason King strcmp(long_options[option_index].name,
4435e1c72e1SJason King "colour") == 0) {
4445e1c72e1SJason King if (optarg == NULL ||
4455e1c72e1SJason King strcmp(optarg, "always") == 0 ||
4465e1c72e1SJason King strcmp(optarg, "yes") == 0 ||
4475e1c72e1SJason King strcmp(optarg, "force") == 0) {
4485e1c72e1SJason King colorflg++;
4495e1c72e1SJason King statreq++;
4505e1c72e1SJason King continue;
4515e1c72e1SJason King }
4525e1c72e1SJason King
453c7a7d03cSJason King if (strcmp(optarg, "auto") == 0 ||
4545e1c72e1SJason King strcmp(optarg, "tty") == 0 ||
455c7a7d03cSJason King strcmp(optarg, "if-tty") == 0) {
456c7a7d03cSJason King if (isatty(1) == 1) {
457c7a7d03cSJason King colorflg++;
458c7a7d03cSJason King statreq++;
459c7a7d03cSJason King }
4605e1c72e1SJason King continue;
4615e1c72e1SJason King }
4625e1c72e1SJason King
4635e1c72e1SJason King if (strcmp(optarg, "never") == 0 ||
4645e1c72e1SJason King strcmp(optarg, "no") == 0 ||
4655e1c72e1SJason King strcmp(optarg, "none") == 0) {
4665e1c72e1SJason King colorflg = 0;
4675e1c72e1SJason King continue;
4685e1c72e1SJason King }
4695e1c72e1SJason King (void) fprintf(stderr,
4705e1c72e1SJason King gettext("Invalid argument '%s' for "
4715e1c72e1SJason King "--color\n"), optarg);
4725e1c72e1SJason King ++opterr;
4735e1c72e1SJason King continue;
4745e1c72e1SJason King }
4755e1c72e1SJason King
4765e1c72e1SJason King if (strcmp(long_options[option_index].name,
4775e1c72e1SJason King "si") == 0) {
4785e1c72e1SJason King hflg++;
4790a055120SJason King nicenum_flags |= NN_DIVISOR_1000;
4805e1c72e1SJason King continue;
4815e1c72e1SJason King }
4825e1c72e1SJason King
4835e1c72e1SJason King if (strcmp(long_options[option_index].name,
4845e1c72e1SJason King "block-size") == 0) {
4855e1c72e1SJason King size_t scale_len = strlen(optarg);
4865e1c72e1SJason King uint64_t scale = 1;
4875e1c72e1SJason King uint64_t kilo = 1024;
4885e1c72e1SJason King char scale_c;
4895e1c72e1SJason King
4905e1c72e1SJason King if (scale_len == 0) {
4915e1c72e1SJason King (void) fprintf(stderr, gettext(
4925e1c72e1SJason King "Invalid block size \'%s\'\n"),
4935e1c72e1SJason King optarg);
4945e1c72e1SJason King exit(1);
4955e1c72e1SJason King }
4965e1c72e1SJason King
4975e1c72e1SJason King scale_c = optarg[scale_len - 1];
4985e1c72e1SJason King if (scale_c == 'B') {
4995e1c72e1SJason King /* need at least digit, scale, B */
5005e1c72e1SJason King if (scale_len < 3) {
5015e1c72e1SJason King (void) fprintf(stderr, gettext(
5025e1c72e1SJason King "Invalid block size "
5035e1c72e1SJason King "\'%s\'\n"), optarg);
5045e1c72e1SJason King exit(1);
5055e1c72e1SJason King }
5065e1c72e1SJason King kilo = 1000;
5075e1c72e1SJason King scale_c = optarg[scale_len - 2];
5085e1c72e1SJason King if (isdigit(scale_c)) {
5095e1c72e1SJason King (void) fprintf(stderr,
5105e1c72e1SJason King gettext("Invalid block size"
5115e1c72e1SJason King " \'%s\'\n"), optarg);
5125e1c72e1SJason King exit(1);
5135e1c72e1SJason King }
5145e1c72e1SJason King /*
5155e1c72e1SJason King * make optarg[scale_len - 1] point to
5165e1c72e1SJason King * the scale factor
5175e1c72e1SJason King */
5185e1c72e1SJason King --scale_len;
5195e1c72e1SJason King }
5205e1c72e1SJason King
5215e1c72e1SJason King switch (scale_c) {
5225e1c72e1SJason King case 'y':
5235e1c72e1SJason King case 'Y':
5245e1c72e1SJason King scale *= kilo;
5255e1c72e1SJason King /*FALLTHROUGH*/
5265e1c72e1SJason King case 'Z':
5275e1c72e1SJason King case 'z':
5285e1c72e1SJason King scale *= kilo;
5295e1c72e1SJason King /*FALLTHROUGH*/
5305e1c72e1SJason King case 'E':
5315e1c72e1SJason King case 'e':
5325e1c72e1SJason King scale *= kilo;
5335e1c72e1SJason King /*FALLTHROUGH*/
5345e1c72e1SJason King case 'P':
5355e1c72e1SJason King case 'p':
5365e1c72e1SJason King scale *= kilo;
5375e1c72e1SJason King /*FALLTHROUGH*/
5385e1c72e1SJason King case 'T':
5395e1c72e1SJason King case 't':
5405e1c72e1SJason King scale *= kilo;
5415e1c72e1SJason King /*FALLTHROUGH*/
5425e1c72e1SJason King case 'G':
5435e1c72e1SJason King case 'g':
5445e1c72e1SJason King scale *= kilo;
5455e1c72e1SJason King /*FALLTHROUGH*/
5465e1c72e1SJason King case 'M':
5475e1c72e1SJason King case 'm':
5485e1c72e1SJason King scale *= kilo;
5495e1c72e1SJason King /*FALLTHROUGH*/
5505e1c72e1SJason King case 'K':
5515e1c72e1SJason King case 'k':
5525e1c72e1SJason King scale *= kilo;
5535e1c72e1SJason King break;
5545e1c72e1SJason King default:
5555e1c72e1SJason King if (!isdigit(scale_c)) {
5565e1c72e1SJason King (void) fprintf(stderr,
5575e1c72e1SJason King gettext("Invalid character "
5585e1c72e1SJason King "following block size in "
5595e1c72e1SJason King "\'%s\'\n"), optarg);
5605e1c72e1SJason King exit(1);
5615e1c72e1SJason King }
5625e1c72e1SJason King }
5635e1c72e1SJason King
5645e1c72e1SJason King /* NULL out scale constant if present */
5655e1c72e1SJason King if (scale > 1 && !isdigit(scale_c))
5665e1c72e1SJason King optarg[scale_len - 1] = '\0';
5675e1c72e1SJason King
5685e1c72e1SJason King /* Based on testing, this is what GNU ls does */
5695e1c72e1SJason King block_size = strtoll(optarg, NULL, 0) * scale;
5705e1c72e1SJason King if (block_size < 1) {
5715e1c72e1SJason King (void) fprintf(stderr,
5725e1c72e1SJason King gettext("Invalid block size "
5735e1c72e1SJason King "\'%s\'\n"), optarg);
5745e1c72e1SJason King exit(1);
5755e1c72e1SJason King }
5765e1c72e1SJason King continue;
5775e1c72e1SJason King }
5785e1c72e1SJason King
5795e1c72e1SJason King if (strcmp(long_options[option_index].name,
5805e1c72e1SJason King "file-type") == 0) {
5815e1c72e1SJason King file_typeflg++;
5825e1c72e1SJason King Fflg++;
5835e1c72e1SJason King statreq++;
5845e1c72e1SJason King continue;
5855e1c72e1SJason King }
5865e1c72e1SJason King
5875e1c72e1SJason King
5885e1c72e1SJason King if (strcmp(long_options[option_index].name,
5895e1c72e1SJason King "full-time") == 0) {
5905e1c72e1SJason King Eflg++;
5915e1c72e1SJason King statreq++;
5925e1c72e1SJason King eflg = 0;
5935e1c72e1SJason King time_fmt_old = FORMAT_ISO_FULL;
5945e1c72e1SJason King time_fmt_new = FORMAT_ISO_FULL;
5955e1c72e1SJason King continue;
5965e1c72e1SJason King }
5975e1c72e1SJason King
5985e1c72e1SJason King if (strcmp(long_options[option_index].name,
5995e1c72e1SJason King "time-style") == 0) {
6005e1c72e1SJason King /* like -E, but doesn't imply -l */
6015e1c72e1SJason King if (strcmp(optarg, "full-iso") == 0) {
6025e1c72e1SJason King Eflg++;
6035e1c72e1SJason King statreq++;
6045e1c72e1SJason King eflg = 0;
6055e1c72e1SJason King time_fmt_old = FORMAT_ISO_FULL;
6065e1c72e1SJason King time_fmt_new = FORMAT_ISO_FULL;
6075e1c72e1SJason King continue;
6085e1c72e1SJason King }
6095e1c72e1SJason King if (strcmp(optarg, "long-iso") == 0) {
6105e1c72e1SJason King statreq++;
6115e1c72e1SJason King Eflg = 0;
6125e1c72e1SJason King eflg = 0;
6135e1c72e1SJason King time_fmt_old = FORMAT_ISO_LONG;
6145e1c72e1SJason King time_fmt_new = FORMAT_ISO_LONG;
6155e1c72e1SJason King continue;
6165e1c72e1SJason King }
6175e1c72e1SJason King if (strcmp(optarg, "iso") == 0) {
6185e1c72e1SJason King statreq++;
6195e1c72e1SJason King Eflg = 0;
6205e1c72e1SJason King eflg = 0;
6215e1c72e1SJason King time_fmt_old = FORMAT_ISO_OLD;
6225e1c72e1SJason King time_fmt_new = FORMAT_ISO_NEW;
6235e1c72e1SJason King continue;
6245e1c72e1SJason King }
6255e1c72e1SJason King /* should be the default */
6265e1c72e1SJason King if (strcmp(optarg, "locale") == 0) {
6275e1c72e1SJason King time_fmt_old = FORMAT_OLD;
6285e1c72e1SJason King time_fmt_new = FORMAT_NEW;
6295e1c72e1SJason King continue;
6305e1c72e1SJason King }
6315e1c72e1SJason King if (optarg[0] == '+') {
6325e1c72e1SJason King char *told, *tnew;
6335e1c72e1SJason King char *p;
6345e1c72e1SJason King size_t timelen = strlen(optarg);
6355e1c72e1SJason King
6365e1c72e1SJason King p = strchr(optarg, '\n');
6375e1c72e1SJason King if (p != NULL)
6385e1c72e1SJason King *p++ = '\0';
6395e1c72e1SJason King
6405e1c72e1SJason King /*
6415e1c72e1SJason King * Time format requires a leading and
6425e1c72e1SJason King * trailing space
6435e1c72e1SJason King * Add room for 3 spaces + 2 nulls
6445e1c72e1SJason King * The + in optarg is replaced with
6455e1c72e1SJason King * a space.
6465e1c72e1SJason King */
6475e1c72e1SJason King timelen += 2 + 3;
6485e1c72e1SJason King told = malloc(timelen);
6495e1c72e1SJason King if (told == NULL) {
65038f2a414SAlbert Lee perror("ls");
65138f2a414SAlbert Lee exit(2);
6525e1c72e1SJason King }
6535e1c72e1SJason King
6545e1c72e1SJason King (void) memset(told, 0, timelen);
6555e1c72e1SJason King told[0] = ' ';
6565e1c72e1SJason King (void) strlcat(told, &optarg[1],
6575e1c72e1SJason King timelen);
6585e1c72e1SJason King (void) strlcat(told, " ", timelen);
6595e1c72e1SJason King
6605e1c72e1SJason King if (p != NULL) {
6615e1c72e1SJason King size_t tnew_len;
6625e1c72e1SJason King
6635e1c72e1SJason King tnew = told + strlen(told) + 1;
6645e1c72e1SJason King tnew_len = timelen -
6655e1c72e1SJason King strlen(told) - 1;
6665e1c72e1SJason King
6675e1c72e1SJason King tnew[0] = ' ';
6685e1c72e1SJason King (void) strlcat(tnew, p,
6695e1c72e1SJason King tnew_len);
6705e1c72e1SJason King (void) strlcat(tnew, " ",
6715e1c72e1SJason King tnew_len);
6725e1c72e1SJason King time_fmt_new =
6735e1c72e1SJason King (const char *)tnew;
6745e1c72e1SJason King } else {
6755e1c72e1SJason King time_fmt_new =
6765e1c72e1SJason King (const char *)told;
6775e1c72e1SJason King }
6785e1c72e1SJason King
6795e1c72e1SJason King time_fmt_old = (const char *)told;
6805e1c72e1SJason King time_custom = 1;
6815e1c72e1SJason King continue;
6825e1c72e1SJason King }
6835e1c72e1SJason King continue;
6845e1c72e1SJason King }
6855e1c72e1SJason King
6865e1c72e1SJason King continue;
6875e1c72e1SJason King
6887c478bd9Sstevel@tonic-gate case 'a':
6897c478bd9Sstevel@tonic-gate aflg++;
6907c478bd9Sstevel@tonic-gate continue;
6917c478bd9Sstevel@tonic-gate case 'A':
6927c478bd9Sstevel@tonic-gate Aflg++;
6937c478bd9Sstevel@tonic-gate continue;
6947c478bd9Sstevel@tonic-gate case 'b':
6957c478bd9Sstevel@tonic-gate bflg = 1;
6967c478bd9Sstevel@tonic-gate qflg = 0;
6977c478bd9Sstevel@tonic-gate continue;
6985e1c72e1SJason King case 'B':
6995e1c72e1SJason King Bflg = 1;
7005e1c72e1SJason King continue;
7017c478bd9Sstevel@tonic-gate case 'c':
7027c478bd9Sstevel@tonic-gate uflg = 0;
703da6c28aaSamw atm = 0;
704da6c28aaSamw ctm = 0;
705da6c28aaSamw mtm = 0;
706da6c28aaSamw crtm = 0;
7077c478bd9Sstevel@tonic-gate cflg++;
7087c478bd9Sstevel@tonic-gate continue;
7097c478bd9Sstevel@tonic-gate case 'C':
7107c478bd9Sstevel@tonic-gate Cflg = 1;
7117c478bd9Sstevel@tonic-gate mflg = 0;
7127c478bd9Sstevel@tonic-gate #ifdef XPG4
7137c478bd9Sstevel@tonic-gate lflg = 0;
7147c478bd9Sstevel@tonic-gate #endif
7157c478bd9Sstevel@tonic-gate continue;
7167c478bd9Sstevel@tonic-gate case 'd':
7177c478bd9Sstevel@tonic-gate dflg++;
7187c478bd9Sstevel@tonic-gate continue;
7197c478bd9Sstevel@tonic-gate case 'e':
7207c478bd9Sstevel@tonic-gate eflg++;
7217c478bd9Sstevel@tonic-gate lflg++;
7227c478bd9Sstevel@tonic-gate statreq++;
7237c478bd9Sstevel@tonic-gate Eflg = 0;
7245e1c72e1SJason King time_fmt_old = FORMAT_LONG;
7255e1c72e1SJason King time_fmt_new = FORMAT_LONG;
7267c478bd9Sstevel@tonic-gate continue;
7277c478bd9Sstevel@tonic-gate case 'E':
7287c478bd9Sstevel@tonic-gate Eflg++;
7297c478bd9Sstevel@tonic-gate lflg++;
7307c478bd9Sstevel@tonic-gate statreq++;
7317c478bd9Sstevel@tonic-gate eflg = 0;
7325e1c72e1SJason King time_fmt_old = FORMAT_ISO_FULL;
7335e1c72e1SJason King time_fmt_new = FORMAT_ISO_FULL;
7347c478bd9Sstevel@tonic-gate continue;
7357c478bd9Sstevel@tonic-gate case 'f':
7367c478bd9Sstevel@tonic-gate fflg++;
7377c478bd9Sstevel@tonic-gate continue;
7387c478bd9Sstevel@tonic-gate case 'F':
7397c478bd9Sstevel@tonic-gate Fflg++;
7407c478bd9Sstevel@tonic-gate statreq++;
7417c478bd9Sstevel@tonic-gate continue;
7427c478bd9Sstevel@tonic-gate case 'g':
7437c478bd9Sstevel@tonic-gate gflg++;
7447c478bd9Sstevel@tonic-gate lflg++;
7457c478bd9Sstevel@tonic-gate statreq++;
7467c478bd9Sstevel@tonic-gate continue;
7477c478bd9Sstevel@tonic-gate case 'h':
7487c478bd9Sstevel@tonic-gate hflg++;
7497c478bd9Sstevel@tonic-gate continue;
7507c478bd9Sstevel@tonic-gate case 'H':
7517c478bd9Sstevel@tonic-gate Hflg++;
7527c478bd9Sstevel@tonic-gate /* -H and -L are mutually exclusive */
7537c478bd9Sstevel@tonic-gate Lflg = 0;
7547c478bd9Sstevel@tonic-gate continue;
7557c478bd9Sstevel@tonic-gate case 'i':
7567c478bd9Sstevel@tonic-gate iflg++;
7577c478bd9Sstevel@tonic-gate continue;
7585e1c72e1SJason King case 'k':
7595e1c72e1SJason King block_size = 1024;
7605e1c72e1SJason King continue;
7617c478bd9Sstevel@tonic-gate case 'l':
7627c478bd9Sstevel@tonic-gate lflg++;
7637c478bd9Sstevel@tonic-gate statreq++;
7647c478bd9Sstevel@tonic-gate Cflg = 0;
7657c478bd9Sstevel@tonic-gate xflg = 0;
7667c478bd9Sstevel@tonic-gate mflg = 0;
7677c478bd9Sstevel@tonic-gate atflg = 0;
7687c478bd9Sstevel@tonic-gate continue;
7697c478bd9Sstevel@tonic-gate case 'L':
7707c478bd9Sstevel@tonic-gate Lflg++;
7717c478bd9Sstevel@tonic-gate /* -H and -L are mutually exclusive */
7727c478bd9Sstevel@tonic-gate Hflg = 0;
7737c478bd9Sstevel@tonic-gate continue;
7747c478bd9Sstevel@tonic-gate case 'm':
7757c478bd9Sstevel@tonic-gate Cflg = 0;
7767c478bd9Sstevel@tonic-gate mflg = 1;
7777c478bd9Sstevel@tonic-gate #ifdef XPG4
7787c478bd9Sstevel@tonic-gate lflg = 0;
7797c478bd9Sstevel@tonic-gate #endif
7807c478bd9Sstevel@tonic-gate continue;
7817c478bd9Sstevel@tonic-gate case 'n':
7827c478bd9Sstevel@tonic-gate nflg++;
7837c478bd9Sstevel@tonic-gate lflg++;
7847c478bd9Sstevel@tonic-gate statreq++;
7857c478bd9Sstevel@tonic-gate Cflg = 0;
7867c478bd9Sstevel@tonic-gate xflg = 0;
7877c478bd9Sstevel@tonic-gate mflg = 0;
7887c478bd9Sstevel@tonic-gate atflg = 0;
7897c478bd9Sstevel@tonic-gate continue;
7907c478bd9Sstevel@tonic-gate case 'o':
7917c478bd9Sstevel@tonic-gate oflg++;
7927c478bd9Sstevel@tonic-gate lflg++;
7937c478bd9Sstevel@tonic-gate statreq++;
7947c478bd9Sstevel@tonic-gate continue;
7957c478bd9Sstevel@tonic-gate case 'p':
7967c478bd9Sstevel@tonic-gate pflg++;
7977c478bd9Sstevel@tonic-gate statreq++;
7987c478bd9Sstevel@tonic-gate continue;
7997c478bd9Sstevel@tonic-gate case 'q':
8007c478bd9Sstevel@tonic-gate qflg = 1;
8017c478bd9Sstevel@tonic-gate bflg = 0;
8027c478bd9Sstevel@tonic-gate continue;
8037c478bd9Sstevel@tonic-gate case 'r':
8047c478bd9Sstevel@tonic-gate rflg = -1;
8057c478bd9Sstevel@tonic-gate continue;
8067c478bd9Sstevel@tonic-gate case 'R':
8077c478bd9Sstevel@tonic-gate Rflg++;
8087c478bd9Sstevel@tonic-gate statreq++;
8097c478bd9Sstevel@tonic-gate continue;
8107c478bd9Sstevel@tonic-gate case 's':
8117c478bd9Sstevel@tonic-gate sflg++;
8127c478bd9Sstevel@tonic-gate statreq++;
8137c478bd9Sstevel@tonic-gate continue;
8147c478bd9Sstevel@tonic-gate case 'S':
8157c478bd9Sstevel@tonic-gate tflg = 0;
8165e1c72e1SJason King Uflg = 0;
8177c478bd9Sstevel@tonic-gate Sflg++;
8187c478bd9Sstevel@tonic-gate statreq++;
8197c478bd9Sstevel@tonic-gate continue;
8207c478bd9Sstevel@tonic-gate case 't':
8217c478bd9Sstevel@tonic-gate Sflg = 0;
8225e1c72e1SJason King Uflg = 0;
8237c478bd9Sstevel@tonic-gate tflg++;
8247c478bd9Sstevel@tonic-gate statreq++;
8257c478bd9Sstevel@tonic-gate continue;
8265e1c72e1SJason King case 'U':
8275e1c72e1SJason King Sflg = 0;
8285e1c72e1SJason King tflg = 0;
8295e1c72e1SJason King Uflg++;
8305e1c72e1SJason King continue;
8317c478bd9Sstevel@tonic-gate case 'u':
8327c478bd9Sstevel@tonic-gate cflg = 0;
833da6c28aaSamw atm = 0;
834da6c28aaSamw ctm = 0;
835da6c28aaSamw mtm = 0;
836da6c28aaSamw crtm = 0;
8377c478bd9Sstevel@tonic-gate uflg++;
8387c478bd9Sstevel@tonic-gate continue;
8395a5eeccaSmarks case 'V':
8405a5eeccaSmarks Vflg++;
8415a5eeccaSmarks /*FALLTHROUGH*/
842fa9e4066Sahrens case 'v':
843fa9e4066Sahrens vflg++;
844fa9e4066Sahrens #if !defined(XPG4)
845fa9e4066Sahrens if (lflg)
846fa9e4066Sahrens continue;
847fa9e4066Sahrens #endif
848fa9e4066Sahrens lflg++;
849fa9e4066Sahrens statreq++;
850fa9e4066Sahrens Cflg = 0;
851fa9e4066Sahrens xflg = 0;
852fa9e4066Sahrens mflg = 0;
853fa9e4066Sahrens continue;
8545e1c72e1SJason King case 'w':
8555e1c72e1SJason King wflg++;
8565e1c72e1SJason King num_cols = atoi(optarg);
8575e1c72e1SJason King continue;
8587c478bd9Sstevel@tonic-gate case 'x':
8597c478bd9Sstevel@tonic-gate xflg = 1;
8607c478bd9Sstevel@tonic-gate Cflg = 1;
8617c478bd9Sstevel@tonic-gate mflg = 0;
8627c478bd9Sstevel@tonic-gate #ifdef XPG4
8637c478bd9Sstevel@tonic-gate lflg = 0;
8647c478bd9Sstevel@tonic-gate #endif
8657c478bd9Sstevel@tonic-gate continue;
8667c478bd9Sstevel@tonic-gate case '1':
8677c478bd9Sstevel@tonic-gate Cflg = 0;
8687c478bd9Sstevel@tonic-gate continue;
8697c478bd9Sstevel@tonic-gate case '@':
8707c478bd9Sstevel@tonic-gate #if !defined(XPG4)
8717c478bd9Sstevel@tonic-gate /*
8727c478bd9Sstevel@tonic-gate * -l has precedence over -@
8737c478bd9Sstevel@tonic-gate */
8747c478bd9Sstevel@tonic-gate if (lflg)
8757c478bd9Sstevel@tonic-gate continue;
8767c478bd9Sstevel@tonic-gate #endif
8777c478bd9Sstevel@tonic-gate atflg++;
8787c478bd9Sstevel@tonic-gate lflg++;
8797c478bd9Sstevel@tonic-gate statreq++;
8807c478bd9Sstevel@tonic-gate Cflg = 0;
8817c478bd9Sstevel@tonic-gate xflg = 0;
8827c478bd9Sstevel@tonic-gate mflg = 0;
8837c478bd9Sstevel@tonic-gate continue;
884da6c28aaSamw case '/':
885da6c28aaSamw saflg++;
886da6c28aaSamw if (optarg != NULL) {
887da6c28aaSamw if (strcmp(optarg, "c") == 0) {
888da6c28aaSamw copt++;
889da6c28aaSamw vopt = 0;
890da6c28aaSamw } else if (strcmp(optarg, "v") == 0) {
891da6c28aaSamw vopt++;
892da6c28aaSamw copt = 0;
893da6c28aaSamw } else
894da6c28aaSamw opterr++;
895da6c28aaSamw } else
896da6c28aaSamw opterr++;
897da6c28aaSamw lflg++;
898da6c28aaSamw statreq++;
899da6c28aaSamw Cflg = 0;
900da6c28aaSamw xflg = 0;
901da6c28aaSamw mflg = 0;
902da6c28aaSamw continue;
903da6c28aaSamw case '%':
904da6c28aaSamw tmflg++;
905da6c28aaSamw if (optarg != NULL) {
906da6c28aaSamw if (strcmp(optarg, "ctime") == 0) {
907da6c28aaSamw ctm++;
908da6c28aaSamw atm = 0;
909da6c28aaSamw mtm = 0;
910da6c28aaSamw crtm = 0;
911da6c28aaSamw } else if (strcmp(optarg, "atime") == 0) {
912da6c28aaSamw atm++;
913da6c28aaSamw ctm = 0;
914da6c28aaSamw mtm = 0;
915da6c28aaSamw crtm = 0;
916da6c28aaSamw uflg = 0;
917da6c28aaSamw cflg = 0;
918da6c28aaSamw } else if (strcmp(optarg, "mtime") == 0) {
919da6c28aaSamw mtm++;
920da6c28aaSamw atm = 0;
921da6c28aaSamw ctm = 0;
922da6c28aaSamw crtm = 0;
923da6c28aaSamw uflg = 0;
924da6c28aaSamw cflg = 0;
925da6c28aaSamw } else if (strcmp(optarg, "crtime") == 0) {
926da6c28aaSamw crtm++;
927da6c28aaSamw atm = 0;
928da6c28aaSamw ctm = 0;
929da6c28aaSamw mtm = 0;
930da6c28aaSamw uflg = 0;
931da6c28aaSamw cflg = 0;
932da6c28aaSamw } else if (strcmp(optarg, "all") == 0) {
933da6c28aaSamw alltm++;
934da6c28aaSamw atm = 0;
935da6c28aaSamw ctm = 0;
936da6c28aaSamw mtm = 0;
937da6c28aaSamw crtm = 0;
938da6c28aaSamw } else
939da6c28aaSamw opterr++;
940da6c28aaSamw } else
941da6c28aaSamw opterr++;
942da6c28aaSamw
943da6c28aaSamw Sflg = 0;
944da6c28aaSamw statreq++;
945da6c28aaSamw mflg = 0;
946da6c28aaSamw continue;
9477c478bd9Sstevel@tonic-gate case '?':
9487c478bd9Sstevel@tonic-gate opterr++;
9497c478bd9Sstevel@tonic-gate continue;
9507c478bd9Sstevel@tonic-gate }
9515e1c72e1SJason King
9527c478bd9Sstevel@tonic-gate if (opterr) {
9537c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(
9545e1c72e1SJason King "usage: ls -aAbBcCdeEfFghHiklLmnopqrRsStuUwxvV1@/%[c | v]"
955da6c28aaSamw "%%[atime | crtime | ctime | mtime | all]"
956da6c28aaSamw " [files]\n"));
9577c478bd9Sstevel@tonic-gate exit(2);
9587c478bd9Sstevel@tonic-gate }
9597c478bd9Sstevel@tonic-gate
9607c478bd9Sstevel@tonic-gate if (fflg) {
9617c478bd9Sstevel@tonic-gate aflg++;
9627c478bd9Sstevel@tonic-gate lflg = 0;
9637c478bd9Sstevel@tonic-gate sflg = 0;
9647c478bd9Sstevel@tonic-gate tflg = 0;
9657c478bd9Sstevel@tonic-gate Sflg = 0;
9667c478bd9Sstevel@tonic-gate statreq = 0;
9677c478bd9Sstevel@tonic-gate }
9687c478bd9Sstevel@tonic-gate
9697c478bd9Sstevel@tonic-gate fixedwidth = 2;
9707c478bd9Sstevel@tonic-gate if (pflg || Fflg)
9717c478bd9Sstevel@tonic-gate fixedwidth++;
9727c478bd9Sstevel@tonic-gate if (iflg)
9737c478bd9Sstevel@tonic-gate fixedwidth += 11;
9747c478bd9Sstevel@tonic-gate if (sflg)
9757c478bd9Sstevel@tonic-gate fixedwidth += 5;
9767c478bd9Sstevel@tonic-gate
9777c478bd9Sstevel@tonic-gate if (lflg) {
9787c478bd9Sstevel@tonic-gate if (!gflg && !oflg)
9797c478bd9Sstevel@tonic-gate gflg = oflg = 1;
9807c478bd9Sstevel@tonic-gate else
9817c478bd9Sstevel@tonic-gate if (gflg && oflg)
9827c478bd9Sstevel@tonic-gate gflg = oflg = 0;
9837c478bd9Sstevel@tonic-gate Cflg = mflg = 0;
9847c478bd9Sstevel@tonic-gate }
9857c478bd9Sstevel@tonic-gate
9865e1c72e1SJason King if (!wflg && (Cflg || mflg)) {
9877c478bd9Sstevel@tonic-gate char *clptr;
9887c478bd9Sstevel@tonic-gate if ((clptr = getenv("COLUMNS")) != NULL)
9897c478bd9Sstevel@tonic-gate num_cols = atoi(clptr);
9907c478bd9Sstevel@tonic-gate #ifdef TERMINFO
9917c478bd9Sstevel@tonic-gate else {
9927c478bd9Sstevel@tonic-gate if (ioctl(1, TIOCGWINSZ, &win) != -1)
9937c478bd9Sstevel@tonic-gate num_cols = (win.ws_col == 0 ? 80 : win.ws_col);
9947c478bd9Sstevel@tonic-gate }
9957c478bd9Sstevel@tonic-gate #endif
9967c478bd9Sstevel@tonic-gate }
9977c478bd9Sstevel@tonic-gate
99891bbe3fdSBill Pijewski /*
99991bbe3fdSBill Pijewski * When certain options (-f, or -U and -1, and not -l, etc.) are
100091bbe3fdSBill Pijewski * specified, don't cache each dirent as it's read. This 'noflist'
100191bbe3fdSBill Pijewski * option is set when there's no need to cache those dirents; instead,
100291bbe3fdSBill Pijewski * print them out as they're read.
100391bbe3fdSBill Pijewski */
100491bbe3fdSBill Pijewski if ((Uflg || fflg) && !Cflg && !lflg && !iflg && statreq == 0)
100591bbe3fdSBill Pijewski noflist = 1;
100691bbe3fdSBill Pijewski
10075e1c72e1SJason King if (num_cols < 20 || num_cols > 1000)
10085e1c72e1SJason King /* assume it is an error */
10095e1c72e1SJason King num_cols = 80;
10105e1c72e1SJason King
10117c478bd9Sstevel@tonic-gate /* allocate space for flist and the associated */
10127c478bd9Sstevel@tonic-gate /* data structures (lbufs) */
10137c478bd9Sstevel@tonic-gate maxfils = quantn;
10147c478bd9Sstevel@tonic-gate if (((flist = malloc(maxfils * sizeof (struct lbuf *))) == NULL) ||
10157c478bd9Sstevel@tonic-gate ((nxtlbf = malloc(quantn * sizeof (struct lbuf))) == NULL)) {
10167c478bd9Sstevel@tonic-gate perror("ls");
10177c478bd9Sstevel@tonic-gate exit(2);
10187c478bd9Sstevel@tonic-gate }
10197c478bd9Sstevel@tonic-gate if ((amino = (argc-optind)) == 0) {
10207c478bd9Sstevel@tonic-gate /*
10217c478bd9Sstevel@tonic-gate * case when no names are given
10227c478bd9Sstevel@tonic-gate * in ls-command and current
10237c478bd9Sstevel@tonic-gate * directory is to be used
10247c478bd9Sstevel@tonic-gate */
10257c478bd9Sstevel@tonic-gate argv[optind] = dotp;
10267c478bd9Sstevel@tonic-gate }
10277c478bd9Sstevel@tonic-gate
102871ef9ec8SLauri Tirkkonen if (colorflg)
102971ef9ec8SLauri Tirkkonen ls_color_init();
103071ef9ec8SLauri Tirkkonen
10317c478bd9Sstevel@tonic-gate for (i = 0; i < (amino ? amino : 1); i++) {
10327c478bd9Sstevel@tonic-gate
10337c478bd9Sstevel@tonic-gate /*
10347c478bd9Sstevel@tonic-gate * If we are recursing, we need to make sure we don't
10357c478bd9Sstevel@tonic-gate * get into an endless loop. To keep track of the inodes
10367c478bd9Sstevel@tonic-gate * (actually, just the directories) visited, we
10377c478bd9Sstevel@tonic-gate * maintain a directory ancestry list for a file
10387c478bd9Sstevel@tonic-gate * hierarchy. As we go deeper into the hierarchy,
10397c478bd9Sstevel@tonic-gate * a parent directory passes its directory list
10407c478bd9Sstevel@tonic-gate * info (device id, inode number, and a pointer to
10417c478bd9Sstevel@tonic-gate * its parent) to each of its children. As we
10427c478bd9Sstevel@tonic-gate * process a child that is a directory, we save
10437c478bd9Sstevel@tonic-gate * its own personal directory list info. We then
10447c478bd9Sstevel@tonic-gate * check to see if the child has already been
10457c478bd9Sstevel@tonic-gate * processed by comparing its device id and inode
10467c478bd9Sstevel@tonic-gate * number from its own personal directory list info
10477c478bd9Sstevel@tonic-gate * to that of each of its ancestors. If there is a
10487c478bd9Sstevel@tonic-gate * match, then we know we've detected a cycle.
10497c478bd9Sstevel@tonic-gate */
10507c478bd9Sstevel@tonic-gate if (Rflg) {
10517c478bd9Sstevel@tonic-gate /*
10527c478bd9Sstevel@tonic-gate * This is the first parent in this lineage
10537c478bd9Sstevel@tonic-gate * (first in a directory hierarchy), so
10547c478bd9Sstevel@tonic-gate * this parent's parent doesn't exist. We
10557c478bd9Sstevel@tonic-gate * only initialize myinfo when we are
10567c478bd9Sstevel@tonic-gate * recursing, otherwise it's not used.
10577c478bd9Sstevel@tonic-gate */
10587c478bd9Sstevel@tonic-gate if ((myinfo = (struct ditem *)malloc(
10597c478bd9Sstevel@tonic-gate sizeof (struct ditem))) == NULL) {
10607c478bd9Sstevel@tonic-gate perror("ls");
10617c478bd9Sstevel@tonic-gate exit(2);
10627c478bd9Sstevel@tonic-gate } else {
10637c478bd9Sstevel@tonic-gate myinfo->dev = 0;
10647c478bd9Sstevel@tonic-gate myinfo->ino = 0;
10657c478bd9Sstevel@tonic-gate myinfo->parent = NULL;
10667c478bd9Sstevel@tonic-gate }
10677c478bd9Sstevel@tonic-gate }
10687c478bd9Sstevel@tonic-gate
10697c478bd9Sstevel@tonic-gate if (Cflg || mflg) {
10707c478bd9Sstevel@tonic-gate width = strcol((unsigned char *)argv[optind]);
10717c478bd9Sstevel@tonic-gate if (width > filewidth)
10727c478bd9Sstevel@tonic-gate filewidth = width;
10737c478bd9Sstevel@tonic-gate }
10747c478bd9Sstevel@tonic-gate if ((ep = gstat((*argv[optind] ? argv[optind] : dotp),
10757c478bd9Sstevel@tonic-gate 1, myinfo)) == NULL) {
10767c478bd9Sstevel@tonic-gate if (nomocore)
10777c478bd9Sstevel@tonic-gate exit(2);
10787c478bd9Sstevel@tonic-gate err = 2;
10797c478bd9Sstevel@tonic-gate optind++;
10807c478bd9Sstevel@tonic-gate continue;
10817c478bd9Sstevel@tonic-gate }
10827c478bd9Sstevel@tonic-gate ep->ln.namep = (*argv[optind] ? argv[optind] : dotp);
10837c478bd9Sstevel@tonic-gate ep->lflags |= ISARG;
10847c478bd9Sstevel@tonic-gate optind++;
10857c478bd9Sstevel@tonic-gate nargs++; /* count good arguments stored in flist */
108656798e90Sbasabi if (acl_err)
108756798e90Sbasabi err = 2;
10887c478bd9Sstevel@tonic-gate }
10897c478bd9Sstevel@tonic-gate colwidth = fixedwidth + filewidth;
10905e1c72e1SJason King if (!Uflg)
10915e1c72e1SJason King qsort(flist, (unsigned)nargs, sizeof (struct lbuf *),
10925e1c72e1SJason King (int (*)(const void *, const void *))compar);
10937c478bd9Sstevel@tonic-gate for (i = 0; i < nargs; i++) {
109429e6ab97SIgor Kozhukhov if ((flist[i]->ltype == 'd' && dflg == 0) || fflg)
10957c478bd9Sstevel@tonic-gate break;
10967c478bd9Sstevel@tonic-gate }
10975e1c72e1SJason King
10987c478bd9Sstevel@tonic-gate pem(&flist[0], &flist[i], 0);
10997c478bd9Sstevel@tonic-gate for (; i < nargs; i++) {
11007c478bd9Sstevel@tonic-gate pdirectory(flist[i]->ln.namep, Rflg ||
11017c478bd9Sstevel@tonic-gate (amino > 1), nargs, 0, flist[i]->ancinfo);
11027c478bd9Sstevel@tonic-gate if (nomocore)
11037c478bd9Sstevel@tonic-gate exit(2);
11047c478bd9Sstevel@tonic-gate /* -R: print subdirectories found */
11057c478bd9Sstevel@tonic-gate while (dfirst || cdfirst) {
11067c478bd9Sstevel@tonic-gate /* Place direct subdirs on front in right order */
11077c478bd9Sstevel@tonic-gate while (cdfirst) {
11087c478bd9Sstevel@tonic-gate /* reverse cdfirst onto front of dfirst */
11097c478bd9Sstevel@tonic-gate dtemp = cdfirst;
11107c478bd9Sstevel@tonic-gate cdfirst = cdfirst -> dc_next;
11117c478bd9Sstevel@tonic-gate dtemp -> dc_next = dfirst;
11127c478bd9Sstevel@tonic-gate dfirst = dtemp;
11137c478bd9Sstevel@tonic-gate }
11147c478bd9Sstevel@tonic-gate /* take off first dir on dfirst & print it */
11157c478bd9Sstevel@tonic-gate dtemp = dfirst;
11167c478bd9Sstevel@tonic-gate dfirst = dfirst->dc_next;
11177c478bd9Sstevel@tonic-gate pdirectory(dtemp->dc_name, 1, nargs,
11187c478bd9Sstevel@tonic-gate dtemp->cycle_detected, dtemp->myancinfo);
11197c478bd9Sstevel@tonic-gate if (nomocore)
11207c478bd9Sstevel@tonic-gate exit(2);
11217c478bd9Sstevel@tonic-gate free(dtemp->dc_name);
11227c478bd9Sstevel@tonic-gate free(dtemp);
11237c478bd9Sstevel@tonic-gate }
11247c478bd9Sstevel@tonic-gate }
11255e1c72e1SJason King
11267c478bd9Sstevel@tonic-gate return (err);
11277c478bd9Sstevel@tonic-gate }
11287c478bd9Sstevel@tonic-gate
11297c478bd9Sstevel@tonic-gate /*
11307c478bd9Sstevel@tonic-gate * pdirectory: print the directory name, labelling it if title is
11317c478bd9Sstevel@tonic-gate * nonzero, using lp as the place to start reading in the dir.
11327c478bd9Sstevel@tonic-gate */
11337c478bd9Sstevel@tonic-gate static void
pdirectory(char * name,int title,int lp,int cdetect,struct ditem * myinfo)11347c478bd9Sstevel@tonic-gate pdirectory(char *name, int title, int lp, int cdetect, struct ditem *myinfo)
11357c478bd9Sstevel@tonic-gate {
11367c478bd9Sstevel@tonic-gate struct dchain *dp;
11377c478bd9Sstevel@tonic-gate struct lbuf *ap;
11387c478bd9Sstevel@tonic-gate char *pname;
11397c478bd9Sstevel@tonic-gate int j;
11407c478bd9Sstevel@tonic-gate
11417c478bd9Sstevel@tonic-gate filewidth = 0;
11427c478bd9Sstevel@tonic-gate curdir = name;
11437c478bd9Sstevel@tonic-gate if (title) {
11447c478bd9Sstevel@tonic-gate if (!first)
11457c478bd9Sstevel@tonic-gate (void) putc('\n', stdout);
11467c478bd9Sstevel@tonic-gate pprintf(name, ":");
11477c478bd9Sstevel@tonic-gate new_line();
11487c478bd9Sstevel@tonic-gate }
11497c478bd9Sstevel@tonic-gate /*
11507c478bd9Sstevel@tonic-gate * If there was a cycle detected, then notify and don't report
11517c478bd9Sstevel@tonic-gate * further.
11527c478bd9Sstevel@tonic-gate */
11537c478bd9Sstevel@tonic-gate if (cdetect) {
11547c478bd9Sstevel@tonic-gate if (lflg || sflg) {
11557c478bd9Sstevel@tonic-gate curcol += printf(gettext("total %d"), 0);
11567c478bd9Sstevel@tonic-gate new_line();
11577c478bd9Sstevel@tonic-gate }
11587c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(
11597c478bd9Sstevel@tonic-gate "ls: cycle detected for %s\n"), name);
11607c478bd9Sstevel@tonic-gate return;
11617c478bd9Sstevel@tonic-gate }
11627c478bd9Sstevel@tonic-gate
11637c478bd9Sstevel@tonic-gate nfiles = lp;
11647c478bd9Sstevel@tonic-gate rddir(name, myinfo);
116591bbe3fdSBill Pijewski if (nomocore || noflist)
11667c478bd9Sstevel@tonic-gate return;
11675e1c72e1SJason King if (fflg == 0 && Uflg == 0)
11687c478bd9Sstevel@tonic-gate qsort(&flist[lp], (unsigned)(nfiles - lp),
11697c478bd9Sstevel@tonic-gate sizeof (struct lbuf *),
11707c478bd9Sstevel@tonic-gate (int (*)(const void *, const void *))compar);
11717c478bd9Sstevel@tonic-gate if (Rflg) {
11727c478bd9Sstevel@tonic-gate for (j = nfiles - 1; j >= lp; j--) {
11737c478bd9Sstevel@tonic-gate ap = flist[j];
11747c478bd9Sstevel@tonic-gate if (ap->ltype == 'd' && strcmp(ap->ln.lname, ".") &&
11757c478bd9Sstevel@tonic-gate strcmp(ap->ln.lname, "..")) {
11767c478bd9Sstevel@tonic-gate dp = malloc(sizeof (struct dchain));
11777c478bd9Sstevel@tonic-gate if (dp == NULL) {
11787c478bd9Sstevel@tonic-gate perror("ls");
11797c478bd9Sstevel@tonic-gate exit(2);
11807c478bd9Sstevel@tonic-gate }
11817c478bd9Sstevel@tonic-gate pname = makename(curdir, ap->ln.lname);
11827c478bd9Sstevel@tonic-gate if ((dp->dc_name = strdup(pname)) == NULL) {
11837c478bd9Sstevel@tonic-gate perror("ls");
11847c478bd9Sstevel@tonic-gate exit(2);
11857c478bd9Sstevel@tonic-gate }
11867c478bd9Sstevel@tonic-gate dp->cycle_detected = ap->cycle;
11877c478bd9Sstevel@tonic-gate dp->myancinfo = ap->ancinfo;
11887c478bd9Sstevel@tonic-gate dp->dc_next = dfirst;
11897c478bd9Sstevel@tonic-gate dfirst = dp;
11907c478bd9Sstevel@tonic-gate }
11917c478bd9Sstevel@tonic-gate }
11927c478bd9Sstevel@tonic-gate }
11937c478bd9Sstevel@tonic-gate if (lflg || sflg) {
11947c478bd9Sstevel@tonic-gate curcol += printf(gettext("total %llu"), tblocks);
11957c478bd9Sstevel@tonic-gate new_line();
11967c478bd9Sstevel@tonic-gate }
11977c478bd9Sstevel@tonic-gate pem(&flist[lp], &flist[nfiles], lflg||sflg);
11987c478bd9Sstevel@tonic-gate }
11997c478bd9Sstevel@tonic-gate
12007c478bd9Sstevel@tonic-gate /*
12017c478bd9Sstevel@tonic-gate * pem: print 'em. Print a list of files (e.g. a directory) bounded
12027c478bd9Sstevel@tonic-gate * by slp and lp.
12037c478bd9Sstevel@tonic-gate */
12047c478bd9Sstevel@tonic-gate static void
pem(struct lbuf ** slp,struct lbuf ** lp,int tot_flag)12057c478bd9Sstevel@tonic-gate pem(struct lbuf **slp, struct lbuf **lp, int tot_flag)
12067c478bd9Sstevel@tonic-gate {
12077c478bd9Sstevel@tonic-gate long row, nrows, i;
120829e6ab97SIgor Kozhukhov int col, ncols = 1;
12097c478bd9Sstevel@tonic-gate struct lbuf **ep;
12107c478bd9Sstevel@tonic-gate
12117c478bd9Sstevel@tonic-gate if (Cflg || mflg) {
121229e6ab97SIgor Kozhukhov if (colwidth <= num_cols) {
12137c478bd9Sstevel@tonic-gate ncols = num_cols / colwidth;
12147c478bd9Sstevel@tonic-gate }
12157c478bd9Sstevel@tonic-gate }
12167c478bd9Sstevel@tonic-gate
12177c478bd9Sstevel@tonic-gate if (ncols == 1 || mflg || xflg || !Cflg) {
12187c478bd9Sstevel@tonic-gate for (ep = slp; ep < lp; ep++)
12197c478bd9Sstevel@tonic-gate pentry(*ep);
12207c478bd9Sstevel@tonic-gate new_line();
12217c478bd9Sstevel@tonic-gate return;
12227c478bd9Sstevel@tonic-gate }
12237c478bd9Sstevel@tonic-gate /* otherwise print -C columns */
12247c478bd9Sstevel@tonic-gate if (tot_flag) {
12257c478bd9Sstevel@tonic-gate slp--;
12267c478bd9Sstevel@tonic-gate row = 1;
12277c478bd9Sstevel@tonic-gate }
12287c478bd9Sstevel@tonic-gate else
12297c478bd9Sstevel@tonic-gate row = 0;
12307c478bd9Sstevel@tonic-gate
12317c478bd9Sstevel@tonic-gate nrows = (lp - slp - 1) / ncols + 1;
12327c478bd9Sstevel@tonic-gate for (i = 0; i < nrows; i++, row++) {
12337c478bd9Sstevel@tonic-gate for (col = 0; col < ncols; col++) {
12347c478bd9Sstevel@tonic-gate ep = slp + (nrows * col) + row;
12357c478bd9Sstevel@tonic-gate if (ep < lp)
12367c478bd9Sstevel@tonic-gate pentry(*ep);
12377c478bd9Sstevel@tonic-gate }
12387c478bd9Sstevel@tonic-gate new_line();
12397c478bd9Sstevel@tonic-gate }
12407c478bd9Sstevel@tonic-gate }
12417c478bd9Sstevel@tonic-gate
12427c478bd9Sstevel@tonic-gate /*
12437c478bd9Sstevel@tonic-gate * print one output entry;
12447c478bd9Sstevel@tonic-gate * if uid/gid is not found in the appropriate
12457c478bd9Sstevel@tonic-gate * file(passwd/group), then print uid/gid instead of
12467c478bd9Sstevel@tonic-gate * user/group name;
12477c478bd9Sstevel@tonic-gate */
12487c478bd9Sstevel@tonic-gate static void
pentry(struct lbuf * ap)12497c478bd9Sstevel@tonic-gate pentry(struct lbuf *ap)
12507c478bd9Sstevel@tonic-gate {
12517c478bd9Sstevel@tonic-gate struct lbuf *p;
12527c478bd9Sstevel@tonic-gate char *dmark = ""; /* Used if -p or -F option active */
12537c478bd9Sstevel@tonic-gate char *cp;
12541b628248SJason King char *str;
12557c478bd9Sstevel@tonic-gate
125691bbe3fdSBill Pijewski if (noflist) {
1257b9c81738SGary Mills (void) printf("%s\n", (ap->lflags & ISARG) ? ap->ln.namep :
1258b9c81738SGary Mills ap->ln.lname);
125991bbe3fdSBill Pijewski return;
126091bbe3fdSBill Pijewski }
126191bbe3fdSBill Pijewski
12627c478bd9Sstevel@tonic-gate p = ap;
12637c478bd9Sstevel@tonic-gate column();
126429e6ab97SIgor Kozhukhov if (iflg) {
12657c478bd9Sstevel@tonic-gate if (mflg && !lflg)
12667c478bd9Sstevel@tonic-gate curcol += printf("%llu ", (long long)p->lnum);
12677c478bd9Sstevel@tonic-gate else
12687c478bd9Sstevel@tonic-gate curcol += printf("%10llu ", (long long)p->lnum);
126929e6ab97SIgor Kozhukhov }
127029e6ab97SIgor Kozhukhov if (sflg) {
12717c478bd9Sstevel@tonic-gate curcol += printf((mflg && !lflg) ? "%lld " :
1272da6c28aaSamw (p->lblocks < 10000) ? "%4lld " : "%lld ",
1273da6c28aaSamw (p->ltype != 'b' && p->ltype != 'c') ?
1274da6c28aaSamw p->lblocks : 0LL);
127529e6ab97SIgor Kozhukhov }
12767c478bd9Sstevel@tonic-gate if (lflg) {
12777c478bd9Sstevel@tonic-gate (void) putchar(p->ltype);
12787c478bd9Sstevel@tonic-gate curcol++;
12797c478bd9Sstevel@tonic-gate pmode(p->lflags);
12807c478bd9Sstevel@tonic-gate
12817c478bd9Sstevel@tonic-gate /* ACL: additional access mode flag */
12827c478bd9Sstevel@tonic-gate (void) putchar(p->acl);
12837c478bd9Sstevel@tonic-gate curcol++;
12847c478bd9Sstevel@tonic-gate
1285*fab57d1bSGordon Ross /*
1286*fab57d1bSGordon Ross * When handling owner/group options (-o -g) note -n:
1287*fab57d1bSGordon Ross * With no -n options, getname/getroup converts any
1288*fab57d1bSGordon Ross * ephemeral IDs to a winname (if possible) or a SID.
1289*fab57d1bSGordon Ross * With just one -n option, convert ephemeral IDs to SIDs
1290*fab57d1bSGordon Ross * With two or more -n options, show the ephemeral ID
1291*fab57d1bSGordon Ross * (which is a lot less helpful than the SID).
1292*fab57d1bSGordon Ross */
12937c478bd9Sstevel@tonic-gate curcol += printf("%3lu ", (ulong_t)p->lnl);
129429e6ab97SIgor Kozhukhov if (oflg) {
1295*fab57d1bSGordon Ross if (nflg == 0) {
12967c478bd9Sstevel@tonic-gate cp = getname(p->luid);
12977c478bd9Sstevel@tonic-gate curcol += printf("%-8s ", cp);
1298*fab57d1bSGordon Ross } else if (nflg == 1 && p->luid > MAXUID) {
1299*fab57d1bSGordon Ross cp = getusid(p->luid);
1300*fab57d1bSGordon Ross curcol += printf("%-8s ", cp);
1301*fab57d1bSGordon Ross } else {
13027c478bd9Sstevel@tonic-gate curcol += printf("%-8lu ", (ulong_t)p->luid);
1303*fab57d1bSGordon Ross }
130429e6ab97SIgor Kozhukhov }
130529e6ab97SIgor Kozhukhov if (gflg) {
1306*fab57d1bSGordon Ross if (nflg == 0) {
13077c478bd9Sstevel@tonic-gate cp = getgroup(p->lgid);
13087c478bd9Sstevel@tonic-gate curcol += printf("%-8s ", cp);
1309*fab57d1bSGordon Ross } else if (nflg == 1 && p->lgid > MAXUID) {
1310*fab57d1bSGordon Ross cp = getgsid(p->lgid);
1311*fab57d1bSGordon Ross curcol += printf("%-8s ", cp);
1312*fab57d1bSGordon Ross } else {
13137c478bd9Sstevel@tonic-gate curcol += printf("%-8lu ", (ulong_t)p->lgid);
1314*fab57d1bSGordon Ross }
131529e6ab97SIgor Kozhukhov }
13167c478bd9Sstevel@tonic-gate if (p->ltype == 'b' || p->ltype == 'c') {
13177c478bd9Sstevel@tonic-gate curcol += printf("%3u, %2u",
13187c478bd9Sstevel@tonic-gate (uint_t)major((dev_t)p->lsize),
13197c478bd9Sstevel@tonic-gate (uint_t)minor((dev_t)p->lsize));
13200a055120SJason King } else if (hflg) {
13210a055120SJason King char numbuf[NN_NUMBUF_SZ];
13220a055120SJason King
13230a055120SJason King nicenum_scale(p->lsize, 1, numbuf, sizeof (numbuf),
13240a055120SJason King nicenum_flags);
13250a055120SJason King
13260a055120SJason King curcol += printf("%7s", numbuf);
13277c478bd9Sstevel@tonic-gate } else {
13285e1c72e1SJason King uint64_t bsize = p->lsize / block_size;
13295e1c72e1SJason King
13305e1c72e1SJason King /*
13315e1c72e1SJason King * Round up only when using blocks > 1 byte, otherwise
13325e1c72e1SJason King * 'normal' sizes display 1 byte too large.
13335e1c72e1SJason King */
13345e1c72e1SJason King if (p->lsize % block_size != 0)
13355e1c72e1SJason King bsize++;
13365e1c72e1SJason King
13375e1c72e1SJason King curcol += printf("%7" PRIu64, bsize);
13387c478bd9Sstevel@tonic-gate }
13395e1c72e1SJason King format_time(p->lmtime.tv_sec, p->lmtime.tv_nsec);
1340da6c28aaSamw /* format extended system attribute time */
1341da6c28aaSamw if (tmflg && crtm)
1342da6c28aaSamw format_attrtime(p);
1343da6c28aaSamw
13447c478bd9Sstevel@tonic-gate curcol += printf("%s", time_buf);
13457c478bd9Sstevel@tonic-gate
1346da6c28aaSamw }
13477c478bd9Sstevel@tonic-gate /*
13487c478bd9Sstevel@tonic-gate * prevent both "->" and trailing marks
13497c478bd9Sstevel@tonic-gate * from appearing
13507c478bd9Sstevel@tonic-gate */
13517c478bd9Sstevel@tonic-gate
13527c478bd9Sstevel@tonic-gate if (pflg && p->ltype == 'd')
13537c478bd9Sstevel@tonic-gate dmark = "/";
13547c478bd9Sstevel@tonic-gate
13557c478bd9Sstevel@tonic-gate if (Fflg && !(lflg && p->flinkto)) {
13567c478bd9Sstevel@tonic-gate if (p->ltype == 'd')
13577c478bd9Sstevel@tonic-gate dmark = "/";
13587c478bd9Sstevel@tonic-gate else if (p->ltype == 'D')
13597c478bd9Sstevel@tonic-gate dmark = ">";
13607c478bd9Sstevel@tonic-gate else if (p->ltype == 'p')
13617c478bd9Sstevel@tonic-gate dmark = "|";
13627c478bd9Sstevel@tonic-gate else if (p->ltype == 'l')
13637c478bd9Sstevel@tonic-gate dmark = "@";
13647c478bd9Sstevel@tonic-gate else if (p->ltype == 's')
13657c478bd9Sstevel@tonic-gate dmark = "=";
13665e1c72e1SJason King else if (!file_typeflg &&
13675e1c72e1SJason King (p->lflags & (S_IXUSR|S_IXGRP|S_IXOTH)))
13687c478bd9Sstevel@tonic-gate dmark = "*";
13697c478bd9Sstevel@tonic-gate else
13707c478bd9Sstevel@tonic-gate dmark = "";
13717c478bd9Sstevel@tonic-gate }
13727c478bd9Sstevel@tonic-gate
13735e1c72e1SJason King if (colorflg)
13741b628248SJason King ls_start_color(p->color);
13755e1c72e1SJason King
13761b628248SJason King if (p->lflags & ISARG)
13771b628248SJason King str = p->ln.namep;
13781b628248SJason King else
13791b628248SJason King str = p->ln.lname;
13801b628248SJason King
13811b628248SJason King if (qflg || bflg) {
13821b628248SJason King csi_pprintf((unsigned char *)str);
13831b628248SJason King
13841b628248SJason King if (lflg && p->flinkto) {
13851b628248SJason King if (colorflg)
13861b628248SJason King ls_end_color();
13871b628248SJason King csi_pprintf((unsigned char *)" -> ");
13881b628248SJason King if (colorflg)
13891b628248SJason King ls_start_color(p->link_color);
13901b628248SJason King csi_pprintf((unsigned char *)p->flinkto);
13911b628248SJason King } else {
13921b628248SJason King csi_pprintf((unsigned char *)dmark);
13937c478bd9Sstevel@tonic-gate }
13947c478bd9Sstevel@tonic-gate } else {
13951b628248SJason King (void) printf("%s", str);
13961b628248SJason King curcol += strcol((unsigned char *)str);
13971b628248SJason King
13981b628248SJason King if (lflg && p->flinkto) {
13991b628248SJason King if (colorflg)
14001b628248SJason King ls_end_color();
14011b628248SJason King str = " -> ";
14021b628248SJason King (void) printf("%s", str);
14031b628248SJason King curcol += strcol((unsigned char *)str);
14041b628248SJason King if (colorflg)
14051b628248SJason King ls_start_color(p->link_color);
14061b628248SJason King (void) printf("%s", p->flinkto);
14071b628248SJason King curcol += strcol((unsigned char *)p->flinkto);
14081b628248SJason King } else {
14091b628248SJason King (void) printf("%s", dmark);
14107c478bd9Sstevel@tonic-gate curcol += strcol((unsigned char *)dmark);
14117c478bd9Sstevel@tonic-gate }
14127c478bd9Sstevel@tonic-gate }
1413fa9e4066Sahrens
14145e1c72e1SJason King if (colorflg)
14155e1c72e1SJason King ls_end_color();
14165e1c72e1SJason King
1417da6c28aaSamw /* Display extended system attributes */
1418da6c28aaSamw if (saflg) {
1419da6c28aaSamw int i;
1420da6c28aaSamw
1421da6c28aaSamw new_line();
1422da6c28aaSamw (void) printf(" \t{");
1423da6c28aaSamw if (p->exttr != NULL) {
1424da6c28aaSamw int k = 0;
1425da6c28aaSamw for (i = 0; i < sacnt; i++) {
1426da6c28aaSamw if (p->exttr[i].name != NULL)
1427da6c28aaSamw k++;
1428da6c28aaSamw }
1429da6c28aaSamw for (i = 0; i < sacnt; i++) {
1430da6c28aaSamw if (p->exttr[i].name != NULL) {
1431da6c28aaSamw (void) printf("%s", p->exttr[i].name);
1432da6c28aaSamw k--;
1433da6c28aaSamw if (vopt && (k != 0))
1434da6c28aaSamw (void) printf(",");
1435da6c28aaSamw }
1436da6c28aaSamw }
1437da6c28aaSamw }
1438da6c28aaSamw (void) printf("}\n");
1439da6c28aaSamw }
1440da6c28aaSamw /* Display file timestamps and extended system attribute timestamps */
1441da6c28aaSamw if (tmflg && alltm) {
1442da6c28aaSamw new_line();
1443da6c28aaSamw print_time(p);
1444da6c28aaSamw new_line();
1445da6c28aaSamw }
1446fa9e4066Sahrens if (vflg) {
1447fa9e4066Sahrens new_line();
1448fa9e4066Sahrens if (p->aclp) {
1449*fab57d1bSGordon Ross int pa_flags = 0;
1450*fab57d1bSGordon Ross
1451*fab57d1bSGordon Ross if (Vflg)
1452*fab57d1bSGordon Ross pa_flags |= ACL_COMPACT_FMT;
1453*fab57d1bSGordon Ross if (nflg)
1454*fab57d1bSGordon Ross pa_flags |= ACL_NORESOLVE;
1455*fab57d1bSGordon Ross if (nflg < 2)
1456*fab57d1bSGordon Ross pa_flags |= ACL_SID_FMT;
1457*fab57d1bSGordon Ross
1458*fab57d1bSGordon Ross acl_printacl2(p->aclp, num_cols, pa_flags);
1459fa9e4066Sahrens }
1460fa9e4066Sahrens }
1461da6c28aaSamw /* Free extended system attribute lists */
1462da6c28aaSamw if (saflg || tmflg)
1463da6c28aaSamw free_sysattr(p);
14647c478bd9Sstevel@tonic-gate }
14657c478bd9Sstevel@tonic-gate
14667c478bd9Sstevel@tonic-gate /* print various r,w,x permissions */
14677c478bd9Sstevel@tonic-gate static void
pmode(mode_t aflag)14687c478bd9Sstevel@tonic-gate pmode(mode_t aflag)
14697c478bd9Sstevel@tonic-gate {
14707c478bd9Sstevel@tonic-gate /* these arrays are declared static to allow initializations */
14717c478bd9Sstevel@tonic-gate static int m0[] = { 1, S_IRUSR, 'r', '-' };
14727c478bd9Sstevel@tonic-gate static int m1[] = { 1, S_IWUSR, 'w', '-' };
14737c478bd9Sstevel@tonic-gate static int m2[] = { 3, S_ISUID|S_IXUSR, 's', S_IXUSR,
14747c478bd9Sstevel@tonic-gate 'x', S_ISUID, 'S', '-' };
14757c478bd9Sstevel@tonic-gate static int m3[] = { 1, S_IRGRP, 'r', '-' };
14767c478bd9Sstevel@tonic-gate static int m4[] = { 1, S_IWGRP, 'w', '-' };
14777c478bd9Sstevel@tonic-gate static int m5[] = { 4, S_ISGID|S_IXGRP, 's', S_IXGRP,
14787c478bd9Sstevel@tonic-gate 'x', S_ISGID|LS_NOTREG, 'S',
14797c478bd9Sstevel@tonic-gate #ifdef XPG4
14807c478bd9Sstevel@tonic-gate S_ISGID, 'L', '-'};
14817c478bd9Sstevel@tonic-gate #else
14827c478bd9Sstevel@tonic-gate S_ISGID, 'l', '-'};
14837c478bd9Sstevel@tonic-gate #endif
14847c478bd9Sstevel@tonic-gate static int m6[] = { 1, S_IROTH, 'r', '-' };
14857c478bd9Sstevel@tonic-gate static int m7[] = { 1, S_IWOTH, 'w', '-' };
14867c478bd9Sstevel@tonic-gate static int m8[] = { 3, S_ISVTX|S_IXOTH, 't', S_IXOTH,
14877c478bd9Sstevel@tonic-gate 'x', S_ISVTX, 'T', '-'};
14887c478bd9Sstevel@tonic-gate
14897c478bd9Sstevel@tonic-gate static int *m[] = { m0, m1, m2, m3, m4, m5, m6, m7, m8};
14907c478bd9Sstevel@tonic-gate
14917c478bd9Sstevel@tonic-gate int **mp;
14927c478bd9Sstevel@tonic-gate
14937c478bd9Sstevel@tonic-gate flags = aflag;
14947c478bd9Sstevel@tonic-gate for (mp = &m[0]; mp < &m[sizeof (m) / sizeof (m[0])]; mp++)
14957c478bd9Sstevel@tonic-gate selection(*mp);
14967c478bd9Sstevel@tonic-gate }
14977c478bd9Sstevel@tonic-gate
14987c478bd9Sstevel@tonic-gate static void
selection(int * pairp)14997c478bd9Sstevel@tonic-gate selection(int *pairp)
15007c478bd9Sstevel@tonic-gate {
15017c478bd9Sstevel@tonic-gate int n;
15027c478bd9Sstevel@tonic-gate
15037c478bd9Sstevel@tonic-gate n = *pairp++;
15047c478bd9Sstevel@tonic-gate while (n-->0) {
15057c478bd9Sstevel@tonic-gate if ((flags & *pairp) == *pairp) {
15067c478bd9Sstevel@tonic-gate pairp++;
15077c478bd9Sstevel@tonic-gate break;
15087c478bd9Sstevel@tonic-gate } else {
15097c478bd9Sstevel@tonic-gate pairp += 2;
15107c478bd9Sstevel@tonic-gate }
15117c478bd9Sstevel@tonic-gate }
15127c478bd9Sstevel@tonic-gate (void) putchar(*pairp);
15137c478bd9Sstevel@tonic-gate curcol++;
15147c478bd9Sstevel@tonic-gate }
15157c478bd9Sstevel@tonic-gate
15167c478bd9Sstevel@tonic-gate /*
15177c478bd9Sstevel@tonic-gate * column: get to the beginning of the next column.
15187c478bd9Sstevel@tonic-gate */
15197c478bd9Sstevel@tonic-gate static void
column(void)15207c478bd9Sstevel@tonic-gate column(void)
15217c478bd9Sstevel@tonic-gate {
15227c478bd9Sstevel@tonic-gate if (curcol == 0)
15237c478bd9Sstevel@tonic-gate return;
15247c478bd9Sstevel@tonic-gate if (mflg) {
15257c478bd9Sstevel@tonic-gate (void) putc(',', stdout);
15267c478bd9Sstevel@tonic-gate curcol++;
15277c478bd9Sstevel@tonic-gate if (curcol + colwidth + 2 > num_cols) {
15287c478bd9Sstevel@tonic-gate (void) putc('\n', stdout);
15297c478bd9Sstevel@tonic-gate curcol = 0;
15307c478bd9Sstevel@tonic-gate return;
15317c478bd9Sstevel@tonic-gate }
15327c478bd9Sstevel@tonic-gate (void) putc(' ', stdout);
15337c478bd9Sstevel@tonic-gate curcol++;
15347c478bd9Sstevel@tonic-gate return;
15357c478bd9Sstevel@tonic-gate }
15367c478bd9Sstevel@tonic-gate if (Cflg == 0) {
15377c478bd9Sstevel@tonic-gate (void) putc('\n', stdout);
15387c478bd9Sstevel@tonic-gate curcol = 0;
15397c478bd9Sstevel@tonic-gate return;
15407c478bd9Sstevel@tonic-gate }
15417c478bd9Sstevel@tonic-gate if ((curcol / colwidth + 2) * colwidth > num_cols) {
15427c478bd9Sstevel@tonic-gate (void) putc('\n', stdout);
15437c478bd9Sstevel@tonic-gate curcol = 0;
15447c478bd9Sstevel@tonic-gate return;
15457c478bd9Sstevel@tonic-gate }
15467c478bd9Sstevel@tonic-gate do {
15477c478bd9Sstevel@tonic-gate (void) putc(' ', stdout);
15487c478bd9Sstevel@tonic-gate curcol++;
15497c478bd9Sstevel@tonic-gate } while (curcol % colwidth);
15507c478bd9Sstevel@tonic-gate }
15517c478bd9Sstevel@tonic-gate
15527c478bd9Sstevel@tonic-gate static void
new_line(void)15537c478bd9Sstevel@tonic-gate new_line(void)
15547c478bd9Sstevel@tonic-gate {
15557c478bd9Sstevel@tonic-gate if (curcol) {
15567c478bd9Sstevel@tonic-gate first = 0;
15577c478bd9Sstevel@tonic-gate (void) putc('\n', stdout);
15587c478bd9Sstevel@tonic-gate curcol = 0;
15597c478bd9Sstevel@tonic-gate }
15607c478bd9Sstevel@tonic-gate }
15617c478bd9Sstevel@tonic-gate
15627c478bd9Sstevel@tonic-gate /*
15637c478bd9Sstevel@tonic-gate * read each filename in directory dir and store its
15647c478bd9Sstevel@tonic-gate * status in flist[nfiles]
15657c478bd9Sstevel@tonic-gate * use makename() to form pathname dir/filename;
15667c478bd9Sstevel@tonic-gate */
15677c478bd9Sstevel@tonic-gate static void
rddir(char * dir,struct ditem * myinfo)15687c478bd9Sstevel@tonic-gate rddir(char *dir, struct ditem *myinfo)
15697c478bd9Sstevel@tonic-gate {
15707c478bd9Sstevel@tonic-gate struct dirent *dentry;
15717c478bd9Sstevel@tonic-gate DIR *dirf;
15727c478bd9Sstevel@tonic-gate int j;
15737c478bd9Sstevel@tonic-gate struct lbuf *ep;
15747c478bd9Sstevel@tonic-gate int width;
15757c478bd9Sstevel@tonic-gate
15767c478bd9Sstevel@tonic-gate if ((dirf = opendir(dir)) == NULL) {
15777c478bd9Sstevel@tonic-gate (void) fflush(stdout);
15787c478bd9Sstevel@tonic-gate perror(dir);
15797c478bd9Sstevel@tonic-gate err = 2;
15807c478bd9Sstevel@tonic-gate return;
15817c478bd9Sstevel@tonic-gate } else {
15827c478bd9Sstevel@tonic-gate tblocks = 0;
15837c478bd9Sstevel@tonic-gate for (;;) {
15847c478bd9Sstevel@tonic-gate errno = 0;
15857c478bd9Sstevel@tonic-gate if ((dentry = readdir(dirf)) == NULL)
15867c478bd9Sstevel@tonic-gate break;
15877c478bd9Sstevel@tonic-gate if (aflg == 0 && dentry->d_name[0] == '.' &&
15887c478bd9Sstevel@tonic-gate (Aflg == 0 ||
15897c478bd9Sstevel@tonic-gate dentry->d_name[1] == '\0' ||
159029e6ab97SIgor Kozhukhov (dentry->d_name[1] == '.' &&
159129e6ab97SIgor Kozhukhov dentry->d_name[2] == '\0')))
15927c478bd9Sstevel@tonic-gate /*
15937c478bd9Sstevel@tonic-gate * check for directory items '.', '..',
15947c478bd9Sstevel@tonic-gate * and items without valid inode-number;
15957c478bd9Sstevel@tonic-gate */
15967c478bd9Sstevel@tonic-gate continue;
15977c478bd9Sstevel@tonic-gate
15985e1c72e1SJason King /* skip entries ending in ~ if -B was given */
15995e1c72e1SJason King if (Bflg &&
16005e1c72e1SJason King dentry->d_name[strlen(dentry->d_name) - 1] == '~')
16015e1c72e1SJason King continue;
16027c478bd9Sstevel@tonic-gate if (Cflg || mflg) {
16037c478bd9Sstevel@tonic-gate width = strcol((unsigned char *)dentry->d_name);
16047c478bd9Sstevel@tonic-gate if (width > filewidth)
16057c478bd9Sstevel@tonic-gate filewidth = width;
16067c478bd9Sstevel@tonic-gate }
16077c478bd9Sstevel@tonic-gate ep = gstat(makename(dir, dentry->d_name), 0, myinfo);
16087c478bd9Sstevel@tonic-gate if (ep == NULL) {
16097c478bd9Sstevel@tonic-gate if (nomocore)
1610da6c28aaSamw exit(2);
16117c478bd9Sstevel@tonic-gate continue;
16127c478bd9Sstevel@tonic-gate } else {
16137c478bd9Sstevel@tonic-gate ep->lnum = dentry->d_ino;
16147c478bd9Sstevel@tonic-gate for (j = 0; dentry->d_name[j] != '\0'; j++)
16157c478bd9Sstevel@tonic-gate ep->ln.lname[j] = dentry->d_name[j];
16167c478bd9Sstevel@tonic-gate ep->ln.lname[j] = '\0';
161791bbe3fdSBill Pijewski
161891bbe3fdSBill Pijewski /*
161991bbe3fdSBill Pijewski * Since this entry doesn't need to be sorted
162091bbe3fdSBill Pijewski * or further processed, print it right away.
162191bbe3fdSBill Pijewski */
162291bbe3fdSBill Pijewski if (noflist) {
162391bbe3fdSBill Pijewski pem(&ep, &ep + 1, 0);
162491bbe3fdSBill Pijewski nfiles--;
162591bbe3fdSBill Pijewski }
16267c478bd9Sstevel@tonic-gate }
16277c478bd9Sstevel@tonic-gate }
16287c478bd9Sstevel@tonic-gate if (errno) {
16297c478bd9Sstevel@tonic-gate int sav_errno = errno;
16307c478bd9Sstevel@tonic-gate
16317c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
16327c478bd9Sstevel@tonic-gate gettext("ls: error reading directory %s: %s\n"),
16337c478bd9Sstevel@tonic-gate dir, strerror(sav_errno));
16347c478bd9Sstevel@tonic-gate }
16357c478bd9Sstevel@tonic-gate (void) closedir(dirf);
16367c478bd9Sstevel@tonic-gate colwidth = fixedwidth + filewidth;
16377c478bd9Sstevel@tonic-gate }
16387c478bd9Sstevel@tonic-gate }
16397c478bd9Sstevel@tonic-gate
16407c478bd9Sstevel@tonic-gate /*
16417c478bd9Sstevel@tonic-gate * Attaching a link to an inode's ancestors. Search
16427c478bd9Sstevel@tonic-gate * through the ancestors to check for cycles (an inode which
16437c478bd9Sstevel@tonic-gate * we have already tracked in this inodes ancestry). If a cycle
16447c478bd9Sstevel@tonic-gate * is detected, set the exit code and record the fact so that
16457c478bd9Sstevel@tonic-gate * it is reported at the right time when printing the directory.
16467c478bd9Sstevel@tonic-gate * In addition, set the exit code. Note: If the -a flag was
16477c478bd9Sstevel@tonic-gate * specified, we don't want to check for cycles for directories
16487c478bd9Sstevel@tonic-gate * ending in '/.' or '/..' unless they were specified on the
16497c478bd9Sstevel@tonic-gate * command line.
16507c478bd9Sstevel@tonic-gate */
16517c478bd9Sstevel@tonic-gate static void
record_ancestry(char * file,struct stat * pstatb,struct lbuf * rep,int argfl,struct ditem * myparent)16527c478bd9Sstevel@tonic-gate record_ancestry(char *file, struct stat *pstatb, struct lbuf *rep,
16537c478bd9Sstevel@tonic-gate int argfl, struct ditem *myparent)
16547c478bd9Sstevel@tonic-gate {
16557c478bd9Sstevel@tonic-gate size_t file_len;
16567c478bd9Sstevel@tonic-gate struct ditem *myinfo;
16577c478bd9Sstevel@tonic-gate struct ditem *tptr;
16587c478bd9Sstevel@tonic-gate
16597c478bd9Sstevel@tonic-gate file_len = strlen(file);
16607c478bd9Sstevel@tonic-gate if (!aflg || argfl || (NOTWORKINGDIR(file, file_len) &&
16617c478bd9Sstevel@tonic-gate NOTPARENTDIR(file, file_len))) {
16627c478bd9Sstevel@tonic-gate /*
16637c478bd9Sstevel@tonic-gate * Add this inode's ancestry
16647c478bd9Sstevel@tonic-gate * info and insert it into the
16657c478bd9Sstevel@tonic-gate * ancestry list by pointing
16667c478bd9Sstevel@tonic-gate * back to its parent. We save
16677c478bd9Sstevel@tonic-gate * it (in rep) with the other info
16687c478bd9Sstevel@tonic-gate * we're gathering for this inode.
16697c478bd9Sstevel@tonic-gate */
16707c478bd9Sstevel@tonic-gate if ((myinfo = malloc(
16717c478bd9Sstevel@tonic-gate sizeof (struct ditem))) == NULL) {
16727c478bd9Sstevel@tonic-gate perror("ls");
16737c478bd9Sstevel@tonic-gate exit(2);
16747c478bd9Sstevel@tonic-gate }
16757c478bd9Sstevel@tonic-gate myinfo->dev = pstatb->st_dev;
16767c478bd9Sstevel@tonic-gate myinfo->ino = pstatb->st_ino;
16777c478bd9Sstevel@tonic-gate myinfo->parent = myparent;
16787c478bd9Sstevel@tonic-gate rep->ancinfo = myinfo;
16797c478bd9Sstevel@tonic-gate
16807c478bd9Sstevel@tonic-gate /*
16817c478bd9Sstevel@tonic-gate * If this node has the same device id and
16827c478bd9Sstevel@tonic-gate * inode number of one of its ancestors,
16837c478bd9Sstevel@tonic-gate * then we've detected a cycle.
16847c478bd9Sstevel@tonic-gate */
16857c478bd9Sstevel@tonic-gate if (myparent != NULL) {
16867c478bd9Sstevel@tonic-gate for (tptr = myparent; tptr->parent != NULL;
16877c478bd9Sstevel@tonic-gate tptr = tptr->parent) {
16887c478bd9Sstevel@tonic-gate if ((tptr->dev == pstatb->st_dev) &&
16897c478bd9Sstevel@tonic-gate (tptr->ino == pstatb->st_ino)) {
16907c478bd9Sstevel@tonic-gate /*
16917c478bd9Sstevel@tonic-gate * Cycle detected for this
16927c478bd9Sstevel@tonic-gate * directory. Record the fact
16937c478bd9Sstevel@tonic-gate * it is a cycle so we don't
16947c478bd9Sstevel@tonic-gate * try to process this
16957c478bd9Sstevel@tonic-gate * directory as we are
16967c478bd9Sstevel@tonic-gate * walking through the
16977c478bd9Sstevel@tonic-gate * list of directories.
16987c478bd9Sstevel@tonic-gate */
16997c478bd9Sstevel@tonic-gate rep->cycle = 1;
17007c478bd9Sstevel@tonic-gate err = 2;
17017c478bd9Sstevel@tonic-gate break;
17027c478bd9Sstevel@tonic-gate }
17037c478bd9Sstevel@tonic-gate }
17047c478bd9Sstevel@tonic-gate }
17057c478bd9Sstevel@tonic-gate }
17067c478bd9Sstevel@tonic-gate }
17077c478bd9Sstevel@tonic-gate
170864d425a7Sny /*
170964d425a7Sny * Do re-calculate the mode for group for ACE_T type of acls.
171064d425a7Sny * This is because, if the server's FS happens to be UFS, supporting
171164d425a7Sny * POSIX ACL's, then it does a special calculation of group mode
171264d425a7Sny * to be the bitwise OR of CLASS_OBJ and GROUP_OBJ (see PSARC/2001/717.)
171364d425a7Sny *
171464d425a7Sny * This algorithm is from the NFSv4 ACL Draft. Here a part of that
171564d425a7Sny * algorithm is used for the group mode calculation only.
171664d425a7Sny * What is modified here from the algorithm is that only the
171764d425a7Sny * entries with flags ACE_GROUP are considered. For each entry
17186027b860SPeter Tribble * with ACE_GROUP flag, the first occurrence of a specific access
171964d425a7Sny * is checked if it is allowed.
1720e2442894Sny * We are not interested in perms for user and other, as they
172164d425a7Sny * were taken from st_mode value.
172264d425a7Sny * We are not interested in a_who field of ACE, as we need just
172364d425a7Sny * unix mode bits for the group.
172464d425a7Sny */
1725e2442894Sny
1726e2442894Sny #define OWNED_GROUP (ACE_GROUP | ACE_IDENTIFIER_GROUP)
1727e2442894Sny #define IS_TYPE_ALLOWED(type) ((type) == ACE_ACCESS_ALLOWED_ACE_TYPE)
1728e2442894Sny
172964d425a7Sny int
grp_mask_to_mode(struct lbuf * p)173027dd1e87SMark Shellenbaum grp_mask_to_mode(struct lbuf *p)
173164d425a7Sny {
173264d425a7Sny int mode = 0, seen = 0;
173364d425a7Sny int acecnt;
1734e2442894Sny int flags;
173564d425a7Sny ace_t *ap;
173627dd1e87SMark Shellenbaum acl_t *acep = p->aclp;
173764d425a7Sny
173864d425a7Sny acecnt = acl_cnt(acep);
173964d425a7Sny for (ap = (ace_t *)acl_data(acep); acecnt--; ap++) {
1740e2442894Sny
1741e2442894Sny if (ap->a_type != ACE_ACCESS_ALLOWED_ACE_TYPE &&
1742e2442894Sny ap->a_type != ACE_ACCESS_DENIED_ACE_TYPE)
1743e2442894Sny continue;
1744e2442894Sny
1745e2442894Sny if (ap->a_flags & ACE_INHERIT_ONLY_ACE)
1746e2442894Sny continue;
1747e2442894Sny
1748e2442894Sny /*
1749e2442894Sny * if it is first group@ or first everyone@
1750e2442894Sny * for each of read, write and execute, then
1751e2442894Sny * that will be the group mode bit.
1752e2442894Sny */
1753e2442894Sny flags = ap->a_flags & ACE_TYPE_FLAGS;
175427dd1e87SMark Shellenbaum if (flags == OWNED_GROUP || (flags == ACE_IDENTIFIER_GROUP &&
175527dd1e87SMark Shellenbaum ap->a_who == p->lgid) || flags == ACE_EVERYONE) {
1756e2442894Sny if (ap->a_access_mask & ACE_READ_DATA) {
1757e2442894Sny if (!(seen & S_IRGRP)) {
1758e2442894Sny seen |= S_IRGRP;
1759e2442894Sny if (IS_TYPE_ALLOWED(ap->a_type))
1760e2442894Sny mode |= S_IRGRP;
176164d425a7Sny }
1762e2442894Sny }
1763e2442894Sny if (ap->a_access_mask & ACE_WRITE_DATA) {
1764e2442894Sny if (!(seen & S_IWGRP)) {
1765e2442894Sny seen |= S_IWGRP;
1766e2442894Sny if (IS_TYPE_ALLOWED(ap->a_type))
1767e2442894Sny mode |= S_IWGRP;
176864d425a7Sny }
1769e2442894Sny }
1770e2442894Sny if (ap->a_access_mask & ACE_EXECUTE) {
1771e2442894Sny if (!(seen & S_IXGRP)) {
1772e2442894Sny seen |= S_IXGRP;
1773e2442894Sny if (IS_TYPE_ALLOWED(ap->a_type))
1774e2442894Sny mode |= S_IXGRP;
177564d425a7Sny }
177664d425a7Sny }
177764d425a7Sny }
177864d425a7Sny }
177964d425a7Sny return (mode);
178064d425a7Sny }
178164d425a7Sny
17827c478bd9Sstevel@tonic-gate /*
17837c478bd9Sstevel@tonic-gate * get status of file and recomputes tblocks;
17847c478bd9Sstevel@tonic-gate * argfl = 1 if file is a name in ls-command and = 0
17857c478bd9Sstevel@tonic-gate * for filename in a directory whose name is an
17867c478bd9Sstevel@tonic-gate * argument in the command;
17877c478bd9Sstevel@tonic-gate * stores a pointer in flist[nfiles] and
17887c478bd9Sstevel@tonic-gate * returns that pointer;
17897c478bd9Sstevel@tonic-gate * returns NULL if failed;
17907c478bd9Sstevel@tonic-gate */
17917c478bd9Sstevel@tonic-gate static struct lbuf *
gstat(char * file,int argfl,struct ditem * myparent)17927c478bd9Sstevel@tonic-gate gstat(char *file, int argfl, struct ditem *myparent)
17937c478bd9Sstevel@tonic-gate {
17947c478bd9Sstevel@tonic-gate struct stat statb, statb1;
17957c478bd9Sstevel@tonic-gate struct lbuf *rep;
17967c478bd9Sstevel@tonic-gate char buf[BUFSIZ];
17977c478bd9Sstevel@tonic-gate ssize_t cc;
17987c478bd9Sstevel@tonic-gate int (*statf)() = ((Lflg) || (Hflg && argfl)) ? stat : lstat;
17997c478bd9Sstevel@tonic-gate int aclcnt;
1800fa9e4066Sahrens int error;
18017c478bd9Sstevel@tonic-gate aclent_t *tp;
18027c478bd9Sstevel@tonic-gate o_mode_t groupperm, mask;
18037c478bd9Sstevel@tonic-gate int grouppermfound, maskfound;
18047c478bd9Sstevel@tonic-gate
18057c478bd9Sstevel@tonic-gate if (nomocore)
18067c478bd9Sstevel@tonic-gate return (NULL);
18077c478bd9Sstevel@tonic-gate
18087c478bd9Sstevel@tonic-gate if (nfiles >= maxfils) {
18097c478bd9Sstevel@tonic-gate /*
18107c478bd9Sstevel@tonic-gate * all flist/lbuf pair assigned files, time to get some
18117c478bd9Sstevel@tonic-gate * more space
18127c478bd9Sstevel@tonic-gate */
18137c478bd9Sstevel@tonic-gate maxfils += quantn;
18147c478bd9Sstevel@tonic-gate if (((flist = realloc(flist,
18157c478bd9Sstevel@tonic-gate maxfils * sizeof (struct lbuf *))) == NULL) ||
18167c478bd9Sstevel@tonic-gate ((nxtlbf = malloc(quantn *
18177c478bd9Sstevel@tonic-gate sizeof (struct lbuf))) == NULL)) {
18187c478bd9Sstevel@tonic-gate perror("ls");
18197c478bd9Sstevel@tonic-gate nomocore = 1;
18207c478bd9Sstevel@tonic-gate return (NULL);
18217c478bd9Sstevel@tonic-gate }
18227c478bd9Sstevel@tonic-gate }
18237c478bd9Sstevel@tonic-gate
18247c478bd9Sstevel@tonic-gate /*
18257c478bd9Sstevel@tonic-gate * nfiles is reset to nargs for each directory
18267c478bd9Sstevel@tonic-gate * that is given as an argument maxn is checked
18277c478bd9Sstevel@tonic-gate * to prevent the assignment of an lbuf to a flist entry
18287c478bd9Sstevel@tonic-gate * that already has one assigned.
18297c478bd9Sstevel@tonic-gate */
18307c478bd9Sstevel@tonic-gate if (nfiles >= maxn) {
18317c478bd9Sstevel@tonic-gate rep = nxtlbf++;
18327c478bd9Sstevel@tonic-gate flist[nfiles++] = rep;
18337c478bd9Sstevel@tonic-gate maxn = nfiles;
18347c478bd9Sstevel@tonic-gate } else {
18357c478bd9Sstevel@tonic-gate rep = flist[nfiles++];
18367c478bd9Sstevel@tonic-gate }
183744f31f13Sbasabi
1838b9c81738SGary Mills /* Clear the lbuf */
1839b9c81738SGary Mills (void) memset((void *) rep, 0, sizeof (struct lbuf));
1840b9c81738SGary Mills
184191bbe3fdSBill Pijewski /*
184291bbe3fdSBill Pijewski * When noflist is set, none of the extra information about the dirent
1843b9c81738SGary Mills * will be printed, so omit remaining initialization of this lbuf
1844b9c81738SGary Mills * as well as the stat(2) call.
184591bbe3fdSBill Pijewski */
184691bbe3fdSBill Pijewski if (!argfl && noflist)
184791bbe3fdSBill Pijewski return (rep);
184891bbe3fdSBill Pijewski
1849b9c81738SGary Mills /* Initialize non-zero members */
18506027b860SPeter Tribble rep->lat.tv_sec = rep->lct.tv_sec = rep->lmt.tv_sec = starttime;
185144f31f13Sbasabi
18527c478bd9Sstevel@tonic-gate if (argfl || statreq) {
18537c478bd9Sstevel@tonic-gate int doacl;
18547c478bd9Sstevel@tonic-gate
18557c478bd9Sstevel@tonic-gate if (lflg)
18567c478bd9Sstevel@tonic-gate doacl = 1;
18577c478bd9Sstevel@tonic-gate else
18587c478bd9Sstevel@tonic-gate doacl = 0;
185944f31f13Sbasabi
18607c478bd9Sstevel@tonic-gate if ((*statf)(file, &statb) < 0) {
18617c478bd9Sstevel@tonic-gate if (argfl || errno != ENOENT ||
18627c478bd9Sstevel@tonic-gate (Lflg && lstat(file, &statb) == 0)) {
18637c478bd9Sstevel@tonic-gate /*
18647c478bd9Sstevel@tonic-gate * Avoid race between readdir and lstat.
18657c478bd9Sstevel@tonic-gate * Print error message in case of dangling link.
18667c478bd9Sstevel@tonic-gate */
18677c478bd9Sstevel@tonic-gate perror(file);
18685e1c72e1SJason King err = 2;
18697c478bd9Sstevel@tonic-gate }
18707c478bd9Sstevel@tonic-gate nfiles--;
18717c478bd9Sstevel@tonic-gate return (NULL);
18727c478bd9Sstevel@tonic-gate }
18737c478bd9Sstevel@tonic-gate
18747c478bd9Sstevel@tonic-gate /*
18757c478bd9Sstevel@tonic-gate * If -H was specified, and the file linked to was
18767c478bd9Sstevel@tonic-gate * not a directory, then we need to get the info
18777c478bd9Sstevel@tonic-gate * for the symlink itself.
18787c478bd9Sstevel@tonic-gate */
18797c478bd9Sstevel@tonic-gate if ((Hflg) && (argfl) &&
18807c478bd9Sstevel@tonic-gate ((statb.st_mode & S_IFMT) != S_IFDIR)) {
18817c478bd9Sstevel@tonic-gate if (lstat(file, &statb) < 0) {
18827c478bd9Sstevel@tonic-gate perror(file);
18835e1c72e1SJason King err = 2;
18847c478bd9Sstevel@tonic-gate }
18857c478bd9Sstevel@tonic-gate }
18867c478bd9Sstevel@tonic-gate
18877c478bd9Sstevel@tonic-gate rep->lnum = statb.st_ino;
18887c478bd9Sstevel@tonic-gate rep->lsize = statb.st_size;
18897c478bd9Sstevel@tonic-gate rep->lblocks = statb.st_blocks;
18901b628248SJason King if (colorflg)
18911b628248SJason King rep->color = ls_color_find(file, statb.st_mode);
18921b628248SJason King
18937c478bd9Sstevel@tonic-gate switch (statb.st_mode & S_IFMT) {
18947c478bd9Sstevel@tonic-gate case S_IFDIR:
18957c478bd9Sstevel@tonic-gate rep->ltype = 'd';
18967c478bd9Sstevel@tonic-gate if (Rflg) {
18977c478bd9Sstevel@tonic-gate record_ancestry(file, &statb, rep,
18987c478bd9Sstevel@tonic-gate argfl, myparent);
18997c478bd9Sstevel@tonic-gate }
19007c478bd9Sstevel@tonic-gate break;
19017c478bd9Sstevel@tonic-gate case S_IFBLK:
19027c478bd9Sstevel@tonic-gate rep->ltype = 'b';
19037c478bd9Sstevel@tonic-gate rep->lsize = (off_t)statb.st_rdev;
19047c478bd9Sstevel@tonic-gate break;
19057c478bd9Sstevel@tonic-gate case S_IFCHR:
19067c478bd9Sstevel@tonic-gate rep->ltype = 'c';
19077c478bd9Sstevel@tonic-gate rep->lsize = (off_t)statb.st_rdev;
19087c478bd9Sstevel@tonic-gate break;
19097c478bd9Sstevel@tonic-gate case S_IFIFO:
19107c478bd9Sstevel@tonic-gate rep->ltype = 'p';
19117c478bd9Sstevel@tonic-gate break;
19127c478bd9Sstevel@tonic-gate case S_IFSOCK:
19137c478bd9Sstevel@tonic-gate rep->ltype = 's';
19147c478bd9Sstevel@tonic-gate rep->lsize = 0;
19157c478bd9Sstevel@tonic-gate break;
19167c478bd9Sstevel@tonic-gate case S_IFLNK:
19177c478bd9Sstevel@tonic-gate /* symbolic links may not have ACLs, so elide acl() */
19187c478bd9Sstevel@tonic-gate if ((Lflg == 0) || (Hflg == 0) ||
19197c478bd9Sstevel@tonic-gate ((Hflg) && (!argfl))) {
19207c478bd9Sstevel@tonic-gate doacl = 0;
19217c478bd9Sstevel@tonic-gate }
19227c478bd9Sstevel@tonic-gate rep->ltype = 'l';
19231b628248SJason King if (lflg || colorflg) {
19247c478bd9Sstevel@tonic-gate cc = readlink(file, buf, BUFSIZ);
19251b628248SJason King if (cc < 0)
19261b628248SJason King break;
19277c478bd9Sstevel@tonic-gate
19281b628248SJason King /*
19291b628248SJason King * follow the symbolic link
19301b628248SJason King * to generate the appropriate
19311b628248SJason King * Fflg marker for the object
19321b628248SJason King * eg, /bin -> /sym/bin/
19331b628248SJason King */
19341b628248SJason King error = 0;
19351b628248SJason King if (Fflg || pflg || colorflg)
19361b628248SJason King error = stat(file, &statb1);
19371b628248SJason King
19381b628248SJason King if (colorflg) {
19391b628248SJason King if (error >= 0)
19401b628248SJason King rep->link_color =
19411b628248SJason King ls_color_find(file,
19421b628248SJason King statb1.st_mode);
19431b628248SJason King else
19441b628248SJason King rep->link_color =
19451b628248SJason King lsc_orphan;
19461b628248SJason King }
19471b628248SJason King
19481b628248SJason King if ((Fflg || pflg) && error >= 0) {
19491b628248SJason King switch (statb1.st_mode & S_IFMT) {
19501b628248SJason King case S_IFDIR:
19511b628248SJason King buf[cc++] = '/';
19521b628248SJason King break;
19531b628248SJason King case S_IFSOCK:
19541b628248SJason King buf[cc++] = '=';
19551b628248SJason King break;
19561b628248SJason King case S_IFDOOR:
19571b628248SJason King buf[cc++] = '>';
19581b628248SJason King break;
19591b628248SJason King case S_IFIFO:
19601b628248SJason King buf[cc++] = '|';
19611b628248SJason King break;
19621b628248SJason King default:
19631b628248SJason King if ((statb1.st_mode & ~S_IFMT) &
19641b628248SJason King (S_IXUSR|S_IXGRP| S_IXOTH))
19651b628248SJason King buf[cc++] = '*';
19661b628248SJason King break;
19677c478bd9Sstevel@tonic-gate }
19687c478bd9Sstevel@tonic-gate }
19691b628248SJason King buf[cc] = '\0';
19701b628248SJason King rep->flinkto = strdup(buf);
197138f2a414SAlbert Lee if (rep->flinkto == NULL) {
197238f2a414SAlbert Lee perror("ls");
197338f2a414SAlbert Lee nomocore = 1;
197438f2a414SAlbert Lee return (NULL);
197538f2a414SAlbert Lee }
19767c478bd9Sstevel@tonic-gate break;
19777c478bd9Sstevel@tonic-gate }
19787c478bd9Sstevel@tonic-gate
19797c478bd9Sstevel@tonic-gate /*
19807c478bd9Sstevel@tonic-gate * ls /sym behaves differently from ls /sym/
19817c478bd9Sstevel@tonic-gate * when /sym is a symbolic link. This is fixed
19827c478bd9Sstevel@tonic-gate * when explicit arguments are specified.
19837c478bd9Sstevel@tonic-gate */
19847c478bd9Sstevel@tonic-gate
19857c478bd9Sstevel@tonic-gate #ifdef XPG6
19867c478bd9Sstevel@tonic-gate /* Do not follow a symlink when -F is specified */
19877c478bd9Sstevel@tonic-gate if ((!argfl) || (argfl && Fflg) ||
19887c478bd9Sstevel@tonic-gate (stat(file, &statb1) < 0))
19897c478bd9Sstevel@tonic-gate #else
19907c478bd9Sstevel@tonic-gate /* Follow a symlink when -F is specified */
19917c478bd9Sstevel@tonic-gate if (!argfl || stat(file, &statb1) < 0)
19927c478bd9Sstevel@tonic-gate #endif /* XPG6 */
19937c478bd9Sstevel@tonic-gate break;
19947c478bd9Sstevel@tonic-gate if ((statb1.st_mode & S_IFMT) == S_IFDIR) {
19957c478bd9Sstevel@tonic-gate statb = statb1;
19967c478bd9Sstevel@tonic-gate rep->ltype = 'd';
19977c478bd9Sstevel@tonic-gate rep->lsize = statb1.st_size;
19987c478bd9Sstevel@tonic-gate if (Rflg) {
19997c478bd9Sstevel@tonic-gate record_ancestry(file, &statb, rep,
20007c478bd9Sstevel@tonic-gate argfl, myparent);
20017c478bd9Sstevel@tonic-gate }
20027c478bd9Sstevel@tonic-gate }
20037c478bd9Sstevel@tonic-gate break;
20047c478bd9Sstevel@tonic-gate case S_IFDOOR:
20057c478bd9Sstevel@tonic-gate rep->ltype = 'D';
20067c478bd9Sstevel@tonic-gate break;
20077c478bd9Sstevel@tonic-gate case S_IFREG:
20087c478bd9Sstevel@tonic-gate rep->ltype = '-';
20097c478bd9Sstevel@tonic-gate break;
20107c478bd9Sstevel@tonic-gate case S_IFPORT:
20117c478bd9Sstevel@tonic-gate rep->ltype = 'P';
20127c478bd9Sstevel@tonic-gate break;
20137c478bd9Sstevel@tonic-gate default:
20147c478bd9Sstevel@tonic-gate rep->ltype = '?';
20157c478bd9Sstevel@tonic-gate break;
20167c478bd9Sstevel@tonic-gate }
20177c478bd9Sstevel@tonic-gate rep->lflags = statb.st_mode & ~S_IFMT;
20187c478bd9Sstevel@tonic-gate
20197c478bd9Sstevel@tonic-gate if (!S_ISREG(statb.st_mode))
20207c478bd9Sstevel@tonic-gate rep->lflags |= LS_NOTREG;
20217c478bd9Sstevel@tonic-gate
202244f31f13Sbasabi rep->luid = statb.st_uid;
202344f31f13Sbasabi rep->lgid = statb.st_gid;
202444f31f13Sbasabi rep->lnl = statb.st_nlink;
202544f31f13Sbasabi if (uflg || (tmflg && atm))
202644f31f13Sbasabi rep->lmtime = statb.st_atim;
202744f31f13Sbasabi else if (cflg || (tmflg && ctm))
202844f31f13Sbasabi rep->lmtime = statb.st_ctim;
202944f31f13Sbasabi else
203044f31f13Sbasabi rep->lmtime = statb.st_mtim;
203144f31f13Sbasabi rep->lat = statb.st_atim;
203244f31f13Sbasabi rep->lct = statb.st_ctim;
203344f31f13Sbasabi rep->lmt = statb.st_mtim;
203444f31f13Sbasabi
20357c478bd9Sstevel@tonic-gate /* ACL: check acl entries count */
20367c478bd9Sstevel@tonic-gate if (doacl) {
20377c478bd9Sstevel@tonic-gate
2038fa9e4066Sahrens error = acl_get(file, 0, &rep->aclp);
2039fa9e4066Sahrens if (error) {
2040fa9e4066Sahrens (void) fprintf(stderr,
2041fa9e4066Sahrens gettext("ls: can't read ACL on %s: %s\n"),
2042fa9e4066Sahrens file, acl_strerror(error));
204344f31f13Sbasabi rep->acl = ' ';
204456798e90Sbasabi acl_err++;
204544f31f13Sbasabi return (rep);
2046fa9e4066Sahrens }
20477c478bd9Sstevel@tonic-gate
2048fa9e4066Sahrens rep->acl = ' ';
20497c478bd9Sstevel@tonic-gate
2050fa9e4066Sahrens if (rep->aclp &&
2051fa9e4066Sahrens ((acl_flags(rep->aclp) & ACL_IS_TRIVIAL) == 0)) {
2052fa9e4066Sahrens rep->acl = '+';
20537c478bd9Sstevel@tonic-gate /*
2054fa9e4066Sahrens * Special handling for ufs aka aclent_t ACL's
20557c478bd9Sstevel@tonic-gate */
205664d425a7Sny if (acl_type(rep->aclp) == ACLENT_T) {
2057fa9e4066Sahrens /*
2058fa9e4066Sahrens * For files with non-trivial acls, the
2059fa9e4066Sahrens * effective group permissions are the
2060fa9e4066Sahrens * intersection of the GROUP_OBJ value
2061fa9e4066Sahrens * and the CLASS_OBJ (acl mask) value.
2062fa9e4066Sahrens * Determine both the GROUP_OBJ and
2063fa9e4066Sahrens * CLASS_OBJ for this file and insert
2064fa9e4066Sahrens * the logical AND of those two values
2065fa9e4066Sahrens * in the group permissions field
2066fa9e4066Sahrens * of the lflags value for this file.
2067fa9e4066Sahrens */
20687c478bd9Sstevel@tonic-gate
2069fa9e4066Sahrens /*
2070fa9e4066Sahrens * Until found in acl list, assume
2071fa9e4066Sahrens * maximum permissions for both group
2072fa9e4066Sahrens * a nd mask. (Just in case the acl
2073fa9e4066Sahrens * lacks either value for some reason.)
2074fa9e4066Sahrens */
2075fa9e4066Sahrens groupperm = 07;
2076fa9e4066Sahrens mask = 07;
2077fa9e4066Sahrens grouppermfound = 0;
2078fa9e4066Sahrens maskfound = 0;
2079fa9e4066Sahrens aclcnt = acl_cnt(rep->aclp);
2080fa9e4066Sahrens for (tp =
2081fa9e4066Sahrens (aclent_t *)acl_data(rep->aclp);
2082fa9e4066Sahrens aclcnt--; tp++) {
2083fa9e4066Sahrens if (tp->a_type == GROUP_OBJ) {
2084fa9e4066Sahrens groupperm = tp->a_perm;
2085fa9e4066Sahrens grouppermfound = 1;
2086fa9e4066Sahrens continue;
2087fa9e4066Sahrens }
2088fa9e4066Sahrens if (tp->a_type == CLASS_OBJ) {
2089fa9e4066Sahrens mask = tp->a_perm;
2090fa9e4066Sahrens maskfound = 1;
2091fa9e4066Sahrens }
2092fa9e4066Sahrens if (grouppermfound && maskfound)
2093fa9e4066Sahrens break;
20947c478bd9Sstevel@tonic-gate }
20957c478bd9Sstevel@tonic-gate
20967c478bd9Sstevel@tonic-gate
2097fa9e4066Sahrens /* reset all the group bits */
2098fa9e4066Sahrens rep->lflags &= ~S_IRWXG;
20997c478bd9Sstevel@tonic-gate
2100fa9e4066Sahrens /*
2101fa9e4066Sahrens * Now set them to the logical AND of
2102fa9e4066Sahrens * the GROUP_OBJ permissions and the
2103fa9e4066Sahrens * acl mask.
2104fa9e4066Sahrens */
21057c478bd9Sstevel@tonic-gate
2106fa9e4066Sahrens rep->lflags |= (groupperm & mask) << 3;
2107fa9e4066Sahrens
210864d425a7Sny } else if (acl_type(rep->aclp) == ACE_T) {
210964d425a7Sny int mode;
211027dd1e87SMark Shellenbaum mode = grp_mask_to_mode(rep);
211164d425a7Sny rep->lflags &= ~S_IRWXG;
211264d425a7Sny rep->lflags |= mode;
2113fa9e4066Sahrens }
21147c478bd9Sstevel@tonic-gate }
21157c478bd9Sstevel@tonic-gate
21165a5eeccaSmarks if (!vflg && !Vflg && rep->aclp) {
21175a5eeccaSmarks acl_free(rep->aclp);
21185a5eeccaSmarks rep->aclp = NULL;
21195a5eeccaSmarks }
21205a5eeccaSmarks
21217c478bd9Sstevel@tonic-gate if (atflg && pathconf(file, _PC_XATTR_EXISTS) == 1)
21227c478bd9Sstevel@tonic-gate rep->acl = '@';
2123da6c28aaSamw
21247c478bd9Sstevel@tonic-gate } else
21257c478bd9Sstevel@tonic-gate rep->acl = ' ';
21267c478bd9Sstevel@tonic-gate
21277c478bd9Sstevel@tonic-gate /* mask ISARG and other file-type bits */
21287c478bd9Sstevel@tonic-gate
21297c478bd9Sstevel@tonic-gate if (rep->ltype != 'b' && rep->ltype != 'c')
21307c478bd9Sstevel@tonic-gate tblocks += rep->lblocks;
2131da6c28aaSamw
2132da6c28aaSamw /* Get extended system attributes */
2133da6c28aaSamw
2134da6c28aaSamw if ((saflg || (tmflg && crtm) || (tmflg && alltm)) &&
2135da6c28aaSamw (sysattr_support(file, _PC_SATTR_EXISTS) == 1)) {
2136da6c28aaSamw int i;
2137da6c28aaSamw
2138da6c28aaSamw sacnt = attr_count();
2139da6c28aaSamw /*
2140da6c28aaSamw * Allocate 'sacnt' size array to hold extended
2141da6c28aaSamw * system attribute name (verbose) or respective
21426027b860SPeter Tribble * symbol representation (compact).
2143da6c28aaSamw */
2144da6c28aaSamw rep->exttr = xmalloc(sacnt * sizeof (struct attrb),
2145da6c28aaSamw rep);
2146da6c28aaSamw
2147da6c28aaSamw /* initialize boolean attribute list */
2148da6c28aaSamw for (i = 0; i < sacnt; i++)
2149da6c28aaSamw rep->exttr[i].name = NULL;
2150da6c28aaSamw if (get_sysxattr(file, rep) != 0) {
2151da6c28aaSamw (void) fprintf(stderr,
2152da6c28aaSamw gettext("ls:Failed to retrieve "
2153da6c28aaSamw "extended system attribute from "
2154da6c28aaSamw "%s\n"), file);
2155da6c28aaSamw rep->exttr[0].name = xmalloc(2, rep);
2156da6c28aaSamw (void) strlcpy(rep->exttr[0].name, "?", 2);
2157da6c28aaSamw }
2158da6c28aaSamw }
21597c478bd9Sstevel@tonic-gate }
21607c478bd9Sstevel@tonic-gate return (rep);
21617c478bd9Sstevel@tonic-gate }
21627c478bd9Sstevel@tonic-gate
21637c478bd9Sstevel@tonic-gate /*
21647c478bd9Sstevel@tonic-gate * returns pathname of the form dir/file;
21657c478bd9Sstevel@tonic-gate * dir and file are null-terminated strings.
21667c478bd9Sstevel@tonic-gate */
21677c478bd9Sstevel@tonic-gate static char *
makename(char * dir,char * file)21687c478bd9Sstevel@tonic-gate makename(char *dir, char *file)
21697c478bd9Sstevel@tonic-gate {
21707c478bd9Sstevel@tonic-gate /*
21717c478bd9Sstevel@tonic-gate * PATH_MAX is the maximum length of a path name.
21727c478bd9Sstevel@tonic-gate * MAXNAMLEN is the maximum length of any path name component.
21737c478bd9Sstevel@tonic-gate * Allocate space for both, plus the '/' in the middle
21747c478bd9Sstevel@tonic-gate * and the null character at the end.
21757c478bd9Sstevel@tonic-gate * dfile is static as this is returned by makename().
21767c478bd9Sstevel@tonic-gate */
21777c478bd9Sstevel@tonic-gate static char dfile[PATH_MAX + 1 + MAXNAMLEN + 1];
21787c478bd9Sstevel@tonic-gate char *dp, *fp;
21797c478bd9Sstevel@tonic-gate
21807c478bd9Sstevel@tonic-gate dp = dfile;
21817c478bd9Sstevel@tonic-gate fp = dir;
21827c478bd9Sstevel@tonic-gate while (*fp)
21837c478bd9Sstevel@tonic-gate *dp++ = *fp++;
21847c478bd9Sstevel@tonic-gate if (dp > dfile && *(dp - 1) != '/')
21857c478bd9Sstevel@tonic-gate *dp++ = '/';
21867c478bd9Sstevel@tonic-gate fp = file;
21877c478bd9Sstevel@tonic-gate while (*fp)
21887c478bd9Sstevel@tonic-gate *dp++ = *fp++;
21897c478bd9Sstevel@tonic-gate *dp = '\0';
21907c478bd9Sstevel@tonic-gate return (dfile);
21917c478bd9Sstevel@tonic-gate }
21927c478bd9Sstevel@tonic-gate
2193*fab57d1bSGordon Ross #define NMAX 256 /* The maximum size of a SID in string format */
2194*fab57d1bSGordon Ross #define SCPYN(a, b) (void) strlcpy(a, b, NMAX)
21957c478bd9Sstevel@tonic-gate
21967c478bd9Sstevel@tonic-gate struct cachenode { /* this struct must be zeroed before using */
21977c478bd9Sstevel@tonic-gate struct cachenode *lesschild; /* subtree whose entries < val */
21987c478bd9Sstevel@tonic-gate struct cachenode *grtrchild; /* subtree whose entries > val */
21997c478bd9Sstevel@tonic-gate long val; /* the uid or gid of this entry */
22007c478bd9Sstevel@tonic-gate int initted; /* name has been filled in */
2201*fab57d1bSGordon Ross char name[NMAX]; /* the string that val maps to */
22027c478bd9Sstevel@tonic-gate };
22037c478bd9Sstevel@tonic-gate static struct cachenode *names, *groups;
2204*fab57d1bSGordon Ross static struct cachenode *user_sids, *group_sids;
22057c478bd9Sstevel@tonic-gate
22067c478bd9Sstevel@tonic-gate static struct cachenode *
findincache(struct cachenode ** head,long val)22077c478bd9Sstevel@tonic-gate findincache(struct cachenode **head, long val)
22087c478bd9Sstevel@tonic-gate {
22097c478bd9Sstevel@tonic-gate struct cachenode **parent = head;
22107c478bd9Sstevel@tonic-gate struct cachenode *c = *parent;
22117c478bd9Sstevel@tonic-gate
22127c478bd9Sstevel@tonic-gate while (c != NULL) {
22137c478bd9Sstevel@tonic-gate if (val == c->val) {
22147c478bd9Sstevel@tonic-gate /* found it */
22157c478bd9Sstevel@tonic-gate return (c);
22167c478bd9Sstevel@tonic-gate } else if (val < c->val) {
22177c478bd9Sstevel@tonic-gate parent = &c->lesschild;
22187c478bd9Sstevel@tonic-gate c = c->lesschild;
22197c478bd9Sstevel@tonic-gate } else {
22207c478bd9Sstevel@tonic-gate parent = &c->grtrchild;
22217c478bd9Sstevel@tonic-gate c = c->grtrchild;
22227c478bd9Sstevel@tonic-gate }
22237c478bd9Sstevel@tonic-gate }
22247c478bd9Sstevel@tonic-gate
22257c478bd9Sstevel@tonic-gate /* not in the cache, make a new entry for it */
22267c478bd9Sstevel@tonic-gate c = calloc(1, sizeof (struct cachenode));
22277c478bd9Sstevel@tonic-gate if (c == NULL) {
22287c478bd9Sstevel@tonic-gate perror("ls");
22297c478bd9Sstevel@tonic-gate exit(2);
22307c478bd9Sstevel@tonic-gate }
22317c478bd9Sstevel@tonic-gate *parent = c;
22327c478bd9Sstevel@tonic-gate c->val = val;
22337c478bd9Sstevel@tonic-gate return (c);
22347c478bd9Sstevel@tonic-gate }
22357c478bd9Sstevel@tonic-gate
22367c478bd9Sstevel@tonic-gate /*
22377c478bd9Sstevel@tonic-gate * get name from cache, or passwd file for a given uid;
22387c478bd9Sstevel@tonic-gate * lastuid is set to uid.
2239*fab57d1bSGordon Ross *
2240*fab57d1bSGordon Ross * If an ephemeral UID (> MAXUID) try to convert to either a
2241*fab57d1bSGordon Ross * name or a sid.
22427c478bd9Sstevel@tonic-gate */
22437c478bd9Sstevel@tonic-gate static char *
getname(uid_t uid)22447c478bd9Sstevel@tonic-gate getname(uid_t uid)
22457c478bd9Sstevel@tonic-gate {
22467c478bd9Sstevel@tonic-gate struct passwd *pwent;
22477c478bd9Sstevel@tonic-gate struct cachenode *c;
2248*fab57d1bSGordon Ross char *sid;
22497c478bd9Sstevel@tonic-gate
22507c478bd9Sstevel@tonic-gate if ((uid == lastuid) && lastuname)
22517c478bd9Sstevel@tonic-gate return (lastuname);
22527c478bd9Sstevel@tonic-gate
22537c478bd9Sstevel@tonic-gate c = findincache(&names, uid);
22547c478bd9Sstevel@tonic-gate if (c->initted == 0) {
2255*fab57d1bSGordon Ross sid = NULL;
2256*fab57d1bSGordon Ross if (uid > MAXUID &&
2257*fab57d1bSGordon Ross sid_string_by_id(uid, B_TRUE, &sid, 0) == 0) {
2258*fab57d1bSGordon Ross SCPYN(&c->name[0], sid);
2259*fab57d1bSGordon Ross free(sid);
2260*fab57d1bSGordon Ross } else if ((pwent = getpwuid(uid)) != NULL) {
22617c478bd9Sstevel@tonic-gate SCPYN(&c->name[0], pwent->pw_name);
22627c478bd9Sstevel@tonic-gate } else {
22637c478bd9Sstevel@tonic-gate (void) sprintf(&c->name[0], "%-8u", (int)uid);
22647c478bd9Sstevel@tonic-gate }
22657c478bd9Sstevel@tonic-gate c->initted = 1;
22667c478bd9Sstevel@tonic-gate }
22677c478bd9Sstevel@tonic-gate lastuid = uid;
22687c478bd9Sstevel@tonic-gate lastuname = &c->name[0];
22697c478bd9Sstevel@tonic-gate return (lastuname);
22707c478bd9Sstevel@tonic-gate }
22717c478bd9Sstevel@tonic-gate
22727c478bd9Sstevel@tonic-gate /*
22737c478bd9Sstevel@tonic-gate * get name from cache, or group file for a given gid;
22747c478bd9Sstevel@tonic-gate * lastgid is set to gid.
2275*fab57d1bSGordon Ross *
2276*fab57d1bSGordon Ross * If an ephemeral GID (> MAXUID) try to convert to either a
2277*fab57d1bSGordon Ross * name or a sid.
22787c478bd9Sstevel@tonic-gate */
22797c478bd9Sstevel@tonic-gate static char *
getgroup(gid_t gid)22807c478bd9Sstevel@tonic-gate getgroup(gid_t gid)
22817c478bd9Sstevel@tonic-gate {
22827c478bd9Sstevel@tonic-gate struct group *grent;
22837c478bd9Sstevel@tonic-gate struct cachenode *c;
2284*fab57d1bSGordon Ross char *sid;
22857c478bd9Sstevel@tonic-gate
22867c478bd9Sstevel@tonic-gate if ((gid == lastgid) && lastgname)
22877c478bd9Sstevel@tonic-gate return (lastgname);
22887c478bd9Sstevel@tonic-gate
22897c478bd9Sstevel@tonic-gate c = findincache(&groups, gid);
22907c478bd9Sstevel@tonic-gate if (c->initted == 0) {
2291*fab57d1bSGordon Ross sid = NULL;
2292*fab57d1bSGordon Ross if (gid > MAXUID &&
2293*fab57d1bSGordon Ross sid_string_by_id(gid, B_FALSE, &sid, 0) == 0) {
2294*fab57d1bSGordon Ross SCPYN(&c->name[0], sid);
2295*fab57d1bSGordon Ross free(sid);
2296*fab57d1bSGordon Ross } else if ((grent = getgrgid(gid)) != NULL) {
22977c478bd9Sstevel@tonic-gate SCPYN(&c->name[0], grent->gr_name);
22987c478bd9Sstevel@tonic-gate } else {
22997c478bd9Sstevel@tonic-gate (void) sprintf(&c->name[0], "%-8u", (int)gid);
23007c478bd9Sstevel@tonic-gate }
23017c478bd9Sstevel@tonic-gate c->initted = 1;
23027c478bd9Sstevel@tonic-gate }
23037c478bd9Sstevel@tonic-gate lastgid = gid;
23047c478bd9Sstevel@tonic-gate lastgname = &c->name[0];
23057c478bd9Sstevel@tonic-gate return (lastgname);
23067c478bd9Sstevel@tonic-gate }
23077c478bd9Sstevel@tonic-gate
2308*fab57d1bSGordon Ross /*
2309*fab57d1bSGordon Ross * get SID from cache, or from idmap for a given (ephemeral) uid;
2310*fab57d1bSGordon Ross *
2311*fab57d1bSGordon Ross * Always an ephemeral UID (> MAXUID) here.
2312*fab57d1bSGordon Ross * Just convert to a SID (no winname lookup)
2313*fab57d1bSGordon Ross */
2314*fab57d1bSGordon Ross static char *
getusid(uid_t uid)2315*fab57d1bSGordon Ross getusid(uid_t uid)
2316*fab57d1bSGordon Ross {
2317*fab57d1bSGordon Ross struct cachenode *c;
2318*fab57d1bSGordon Ross char *sid;
2319*fab57d1bSGordon Ross
2320*fab57d1bSGordon Ross c = findincache(&user_sids, uid);
2321*fab57d1bSGordon Ross if (c->initted == 0) {
2322*fab57d1bSGordon Ross sid = NULL;
2323*fab57d1bSGordon Ross if (sid_string_by_id(uid, B_TRUE, &sid, ACL_NORESOLVE) == 0) {
2324*fab57d1bSGordon Ross SCPYN(&c->name[0], sid);
2325*fab57d1bSGordon Ross free(sid);
2326*fab57d1bSGordon Ross } else {
2327*fab57d1bSGordon Ross (void) sprintf(&c->name[0], "%-8u", (int)uid);
2328*fab57d1bSGordon Ross }
2329*fab57d1bSGordon Ross c->initted = 1;
2330*fab57d1bSGordon Ross }
2331*fab57d1bSGordon Ross
2332*fab57d1bSGordon Ross return (&c->name[0]);
2333*fab57d1bSGordon Ross }
2334*fab57d1bSGordon Ross
2335*fab57d1bSGordon Ross /*
2336*fab57d1bSGordon Ross * get SID from cache, or from idmap for a given (ephemeral) gid;
2337*fab57d1bSGordon Ross *
2338*fab57d1bSGordon Ross * If an ephemeral UID (> MAXUID) try to convert to a SID
2339*fab57d1bSGordon Ross * (no winname lookup here)
2340*fab57d1bSGordon Ross */
2341*fab57d1bSGordon Ross static char *
getgsid(gid_t gid)2342*fab57d1bSGordon Ross getgsid(gid_t gid)
2343*fab57d1bSGordon Ross {
2344*fab57d1bSGordon Ross struct cachenode *c;
2345*fab57d1bSGordon Ross char *sid;
2346*fab57d1bSGordon Ross
2347*fab57d1bSGordon Ross c = findincache(&group_sids, gid);
2348*fab57d1bSGordon Ross if (c->initted == 0) {
2349*fab57d1bSGordon Ross sid = NULL;
2350*fab57d1bSGordon Ross if (sid_string_by_id(gid, B_FALSE, &sid, ACL_NORESOLVE) == 0) {
2351*fab57d1bSGordon Ross SCPYN(&c->name[0], sid);
2352*fab57d1bSGordon Ross free(sid);
2353*fab57d1bSGordon Ross } else {
2354*fab57d1bSGordon Ross (void) sprintf(&c->name[0], "%-8u", (int)gid);
2355*fab57d1bSGordon Ross }
2356*fab57d1bSGordon Ross c->initted = 1;
2357*fab57d1bSGordon Ross }
2358*fab57d1bSGordon Ross
2359*fab57d1bSGordon Ross return (&c->name[0]);
2360*fab57d1bSGordon Ross }
2361*fab57d1bSGordon Ross
23627c478bd9Sstevel@tonic-gate /* return >0 if item pointed by pp2 should appear first */
23637c478bd9Sstevel@tonic-gate static int
compar(struct lbuf ** pp1,struct lbuf ** pp2)23647c478bd9Sstevel@tonic-gate compar(struct lbuf **pp1, struct lbuf **pp2)
23657c478bd9Sstevel@tonic-gate {
23667c478bd9Sstevel@tonic-gate struct lbuf *p1, *p2;
23677c478bd9Sstevel@tonic-gate
23687c478bd9Sstevel@tonic-gate p1 = *pp1;
23697c478bd9Sstevel@tonic-gate p2 = *pp2;
23707c478bd9Sstevel@tonic-gate if (dflg == 0) {
23717c478bd9Sstevel@tonic-gate /*
23727c478bd9Sstevel@tonic-gate * compare two names in ls-command one of which is file
23737c478bd9Sstevel@tonic-gate * and the other is a directory;
23747c478bd9Sstevel@tonic-gate * this portion is not used for comparing files within
23757c478bd9Sstevel@tonic-gate * a directory name of ls-command;
23767c478bd9Sstevel@tonic-gate */
23777c478bd9Sstevel@tonic-gate if (p1->lflags&ISARG && p1->ltype == 'd') {
23787c478bd9Sstevel@tonic-gate if (!(p2->lflags&ISARG && p2->ltype == 'd'))
23797c478bd9Sstevel@tonic-gate return (1);
23807c478bd9Sstevel@tonic-gate } else {
23817c478bd9Sstevel@tonic-gate if (p2->lflags&ISARG && p2->ltype == 'd')
23827c478bd9Sstevel@tonic-gate return (-1);
23837c478bd9Sstevel@tonic-gate }
23847c478bd9Sstevel@tonic-gate }
23857c478bd9Sstevel@tonic-gate if (tflg) {
23867c478bd9Sstevel@tonic-gate if (p2->lmtime.tv_sec > p1->lmtime.tv_sec)
23877c478bd9Sstevel@tonic-gate return (rflg);
23887c478bd9Sstevel@tonic-gate else if (p2->lmtime.tv_sec < p1->lmtime.tv_sec)
23897c478bd9Sstevel@tonic-gate return (-rflg);
23907c478bd9Sstevel@tonic-gate /* times are equal to the sec, check nsec */
23917c478bd9Sstevel@tonic-gate if (p2->lmtime.tv_nsec > p1->lmtime.tv_nsec)
23927c478bd9Sstevel@tonic-gate return (rflg);
23937c478bd9Sstevel@tonic-gate else if (p2->lmtime.tv_nsec < p1->lmtime.tv_nsec)
23947c478bd9Sstevel@tonic-gate return (-rflg);
23957c478bd9Sstevel@tonic-gate /* if times are equal, fall through and sort by name */
23967c478bd9Sstevel@tonic-gate } else if (Sflg) {
23977c478bd9Sstevel@tonic-gate /*
23987c478bd9Sstevel@tonic-gate * The size stored in lsize can be either the
23997c478bd9Sstevel@tonic-gate * size or the major minor number (in the case of
24007c478bd9Sstevel@tonic-gate * block and character special devices). If it's
24017c478bd9Sstevel@tonic-gate * a major minor number, then the size is considered
24027c478bd9Sstevel@tonic-gate * to be zero and we want to fall through and sort
24037c478bd9Sstevel@tonic-gate * by name. In addition, if the size of p2 is equal
24047c478bd9Sstevel@tonic-gate * to the size of p1 we want to fall through and
24057c478bd9Sstevel@tonic-gate * sort by name.
24067c478bd9Sstevel@tonic-gate */
24077c478bd9Sstevel@tonic-gate off_t p1size = (p1->ltype == 'b') ||
2408da6c28aaSamw (p1->ltype == 'c') ? 0 : p1->lsize;
24097c478bd9Sstevel@tonic-gate off_t p2size = (p2->ltype == 'b') ||
2410da6c28aaSamw (p2->ltype == 'c') ? 0 : p2->lsize;
24117c478bd9Sstevel@tonic-gate if (p2size > p1size) {
24127c478bd9Sstevel@tonic-gate return (rflg);
24137c478bd9Sstevel@tonic-gate } else if (p2size < p1size) {
24147c478bd9Sstevel@tonic-gate return (-rflg);
24157c478bd9Sstevel@tonic-gate }
24167c478bd9Sstevel@tonic-gate /* Sizes are equal, fall through and sort by name. */
24177c478bd9Sstevel@tonic-gate }
24187c478bd9Sstevel@tonic-gate return (rflg * strcoll(
24197c478bd9Sstevel@tonic-gate p1->lflags & ISARG ? p1->ln.namep : p1->ln.lname,
24207c478bd9Sstevel@tonic-gate p2->lflags&ISARG ? p2->ln.namep : p2->ln.lname));
24217c478bd9Sstevel@tonic-gate }
24227c478bd9Sstevel@tonic-gate
24237c478bd9Sstevel@tonic-gate static void
pprintf(char * s1,char * s2)24247c478bd9Sstevel@tonic-gate pprintf(char *s1, char *s2)
24257c478bd9Sstevel@tonic-gate {
24267c478bd9Sstevel@tonic-gate csi_pprintf((unsigned char *)s1);
24277c478bd9Sstevel@tonic-gate csi_pprintf((unsigned char *)s2);
24287c478bd9Sstevel@tonic-gate }
24297c478bd9Sstevel@tonic-gate
24307c478bd9Sstevel@tonic-gate static void
csi_pprintf(unsigned char * s)24317c478bd9Sstevel@tonic-gate csi_pprintf(unsigned char *s)
24327c478bd9Sstevel@tonic-gate {
24337c478bd9Sstevel@tonic-gate unsigned char *cp;
24347c478bd9Sstevel@tonic-gate char c;
24357c478bd9Sstevel@tonic-gate int i;
24367c478bd9Sstevel@tonic-gate int c_len;
24377c478bd9Sstevel@tonic-gate int p_col;
24387c478bd9Sstevel@tonic-gate wchar_t pcode;
24397c478bd9Sstevel@tonic-gate
24407c478bd9Sstevel@tonic-gate if (!qflg && !bflg) {
24417c478bd9Sstevel@tonic-gate for (cp = s; *cp != '\0'; cp++) {
24427c478bd9Sstevel@tonic-gate (void) putchar(*cp);
24437c478bd9Sstevel@tonic-gate curcol++;
24447c478bd9Sstevel@tonic-gate }
24457c478bd9Sstevel@tonic-gate return;
24467c478bd9Sstevel@tonic-gate }
24477c478bd9Sstevel@tonic-gate
24487c478bd9Sstevel@tonic-gate for (cp = s; *cp; ) {
24497c478bd9Sstevel@tonic-gate if (isascii(c = *cp)) {
24507c478bd9Sstevel@tonic-gate if (!isprint(c)) {
24517c478bd9Sstevel@tonic-gate if (qflg) {
24527c478bd9Sstevel@tonic-gate c = '?';
24537c478bd9Sstevel@tonic-gate } else {
24547c478bd9Sstevel@tonic-gate curcol += 3;
24557c478bd9Sstevel@tonic-gate (void) putc('\\', stdout);
24567c478bd9Sstevel@tonic-gate c = '0' + ((*cp >> 6) & 07);
24577c478bd9Sstevel@tonic-gate (void) putc(c, stdout);
24587c478bd9Sstevel@tonic-gate c = '0' + ((*cp >> 3) & 07);
24597c478bd9Sstevel@tonic-gate (void) putc(c, stdout);
24607c478bd9Sstevel@tonic-gate c = '0' + (*cp & 07);
24617c478bd9Sstevel@tonic-gate }
24627c478bd9Sstevel@tonic-gate }
24637c478bd9Sstevel@tonic-gate curcol++;
24647c478bd9Sstevel@tonic-gate cp++;
24657c478bd9Sstevel@tonic-gate (void) putc(c, stdout);
24667c478bd9Sstevel@tonic-gate continue;
24677c478bd9Sstevel@tonic-gate }
24687c478bd9Sstevel@tonic-gate
24697c478bd9Sstevel@tonic-gate if ((c_len = mbtowc(&pcode, (char *)cp, MB_LEN_MAX)) <= 0) {
24707c478bd9Sstevel@tonic-gate c_len = 1;
24717c478bd9Sstevel@tonic-gate goto not_print;
24727c478bd9Sstevel@tonic-gate }
24737c478bd9Sstevel@tonic-gate
24747c478bd9Sstevel@tonic-gate if ((p_col = wcwidth(pcode)) > 0) {
24757c478bd9Sstevel@tonic-gate (void) putwchar(pcode);
24767c478bd9Sstevel@tonic-gate cp += c_len;
24777c478bd9Sstevel@tonic-gate curcol += p_col;
24787c478bd9Sstevel@tonic-gate continue;
24797c478bd9Sstevel@tonic-gate }
24807c478bd9Sstevel@tonic-gate
24817c478bd9Sstevel@tonic-gate not_print:
24827c478bd9Sstevel@tonic-gate for (i = 0; i < c_len; i++) {
24837c478bd9Sstevel@tonic-gate if (qflg) {
24847c478bd9Sstevel@tonic-gate c = '?';
24857c478bd9Sstevel@tonic-gate } else {
24867c478bd9Sstevel@tonic-gate curcol += 3;
24877c478bd9Sstevel@tonic-gate (void) putc('\\', stdout);
24887c478bd9Sstevel@tonic-gate c = '0' + ((*cp >> 6) & 07);
24897c478bd9Sstevel@tonic-gate (void) putc(c, stdout);
24907c478bd9Sstevel@tonic-gate c = '0' + ((*cp >> 3) & 07);
24917c478bd9Sstevel@tonic-gate (void) putc(c, stdout);
24927c478bd9Sstevel@tonic-gate c = '0' + (*cp & 07);
24937c478bd9Sstevel@tonic-gate }
24947c478bd9Sstevel@tonic-gate curcol++;
24957c478bd9Sstevel@tonic-gate (void) putc(c, stdout);
24967c478bd9Sstevel@tonic-gate cp++;
24977c478bd9Sstevel@tonic-gate }
24987c478bd9Sstevel@tonic-gate }
24997c478bd9Sstevel@tonic-gate }
25007c478bd9Sstevel@tonic-gate
25017c478bd9Sstevel@tonic-gate static int
strcol(unsigned char * s1)25027c478bd9Sstevel@tonic-gate strcol(unsigned char *s1)
25037c478bd9Sstevel@tonic-gate {
25047c478bd9Sstevel@tonic-gate int w;
25057c478bd9Sstevel@tonic-gate int w_col;
25067c478bd9Sstevel@tonic-gate int len;
25077c478bd9Sstevel@tonic-gate wchar_t wc;
25087c478bd9Sstevel@tonic-gate
25097c478bd9Sstevel@tonic-gate w = 0;
25107c478bd9Sstevel@tonic-gate while (*s1) {
25117c478bd9Sstevel@tonic-gate if (isascii(*s1)) {
25127c478bd9Sstevel@tonic-gate w++;
25137c478bd9Sstevel@tonic-gate s1++;
25147c478bd9Sstevel@tonic-gate continue;
25157c478bd9Sstevel@tonic-gate }
25167c478bd9Sstevel@tonic-gate
25177c478bd9Sstevel@tonic-gate if ((len = mbtowc(&wc, (char *)s1, MB_LEN_MAX)) <= 0) {
25187c478bd9Sstevel@tonic-gate w++;
25197c478bd9Sstevel@tonic-gate s1++;
25207c478bd9Sstevel@tonic-gate continue;
25217c478bd9Sstevel@tonic-gate }
25227c478bd9Sstevel@tonic-gate
25237c478bd9Sstevel@tonic-gate if ((w_col = wcwidth(wc)) < 0)
25247c478bd9Sstevel@tonic-gate w_col = len;
25257c478bd9Sstevel@tonic-gate s1 += len;
25267c478bd9Sstevel@tonic-gate w += w_col;
25277c478bd9Sstevel@tonic-gate }
25287c478bd9Sstevel@tonic-gate return (w);
25297c478bd9Sstevel@tonic-gate }
25307c478bd9Sstevel@tonic-gate
2531da6c28aaSamw /* Get extended system attributes and set the display */
2532da6c28aaSamw
2533da6c28aaSamw int
get_sysxattr(char * fname,struct lbuf * rep)2534da6c28aaSamw get_sysxattr(char *fname, struct lbuf *rep)
2535da6c28aaSamw {
2536da6c28aaSamw boolean_t value;
2537da6c28aaSamw data_type_t type;
2538da6c28aaSamw int error;
2539da6c28aaSamw char *name;
2540da6c28aaSamw int i;
2541da6c28aaSamw
2542da6c28aaSamw if ((error = getattrat(AT_FDCWD, XATTR_VIEW_READWRITE, fname,
2543da6c28aaSamw &response)) != 0) {
2544da6c28aaSamw perror("ls:getattrat");
2545da6c28aaSamw return (error);
2546da6c28aaSamw }
2547da6c28aaSamw
2548da6c28aaSamw /*
2549da6c28aaSamw * Allocate 'sacnt' size array to hold extended timestamp
2550da6c28aaSamw * system attributes and initialize the array.
2551da6c28aaSamw */
2552da6c28aaSamw rep->extm = xmalloc(sacnt * sizeof (struct attrtm), rep);
2553da6c28aaSamw for (i = 0; i < sacnt; i++) {
2554da6c28aaSamw rep->extm[i].stm = 0;
2555da6c28aaSamw rep->extm[i].nstm = 0;
2556da6c28aaSamw rep->extm[i].name = NULL;
2557da6c28aaSamw }
2558da6c28aaSamw while ((pair = nvlist_next_nvpair(response, pair)) != NULL) {
2559da6c28aaSamw name = nvpair_name(pair);
2560da6c28aaSamw type = nvpair_type(pair);
2561da6c28aaSamw if (type == DATA_TYPE_BOOLEAN_VALUE) {
2562da6c28aaSamw error = nvpair_value_boolean_value(pair, &value);
2563da6c28aaSamw if (error) {
2564da6c28aaSamw (void) fprintf(stderr,
2565da6c28aaSamw gettext("nvpair_value_boolean_value "
2566da6c28aaSamw "failed: error = %d\n"), error);
2567da6c28aaSamw continue;
2568da6c28aaSamw }
2569da6c28aaSamw if (name != NULL)
2570da6c28aaSamw set_sysattrb_display(name, value, rep);
2571da6c28aaSamw continue;
2572da6c28aaSamw } else if (type == DATA_TYPE_UINT64_ARRAY) {
2573da6c28aaSamw if (name != NULL)
2574da6c28aaSamw set_sysattrtm_display(name, rep);
2575da6c28aaSamw continue;
2576da6c28aaSamw }
2577da6c28aaSamw }
2578da6c28aaSamw nvlist_free(response);
2579da6c28aaSamw return (0);
2580da6c28aaSamw }
2581da6c28aaSamw
2582da6c28aaSamw /* Set extended system attribute boolean display */
2583da6c28aaSamw
2584da6c28aaSamw void
set_sysattrb_display(char * name,boolean_t val,struct lbuf * rep)2585da6c28aaSamw set_sysattrb_display(char *name, boolean_t val, struct lbuf *rep)
2586da6c28aaSamw {
2587da6c28aaSamw f_attr_t fattr;
2588da6c28aaSamw const char *opt;
2589da6c28aaSamw size_t len;
2590da6c28aaSamw
2591da6c28aaSamw fattr = name_to_attr(name);
2592da6c28aaSamw if (fattr != F_ATTR_INVAL && fattr < sacnt) {
2593da6c28aaSamw if (vopt) {
2594da6c28aaSamw len = strlen(name);
2595da6c28aaSamw if (val) {
2596da6c28aaSamw rep->exttr[fattr].name = xmalloc(len + 1, rep);
2597da6c28aaSamw (void) strlcpy(rep->exttr[fattr].name, name,
2598da6c28aaSamw len + 1);
2599da6c28aaSamw } else {
2600da6c28aaSamw rep->exttr[fattr].name = xmalloc(len + 3, rep);
2601da6c28aaSamw (void) snprintf(rep->exttr[fattr].name, len + 3,
2602da6c28aaSamw "no%s", name);
2603da6c28aaSamw }
2604da6c28aaSamw } else {
2605da6c28aaSamw opt = attr_to_option(fattr);
2606da6c28aaSamw if (opt != NULL) {
2607da6c28aaSamw len = strlen(opt);
2608da6c28aaSamw rep->exttr[fattr].name = xmalloc(len + 1, rep);
2609da6c28aaSamw if (val)
2610da6c28aaSamw (void) strlcpy(rep->exttr[fattr].name,
2611da6c28aaSamw opt, len + 1);
2612da6c28aaSamw else
2613da6c28aaSamw (void) strlcpy(rep->exttr[fattr].name,
2614da6c28aaSamw "-", len + 1);
2615da6c28aaSamw }
2616da6c28aaSamw }
2617da6c28aaSamw }
2618da6c28aaSamw }
2619da6c28aaSamw
2620da6c28aaSamw /* Set extended system attribute timestamp display */
2621da6c28aaSamw
2622da6c28aaSamw void
set_sysattrtm_display(char * name,struct lbuf * rep)2623da6c28aaSamw set_sysattrtm_display(char *name, struct lbuf *rep)
2624da6c28aaSamw {
2625da6c28aaSamw uint_t nelem;
2626da6c28aaSamw uint64_t *value;
2627da6c28aaSamw int i;
2628da6c28aaSamw size_t len;
2629da6c28aaSamw
2630da6c28aaSamw if (nvpair_value_uint64_array(pair, &value, &nelem) == 0) {
26311418cdc0SToomas Soome if (value != NULL) {
2632da6c28aaSamw len = strlen(name);
2633da6c28aaSamw i = 0;
2634da6c28aaSamw while (rep->extm[i].stm != 0 && i < sacnt)
2635da6c28aaSamw i++;
2636da6c28aaSamw rep->extm[i].stm = value[0];
2637da6c28aaSamw rep->extm[i].nstm = value[1];
2638da6c28aaSamw rep->extm[i].name = xmalloc(len + 1, rep);
2639da6c28aaSamw (void) strlcpy(rep->extm[i].name, name, len + 1);
2640da6c28aaSamw }
2641da6c28aaSamw }
2642da6c28aaSamw }
2643da6c28aaSamw
2644da6c28aaSamw void
format_time(time_t sec,time_t nsec)26455e1c72e1SJason King format_time(time_t sec, time_t nsec)
2646da6c28aaSamw {
26475e1c72e1SJason King const char *fstr = time_fmt_new;
26485e1c72e1SJason King char fmt_buf[FMTSIZE];
2649da6c28aaSamw
26505e1c72e1SJason King if (Eflg) {
26515e1c72e1SJason King (void) snprintf(fmt_buf, FMTSIZE, fstr, nsec);
26525e1c72e1SJason King (void) strftime(time_buf, sizeof (time_buf), fmt_buf,
26535e1c72e1SJason King localtime(&sec));
26545e1c72e1SJason King return;
26555e1c72e1SJason King }
2656da6c28aaSamw
26575e1c72e1SJason King if (sec < year || sec > now)
26585e1c72e1SJason King fstr = time_fmt_old;
2659da6c28aaSamw
26605e1c72e1SJason King /* if a custom time was specified, shouldn't be localized */
2661da6c28aaSamw (void) strftime(time_buf, sizeof (time_buf),
26625e1c72e1SJason King (time_custom == 0) ? dcgettext(NULL, fstr, LC_TIME) : fstr,
26635e1c72e1SJason King localtime(&sec));
2664da6c28aaSamw }
2665da6c28aaSamw
2666da6c28aaSamw void
format_attrtime(struct lbuf * p)2667da6c28aaSamw format_attrtime(struct lbuf *p)
2668da6c28aaSamw {
26695e1c72e1SJason King int tmattr = 0;
2670da6c28aaSamw int i;
2671da6c28aaSamw
2672da6c28aaSamw if (p->extm != NULL) {
2673da6c28aaSamw for (i = 0; i < sacnt; i++) {
2674da6c28aaSamw if (p->extm[i].name != NULL) {
2675da6c28aaSamw tmattr = 1;
2676da6c28aaSamw break;
2677da6c28aaSamw }
2678da6c28aaSamw }
2679da6c28aaSamw }
26805e1c72e1SJason King
2681da6c28aaSamw if (tmattr) {
26825e1c72e1SJason King const char *old_save = time_fmt_old;
26835e1c72e1SJason King const char *new_save = time_fmt_new;
26845e1c72e1SJason King
26855e1c72e1SJason King /* Eflg always sets format to FORMAT_ISO_FULL */
26865e1c72e1SJason King if (!Eflg && !time_custom) {
26875e1c72e1SJason King time_fmt_old = FORMAT_OLD;
26885e1c72e1SJason King time_fmt_new = FORMAT_NEW;
2689da6c28aaSamw }
26905e1c72e1SJason King
26915e1c72e1SJason King format_time((time_t)p->extm[i].stm, (time_t)p->extm[i].nstm);
26925e1c72e1SJason King
26935e1c72e1SJason King time_fmt_old = old_save;
26945e1c72e1SJason King time_fmt_new = new_save;
2695da6c28aaSamw }
2696da6c28aaSamw }
2697da6c28aaSamw
2698da6c28aaSamw void
print_time(struct lbuf * p)2699da6c28aaSamw print_time(struct lbuf *p)
2700da6c28aaSamw {
27015e1c72e1SJason King const char *old_save = time_fmt_old;
27025e1c72e1SJason King const char *new_save = time_fmt_new;
27035e1c72e1SJason King
2704da6c28aaSamw int i = 0;
2705da6c28aaSamw
27065e1c72e1SJason King if (!Eflg) {
27075e1c72e1SJason King time_fmt_old = FORMAT_LONG;
27085e1c72e1SJason King time_fmt_new = FORMAT_LONG;
27095e1c72e1SJason King }
27105e1c72e1SJason King
2711da6c28aaSamw new_line();
27125e1c72e1SJason King format_time(p->lat.tv_sec, p->lat.tv_nsec);
27135e1c72e1SJason King (void) printf(" timestamp: atime %s\n", time_buf);
27145e1c72e1SJason King format_time(p->lct.tv_sec, p->lct.tv_nsec);
27155e1c72e1SJason King (void) printf(" timestamp: ctime %s\n", time_buf);
27165e1c72e1SJason King format_time(p->lmt.tv_sec, p->lmt.tv_nsec);
27175e1c72e1SJason King (void) printf(" timestamp: mtime %s\n", time_buf);
27185e1c72e1SJason King if (p->extm != NULL) {
27195e1c72e1SJason King while (p->extm[i].nstm != 0 && i < sacnt) {
27205e1c72e1SJason King format_time(p->extm[i].stm, p->extm[i].nstm);
27215e1c72e1SJason King if (p->extm[i].name != NULL) {
27225e1c72e1SJason King (void) printf(" timestamp:"
27235e1c72e1SJason King " %s %s\n",
27245e1c72e1SJason King p->extm[i].name, time_buf);
2725da6c28aaSamw }
27265e1c72e1SJason King i++;
27275e1c72e1SJason King }
27285e1c72e1SJason King }
27295e1c72e1SJason King
27305e1c72e1SJason King time_fmt_old = old_save;
27315e1c72e1SJason King time_fmt_new = new_save;
27325e1c72e1SJason King }
27335e1c72e1SJason King
27345e1c72e1SJason King /*
27355e1c72e1SJason King * Check if color definition applies to entry, returns 1 if yes, 0 if no
27365e1c72e1SJason King */
27375e1c72e1SJason King static int
color_match(const char * fname,mode_t mode,ls_color_t * color)27381b628248SJason King color_match(const char *fname, mode_t mode, ls_color_t *color)
27395e1c72e1SJason King {
27405e1c72e1SJason King switch (color->ftype) {
27415e1c72e1SJason King case LS_PAT:
27425e1c72e1SJason King {
27435e1c72e1SJason King size_t fname_len, sfx_len;
27445e1c72e1SJason King
27455e1c72e1SJason King fname_len = strlen(fname);
27465e1c72e1SJason King sfx_len = strlen(color->sfx);
27475e1c72e1SJason King if (sfx_len > fname_len)
27485e1c72e1SJason King return (0);
27495e1c72e1SJason King
27505e1c72e1SJason King if (strcmp(color->sfx, fname + fname_len - sfx_len) == 0)
27515e1c72e1SJason King return (1);
27525e1c72e1SJason King else
27535e1c72e1SJason King return (0);
27545e1c72e1SJason King }
27555e1c72e1SJason King
27565e1c72e1SJason King case LS_NORMAL:
27575e1c72e1SJason King return (1);
27585e1c72e1SJason King
27595e1c72e1SJason King case LS_FILE:
27601b628248SJason King return (S_ISREG(mode));
27615e1c72e1SJason King
27625e1c72e1SJason King case LS_DIR:
27631b628248SJason King return (S_ISDIR(mode));
27645e1c72e1SJason King
27655e1c72e1SJason King case LS_LINK:
27661b628248SJason King return (S_ISLNK(mode));
27675e1c72e1SJason King
27685e1c72e1SJason King case LS_FIFO:
27691b628248SJason King return (S_ISFIFO(mode));
27705e1c72e1SJason King
27715e1c72e1SJason King case LS_SOCK:
27721b628248SJason King return (S_ISSOCK(mode));
27735e1c72e1SJason King
27745e1c72e1SJason King case LS_DOOR:
27751b628248SJason King return (S_ISDOOR(mode));
27765e1c72e1SJason King
27775e1c72e1SJason King case LS_BLK:
27781b628248SJason King return (S_ISBLK(mode));
27795e1c72e1SJason King
27805e1c72e1SJason King case LS_CHR:
27811b628248SJason King return (S_ISCHR(mode));
27825e1c72e1SJason King
27835e1c72e1SJason King case LS_PORT:
27841b628248SJason King return (S_ISPORT(mode));
27855e1c72e1SJason King
27865e1c72e1SJason King case LS_ORPHAN:
27871b628248SJason King /* this is tested for by gstat */
27885e1c72e1SJason King return (0);
27895e1c72e1SJason King
27905e1c72e1SJason King case LS_SETUID:
27911b628248SJason King return (!S_ISLNK(mode) && (mode & S_ISUID));
27925e1c72e1SJason King
27935e1c72e1SJason King case LS_SETGID:
27941b628248SJason King return (!S_ISLNK(mode) && (mode & S_ISGID));
27955e1c72e1SJason King
27965e1c72e1SJason King case LS_STICKY_OTHER_WRITABLE:
27971b628248SJason King return (!S_ISLNK(mode) && (mode & (S_IWOTH|S_ISVTX)));
27985e1c72e1SJason King
27995e1c72e1SJason King case LS_OTHER_WRITABLE:
28001b628248SJason King return (!S_ISLNK(mode) && (mode & S_IWOTH));
28015e1c72e1SJason King
28025e1c72e1SJason King case LS_STICKY:
28031b628248SJason King return (!S_ISLNK(mode) && (mode & S_ISVTX));
28045e1c72e1SJason King
28055e1c72e1SJason King case LS_EXEC:
28061b628248SJason King return (!S_ISLNK(mode) && (mode & (S_IXUSR|S_IXGRP|S_IXOTH)));
28075e1c72e1SJason King }
28085e1c72e1SJason King
28095e1c72e1SJason King return (0);
28105e1c72e1SJason King }
28115e1c72e1SJason King
28125e1c72e1SJason King static void
dump_color(ls_color_t * c)28135e1c72e1SJason King dump_color(ls_color_t *c)
28145e1c72e1SJason King {
28155e1c72e1SJason King if (c == NULL)
28165e1c72e1SJason King return;
28175e1c72e1SJason King
28185e1c72e1SJason King (void) printf("\n\ttype: ");
28195e1c72e1SJason King switch (c->ftype) {
28205e1c72e1SJason King case LS_NORMAL:
28215e1c72e1SJason King (void) printf("LS_NORMAL");
28225e1c72e1SJason King break;
28235e1c72e1SJason King case LS_FILE:
28245e1c72e1SJason King (void) printf("LS_FILE");
28255e1c72e1SJason King break;
28265e1c72e1SJason King case LS_EXEC:
28275e1c72e1SJason King (void) printf("LS_EXEC");
28285e1c72e1SJason King break;
28295e1c72e1SJason King case LS_DIR:
28305e1c72e1SJason King (void) printf("LS_DIR");
28315e1c72e1SJason King break;
28325e1c72e1SJason King case LS_LINK:
28335e1c72e1SJason King (void) printf("LS_LINK");
28345e1c72e1SJason King break;
28355e1c72e1SJason King
28365e1c72e1SJason King case LS_FIFO:
28375e1c72e1SJason King (void) printf("LS_FIFO");
28385e1c72e1SJason King break;
28395e1c72e1SJason King
28405e1c72e1SJason King case LS_SOCK:
28415e1c72e1SJason King (void) printf("LS_SOCK");
28425e1c72e1SJason King break;
28435e1c72e1SJason King
28445e1c72e1SJason King case LS_DOOR:
28455e1c72e1SJason King (void) printf("LS_DOOR");
28465e1c72e1SJason King break;
28475e1c72e1SJason King
28485e1c72e1SJason King case LS_BLK:
28495e1c72e1SJason King (void) printf("LS_BLK");
28505e1c72e1SJason King break;
28515e1c72e1SJason King
28525e1c72e1SJason King case LS_CHR:
28535e1c72e1SJason King (void) printf("LS_CHR");
28545e1c72e1SJason King break;
28555e1c72e1SJason King
28565e1c72e1SJason King case LS_PORT:
28575e1c72e1SJason King (void) printf("LS_PORT");
28585e1c72e1SJason King break;
28595e1c72e1SJason King
28605e1c72e1SJason King case LS_STICKY:
28615e1c72e1SJason King (void) printf("LS_STICKY");
28625e1c72e1SJason King break;
28635e1c72e1SJason King
28645e1c72e1SJason King case LS_ORPHAN:
28655e1c72e1SJason King (void) printf("LS_ORPHAN");
28665e1c72e1SJason King break;
28675e1c72e1SJason King
28685e1c72e1SJason King case LS_SETGID:
28695e1c72e1SJason King (void) printf("LS_SETGID");
28705e1c72e1SJason King break;
28715e1c72e1SJason King
28725e1c72e1SJason King case LS_SETUID:
28735e1c72e1SJason King (void) printf("LS_SETUID");
28745e1c72e1SJason King break;
28755e1c72e1SJason King
28765e1c72e1SJason King case LS_OTHER_WRITABLE:
28775e1c72e1SJason King (void) printf("LS_OTHER_WRITABLE");
28785e1c72e1SJason King break;
28795e1c72e1SJason King
28805e1c72e1SJason King case LS_STICKY_OTHER_WRITABLE:
28815e1c72e1SJason King (void) printf("LS_STICKY_OTHER_WRITABLE");
28825e1c72e1SJason King break;
28835e1c72e1SJason King
28845e1c72e1SJason King case LS_PAT:
28855e1c72e1SJason King (void) printf("LS_PAT\n");
28865e1c72e1SJason King (void) printf("\tpattern: %s", c->sfx);
28875e1c72e1SJason King break;
28885e1c72e1SJason King }
28895e1c72e1SJason King (void) printf("\n");
28905e1c72e1SJason King (void) printf("\tattr: %d\n", c->attr);
28915e1c72e1SJason King (void) printf("\tfg: %d\n", c->fg);
28925e1c72e1SJason King (void) printf("\tbg: %d\n", c->bg);
28935e1c72e1SJason King (void) printf("\t");
28945e1c72e1SJason King }
28955e1c72e1SJason King
28965e1c72e1SJason King static ls_color_t *
ls_color_find(const char * fname,mode_t mode)28971b628248SJason King ls_color_find(const char *fname, mode_t mode)
28985e1c72e1SJason King {
28995e1c72e1SJason King int i;
29005e1c72e1SJason King
29015e1c72e1SJason King /*
29025e1c72e1SJason King * Colors are sorted from most general lsc_colors[0] to most specific
29035e1c72e1SJason King * lsc_colors[lsc_ncolors - 1] by ls_color_init(). Start search with
29045e1c72e1SJason King * most specific color rule and work towards most general.
29055e1c72e1SJason King */
29065e1c72e1SJason King for (i = lsc_ncolors - 1; i >= 0; --i)
29071b628248SJason King if (color_match(fname, mode, &lsc_colors[i]))
29085e1c72e1SJason King return (&lsc_colors[i]);
29095e1c72e1SJason King
29105e1c72e1SJason King return (NULL);
29115e1c72e1SJason King }
29125e1c72e1SJason King
29135e1c72e1SJason King static void
ls_tprint(char * str,long int p1,long int p2,long int p3,long int p4,long int p5,long int p6,long int p7,long int p8,long int p9)29145e1c72e1SJason King ls_tprint(char *str, long int p1, long int p2, long int p3, long int p4,
29155e1c72e1SJason King long int p5, long int p6, long int p7, long int p8, long int p9)
29165e1c72e1SJason King {
29175e1c72e1SJason King char *s;
29185e1c72e1SJason King
29195e1c72e1SJason King if (str == NULL)
29205e1c72e1SJason King return;
29215e1c72e1SJason King
29225e1c72e1SJason King s = tparm(str, p1, p2, p3, p4, p5, p6, p7, p8, p9);
29235e1c72e1SJason King
29245e1c72e1SJason King if (s != NULL)
29255e1c72e1SJason King (void) putp(s);
29265e1c72e1SJason King }
29275e1c72e1SJason King
29285e1c72e1SJason King static void
ls_start_color(ls_color_t * c)29291b628248SJason King ls_start_color(ls_color_t *c)
29305e1c72e1SJason King {
29315e1c72e1SJason King if (c == NULL)
29325e1c72e1SJason King return;
29335e1c72e1SJason King
29345e1c72e1SJason King if (lsc_debug)
29355e1c72e1SJason King lsc_match = c;
29365e1c72e1SJason King
29375e1c72e1SJason King if (c->attr & LSA_BOLD)
29385e1c72e1SJason King ls_tprint(lsc_bold, 0, 0, 0, 0, 0, 0, 0, 0, 0);
29395e1c72e1SJason King if (c->attr & LSA_UNDERSCORE)
29405e1c72e1SJason King ls_tprint(lsc_underline, 0, 0, 0, 0, 0, 0, 0, 0, 0);
29415e1c72e1SJason King if (c->attr & LSA_BLINK)
29425e1c72e1SJason King ls_tprint(lsc_blink, 0, 0, 0, 0, 0, 0, 0, 0, 0);
29435e1c72e1SJason King if (c->attr & LSA_REVERSE)
29445e1c72e1SJason King ls_tprint(lsc_reverse, 0, 0, 0, 0, 0, 0, 0, 0, 0);
29455e1c72e1SJason King if (c->attr & LSA_CONCEALED)
29465e1c72e1SJason King ls_tprint(lsc_concealed, 0, 0, 0, 0, 0, 0, 0, 0, 0);
29475e1c72e1SJason King if (c->attr == LSA_NONE)
29485e1c72e1SJason King ls_tprint(lsc_none, 0, 0, 0, 0, 0, 0, 0, 0, 0);
29495e1c72e1SJason King
29505e1c72e1SJason King if (c->fg != -1)
29515e1c72e1SJason King ls_tprint(lsc_setfg, c->fg, 0, 0, 0, 0, 0, 0, 0, 0);
29525e1c72e1SJason King if (c->bg != -1)
29535e1c72e1SJason King ls_tprint(lsc_setbg, c->bg, 0, 0, 0, 0, 0, 0, 0, 0);
29545e1c72e1SJason King }
29555e1c72e1SJason King
29565e1c72e1SJason King static void
ls_end_color()29575e1c72e1SJason King ls_end_color()
29585e1c72e1SJason King {
29595e1c72e1SJason King ls_tprint(lsc_none, 0, 0, 0, 0, 0, 0, 0, 0, 0);
29605e1c72e1SJason King if (lsc_debug)
29615e1c72e1SJason King dump_color(lsc_match);
29625e1c72e1SJason King }
29635e1c72e1SJason King
29645e1c72e1SJason King static void
new_color_entry(char * colorstr)29655e1c72e1SJason King new_color_entry(char *colorstr)
29665e1c72e1SJason King {
29675e1c72e1SJason King static const struct {
29685e1c72e1SJason King const char *s;
29695e1c72e1SJason King ls_cftype_t stype;
29705e1c72e1SJason King } type_map[] = {
29715e1c72e1SJason King { "no", LS_NORMAL },
29725e1c72e1SJason King { "fi", LS_FILE },
29735e1c72e1SJason King { "di", LS_DIR },
29745e1c72e1SJason King { "ln", LS_LINK },
29755e1c72e1SJason King { "pi", LS_FIFO },
29765e1c72e1SJason King { "so", LS_SOCK },
29775e1c72e1SJason King { "do", LS_DOOR },
29785e1c72e1SJason King { "bd", LS_BLK },
29795e1c72e1SJason King { "cd", LS_CHR },
29805e1c72e1SJason King { "or", LS_ORPHAN },
29815e1c72e1SJason King { "su", LS_SETUID },
29825e1c72e1SJason King { "sg", LS_SETGID },
29835e1c72e1SJason King { "tw", LS_STICKY_OTHER_WRITABLE },
29845e1c72e1SJason King { "ow", LS_OTHER_WRITABLE },
29855e1c72e1SJason King { "st", LS_STICKY },
29865e1c72e1SJason King { "ex", LS_EXEC },
29875e1c72e1SJason King { "po", LS_PORT },
29885e1c72e1SJason King { NULL, LS_NORMAL }
29895e1c72e1SJason King };
29905e1c72e1SJason King
29915e1c72e1SJason King char *p, *lasts;
29925e1c72e1SJason King int i;
29935e1c72e1SJason King int color, attr;
29945e1c72e1SJason King
29955e1c72e1SJason King p = strtok_r(colorstr, "=", &lasts);
29965e1c72e1SJason King if (p == NULL) {
29975e1c72e1SJason King colorflg = 0;
29985e1c72e1SJason King return;
29995e1c72e1SJason King }
30005e1c72e1SJason King
30015e1c72e1SJason King if (p[0] == '*') {
30025e1c72e1SJason King lsc_colors[lsc_ncolors].ftype = LS_PAT;
30035e1c72e1SJason King /* don't include the * in the suffix */
30045e1c72e1SJason King if ((lsc_colors[lsc_ncolors].sfx = strdup(p + 1)) == NULL) {
30055e1c72e1SJason King colorflg = 0;
30065e1c72e1SJason King return;
3007da6c28aaSamw }
3008da6c28aaSamw } else {
30095e1c72e1SJason King lsc_colors[lsc_ncolors].sfx = NULL;
30105e1c72e1SJason King
30115e1c72e1SJason King for (i = 0; type_map[i].s != NULL; ++i) {
30125e1c72e1SJason King if (strncmp(type_map[i].s, p, 2) == 0)
30135e1c72e1SJason King break;
30145e1c72e1SJason King }
30155e1c72e1SJason King
30165e1c72e1SJason King /* ignore unknown file types */
30175e1c72e1SJason King if (type_map[i].s == NULL)
30185e1c72e1SJason King return;
30195e1c72e1SJason King
30205e1c72e1SJason King lsc_colors[lsc_ncolors].ftype = type_map[i].stype;
30215e1c72e1SJason King }
30225e1c72e1SJason King
30235e1c72e1SJason King attr = LSA_NONE;
30245e1c72e1SJason King lsc_colors[lsc_ncolors].fg = -1;
30255e1c72e1SJason King lsc_colors[lsc_ncolors].bg = -1;
30265e1c72e1SJason King for (p = strtok_r(NULL, ";", &lasts); p != NULL;
30275e1c72e1SJason King p = strtok_r(NULL, ";", &lasts)) {
30285e1c72e1SJason King color = strtol(p, NULL, 10);
30295e1c72e1SJason King
30305e1c72e1SJason King if (color < 10) {
30315e1c72e1SJason King switch (color) {
30325e1c72e1SJason King case 0:
30335e1c72e1SJason King attr = LSA_NONE;
30345e1c72e1SJason King continue;
30355e1c72e1SJason King case 1:
30365e1c72e1SJason King attr |= LSA_BOLD;
30375e1c72e1SJason King continue;
30385e1c72e1SJason King case 4:
30395e1c72e1SJason King attr |= LSA_UNDERSCORE;
30405e1c72e1SJason King continue;
30415e1c72e1SJason King case 5:
30425e1c72e1SJason King attr |= LSA_BLINK;
30435e1c72e1SJason King continue;
30445e1c72e1SJason King case 7:
30455e1c72e1SJason King attr |= LSA_REVERSE;
30465e1c72e1SJason King continue;
30475e1c72e1SJason King case 8:
30485e1c72e1SJason King attr |= LSA_CONCEALED;
30495e1c72e1SJason King continue;
30505e1c72e1SJason King default:
30515e1c72e1SJason King continue;
3052da6c28aaSamw }
3053da6c28aaSamw }
30545e1c72e1SJason King
30555e1c72e1SJason King if (color < 40)
30565e1c72e1SJason King lsc_colors[lsc_ncolors].fg = color - 30;
30575e1c72e1SJason King else
30585e1c72e1SJason King lsc_colors[lsc_ncolors].bg = color - 40;
30595e1c72e1SJason King }
30605e1c72e1SJason King
30615e1c72e1SJason King lsc_colors[lsc_ncolors].attr = attr;
30625e1c72e1SJason King ++lsc_ncolors;
30635e1c72e1SJason King }
30645e1c72e1SJason King
30655e1c72e1SJason King static int
ls_color_compare(const void * p1,const void * p2)30665e1c72e1SJason King ls_color_compare(const void *p1, const void *p2)
30675e1c72e1SJason King {
30685e1c72e1SJason King const ls_color_t *c1 = (const ls_color_t *)p1;
30695e1c72e1SJason King const ls_color_t *c2 = (const ls_color_t *)p2;
30705e1c72e1SJason King
30715e1c72e1SJason King int ret = c1->ftype - c2->ftype;
30725e1c72e1SJason King
30735e1c72e1SJason King if (ret != 0)
30745e1c72e1SJason King return (ret);
30755e1c72e1SJason King
30765e1c72e1SJason King if (c1->ftype != LS_PAT)
30775e1c72e1SJason King return (ret);
30785e1c72e1SJason King
30795e1c72e1SJason King return (strcmp(c1->sfx, c2->sfx));
30805e1c72e1SJason King }
30815e1c72e1SJason King
30825e1c72e1SJason King static void
ls_color_init()30835e1c72e1SJason King ls_color_init()
30845e1c72e1SJason King {
30855e1c72e1SJason King static char *default_colorstr = "no=00:fi=00:di=01;34:ln=01;36:po=01;35"
30865e1c72e1SJason King ":pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01"
30875e1c72e1SJason King ":su=37;41:sg=30;43:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31"
30885e1c72e1SJason King ":*.tgz=01;31:*.arj=01;31:*.taz=01;31:*.lzh=01;31:*.zip=01;31"
30895e1c72e1SJason King ":*.z=01;31:*.Z=01;31:*.gz=01;31:*.bz2=01;31:*.deb=01;31"
30905e1c72e1SJason King ":*.rpm=01;31:*.jar=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35"
30915e1c72e1SJason King ":*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35"
30925e1c72e1SJason King ":*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35"
30935e1c72e1SJason King ":*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.avi=01;35:*.fli=01;35"
30945e1c72e1SJason King ":*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.flac=01;35"
30955e1c72e1SJason King ":*.mp3=01;35:*.mpc=01;35:*.ogg=01;35:*.wav=01;35";
30965e1c72e1SJason King
30975e1c72e1SJason King char *colorstr;
30985e1c72e1SJason King char *p, *lasts;
30995e1c72e1SJason King size_t color_sz;
31005e1c72e1SJason King int termret;
31011b628248SJason King int i;
31025e1c72e1SJason King
31035e1c72e1SJason King (void) setupterm(NULL, 1, &termret);
31045e1c72e1SJason King if (termret != 1)
31055e1c72e1SJason King return;
31065e1c72e1SJason King
310738f2a414SAlbert Lee if ((p = getenv("LS_COLORS")) == NULL)
310838f2a414SAlbert Lee p = default_colorstr;
310938f2a414SAlbert Lee colorstr = strdup(p);
311038f2a414SAlbert Lee if (colorstr == NULL)
311138f2a414SAlbert Lee return;
31125e1c72e1SJason King
3113f7387fb0SJason King /*
3114f7387fb0SJason King * Determine the size of lsc_colors. color_sz can be > lsc_ncolors
3115f7387fb0SJason King * if there are invalid entries passed in the string (they are ignored)
3116f7387fb0SJason King */
3117f7387fb0SJason King color_sz = 1;
31185e1c72e1SJason King for (p = strchr(colorstr, ':'); p != NULL && *p != '\0';
31195e1c72e1SJason King p = strchr(++p, ':'))
31205e1c72e1SJason King ++color_sz;
31215e1c72e1SJason King
31225e1c72e1SJason King lsc_colors = calloc(color_sz, sizeof (ls_color_t));
31235e1c72e1SJason King if (lsc_colors == NULL) {
31245e1c72e1SJason King free(colorstr);
31255e1c72e1SJason King return;
31265e1c72e1SJason King }
31275e1c72e1SJason King
31285e1c72e1SJason King for (p = strtok_r(colorstr, ":", &lasts);
31295e1c72e1SJason King p != NULL && lsc_ncolors < color_sz;
31305e1c72e1SJason King p = strtok_r(NULL, ":", &lasts))
31315e1c72e1SJason King new_color_entry(p);
31325e1c72e1SJason King
31335e1c72e1SJason King qsort((void *)lsc_colors, lsc_ncolors, sizeof (ls_color_t),
31345e1c72e1SJason King ls_color_compare);
31355e1c72e1SJason King
31361b628248SJason King for (i = 0; i < lsc_ncolors; ++i)
31371b628248SJason King if (lsc_colors[i].ftype == LS_ORPHAN) {
31381b628248SJason King lsc_orphan = &lsc_colors[i];
31391b628248SJason King break;
31401b628248SJason King }
31411b628248SJason King
31425e1c72e1SJason King if ((lsc_bold = tigetstr("bold")) == (char *)-1)
31435e1c72e1SJason King lsc_bold = NULL;
31445e1c72e1SJason King
31455e1c72e1SJason King if ((lsc_underline = tigetstr("smul")) == (char *)-1)
31465e1c72e1SJason King lsc_underline = NULL;
31475e1c72e1SJason King
31485e1c72e1SJason King if ((lsc_blink = tigetstr("blink")) == (char *)-1)
31495e1c72e1SJason King lsc_blink = NULL;
31505e1c72e1SJason King
31515e1c72e1SJason King if ((lsc_reverse = tigetstr("rev")) == (char *)-1)
31525e1c72e1SJason King lsc_reverse = NULL;
31535e1c72e1SJason King
31545e1c72e1SJason King if ((lsc_concealed = tigetstr("prot")) == (char *)-1)
31555e1c72e1SJason King lsc_concealed = NULL;
31565e1c72e1SJason King
31575e1c72e1SJason King if ((lsc_none = tigetstr("sgr0")) == (char *)-1)
31585e1c72e1SJason King lsc_none = NULL;
31595e1c72e1SJason King
31605e1c72e1SJason King if ((lsc_setfg = tigetstr("setaf")) == (char *)-1)
31615e1c72e1SJason King lsc_setfg = NULL;
31625e1c72e1SJason King
31635e1c72e1SJason King if ((lsc_setbg = tigetstr("setab")) == (char *)-1)
31645e1c72e1SJason King lsc_setbg = NULL;
31655e1c72e1SJason King
31665e1c72e1SJason King if (getenv("_LS_COLOR_DEBUG") != NULL) {
31675e1c72e1SJason King int i;
31685e1c72e1SJason King
31695e1c72e1SJason King lsc_debug = 1;
31705e1c72e1SJason King for (i = 0; i < lsc_ncolors; ++i)
31715e1c72e1SJason King dump_color(&lsc_colors[i]);
3172da6c28aaSamw }
317338f2a414SAlbert Lee
317438f2a414SAlbert Lee free(colorstr);
3175da6c28aaSamw }
3176da6c28aaSamw
3177da6c28aaSamw /* Free extended system attribute lists */
3178da6c28aaSamw
3179da6c28aaSamw void
free_sysattr(struct lbuf * p)3180da6c28aaSamw free_sysattr(struct lbuf *p)
3181da6c28aaSamw {
3182da6c28aaSamw int i;
3183da6c28aaSamw
3184da6c28aaSamw if (p->exttr != NULL) {
3185da6c28aaSamw for (i = 0; i < sacnt; i++) {
3186da6c28aaSamw if (p->exttr[i].name != NULL)
3187da6c28aaSamw free(p->exttr[i].name);
3188da6c28aaSamw }
3189da6c28aaSamw free(p->exttr);
3190da6c28aaSamw }
3191da6c28aaSamw if (p->extm != NULL) {
3192da6c28aaSamw for (i = 0; i < sacnt; i++) {
3193da6c28aaSamw if (p->extm[i].name != NULL)
3194da6c28aaSamw free(p->extm[i].name);
3195da6c28aaSamw }
3196da6c28aaSamw free(p->extm);
3197da6c28aaSamw }
3198da6c28aaSamw }
3199da6c28aaSamw
3200da6c28aaSamw /* Allocate extended system attribute list */
3201da6c28aaSamw
3202da6c28aaSamw void *
xmalloc(size_t size,struct lbuf * p)3203da6c28aaSamw xmalloc(size_t size, struct lbuf *p)
3204da6c28aaSamw {
3205da6c28aaSamw if ((p = malloc(size)) == NULL) {
3206da6c28aaSamw perror("ls");
3207da6c28aaSamw free_sysattr(p);
3208da6c28aaSamw nvlist_free(response);
3209da6c28aaSamw exit(2);
3210da6c28aaSamw }
3211da6c28aaSamw return (p);
3212da6c28aaSamw }
3213