6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright (c) 2012, Joyent, Inc. All rights reserved.
  25  * Copyright 2015 Gary Mills
  26  */
  27 
  28 /*
  29  * Copyright 2017 Jason King.  All rights reserved.
  30  * Use is subject to license terms.
  31  */
  32 
  33 /*      Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T     */
  34 /*        All Rights Reserved   */
  35 
  36 /*      Copyright (c) 1987, 1988 Microsoft Corporation  */
  37 /*        All Rights Reserved   */
  38 
  39 /*
  40  * List files or directories
  41  */
  42 
  43 #include <sys/param.h>
  44 #include <sys/types.h>
  45 #include <sys/mkdev.h>
 
 
 213         int cycle_detected;     /* cycle detected visiting this directory */
 214         struct ditem *myancinfo;        /* this directory's ancestry info */
 215         struct dchain *dc_next; /* next directory in the chain */
 216 };
 217 
 218 static struct dchain *dfirst;   /* start of the dir chain */
 219 static struct dchain *cdfirst;  /* start of the current dir chain */
 220 static struct dchain *dtemp;    /* temporary - used for linking */
 221 static char *curdir;            /* the current directory */
 222 
 223 static int      first = 1;      /* true if first line is not yet printed */
 224 static int      nfiles = 0;     /* number of flist entries in current use */
 225 static int      nargs = 0;      /* number of flist entries used for arguments */
 226 static int      maxfils = 0;    /* number of flist/lbuf entries allocated */
 227 static int      maxn = 0;       /* number of flist entries with lbufs asigned */
 228 static int      quantn = 64;    /* allocation growth quantum */
 229 
 230 static struct lbuf      *nxtlbf;        /* ptr to next lbuf to be assigned */
 231 static struct lbuf      **flist;        /* ptr to list of lbuf pointers */
 232 static struct lbuf      *gstat(char *, int, struct ditem *);
 233 static char             *getname(uid_t);
 234 static char             *getgroup(gid_t);
 235 static char             *makename(char *, char *);
 236 static void             pentry(struct lbuf *);
 237 static void             column(void);
 238 static void             pmode(mode_t aflag);
 239 static void             selection(int *);
 240 static void             new_line(void);
 241 static void             rddir(char *, struct ditem *);
 242 static int              strcol(unsigned char *);
 243 static void             pem(struct lbuf **, struct lbuf **, int);
 244 static void             pdirectory(char *, int, int, int, struct ditem *);
 245 static struct cachenode *findincache(struct cachenode **, long);
 246 static void             csi_pprintf(unsigned char *);
 247 static void             pprintf(char *, char *);
 248 static int              compar(struct lbuf **pp1, struct lbuf **pp2);
 249 static void             record_ancestry(char *, struct stat *, struct lbuf *,
 250                             int, struct ditem *);
 251 static void             ls_color_init(void);
 252 static ls_color_t       *ls_color_find(const char *, mode_t);
 
 
 759                         statreq++;
 760                         Cflg = 0;
 761                         xflg = 0;
 762                         mflg = 0;
 763                         atflg = 0;
 764                         continue;
 765                 case 'L':
 766                         Lflg++;
 767                         /* -H and -L are mutually exclusive */
 768                         Hflg = 0;
 769                         continue;
 770                 case 'm':
 771                         Cflg = 0;
 772                         mflg = 1;
 773 #ifdef XPG4
 774                         lflg = 0;
 775 #endif
 776                         continue;
 777                 case 'n':
 778                         nflg++;
 779                         lflg++;
 780                         statreq++;
 781                         Cflg = 0;
 782                         xflg = 0;
 783                         mflg = 0;
 784                         atflg = 0;
 785                         continue;
 786                 case 'o':
 787                         oflg++;
 788                         lflg++;
 789                         statreq++;
 790                         continue;
 791                 case 'p':
 792                         pflg++;
 793                         statreq++;
 794                         continue;
 795                 case 'q':
 796                         qflg = 1;
 797                         bflg = 0;
 798                         continue;
 799                 case 'r':
 800                         rflg = -1;
 801                         continue;
 802                 case 'R':
 803                         Rflg++;
 804                         statreq++;
 
 
1224         else
1225                 row = 0;
1226 
1227         nrows = (lp - slp - 1) / ncols + 1;
1228         for (i = 0; i < nrows; i++, row++) {
1229                 for (col = 0; col < ncols; col++) {
1230                         ep = slp + (nrows * col) + row;
1231                         if (ep < lp)
1232                                 pentry(*ep);
1233                 }
1234                 new_line();
1235         }
1236 }
1237 
1238 /*
1239  * print one output entry;
1240  * if uid/gid is not found in the appropriate
1241  * file(passwd/group), then print uid/gid instead of
1242  * user/group name;
1243  */
1244 static void
1245 pentry(struct lbuf *ap)
1246 {
1247         struct lbuf *p;
1248         char *dmark = "";       /* Used if -p or -F option active */
1249         char *cp;
1250         char *str;
1251 
1252         if (noflist) {
1253                 (void) printf("%s\n", (ap->lflags & ISARG) ? ap->ln.namep :
1254                     ap->ln.lname);
1255                 return;
1256         }
1257 
1258         p = ap;
1259         column();
1260         if (iflg) {
1261                 if (mflg && !lflg)
1262                         curcol += printf("%llu ", (long long)p->lnum);
1263                 else
1264                         curcol += printf("%10llu ", (long long)p->lnum);
1265         }
1266         if (sflg) {
1267                 curcol += printf((mflg && !lflg) ? "%lld " :
1268                     (p->lblocks < 10000) ? "%4lld " : "%lld ",
1269                     (p->ltype != 'b' && p->ltype != 'c') ?
1270                     p->lblocks : 0LL);
1271         }
1272         if (lflg) {
1273                 (void) putchar(p->ltype);
1274                 curcol++;
1275                 pmode(p->lflags);
1276 
1277                 /* ACL: additional access mode flag */
1278                 (void) putchar(p->acl);
1279                 curcol++;
1280 
1281                 curcol += printf("%3lu ", (ulong_t)p->lnl);
1282                 if (oflg) {
1283                         if (!nflg) {
1284                                 cp = getname(p->luid);
1285                                 curcol += printf("%-8s ", cp);
1286                         } else
1287                                 curcol += printf("%-8lu ", (ulong_t)p->luid);
1288                 }
1289                 if (gflg) {
1290                         if (!nflg) {
1291                                 cp = getgroup(p->lgid);
1292                                 curcol += printf("%-8s ", cp);
1293                         } else
1294                                 curcol += printf("%-8lu ", (ulong_t)p->lgid);
1295                 }
1296                 if (p->ltype == 'b' || p->ltype == 'c') {
1297                         curcol += printf("%3u, %2u",
1298                             (uint_t)major((dev_t)p->lsize),
1299                             (uint_t)minor((dev_t)p->lsize));
1300                 } else if (hflg) {
1301                         char numbuf[NN_NUMBUF_SZ];
1302 
1303                         nicenum_scale(p->lsize, 1, numbuf, sizeof (numbuf),
1304                             nicenum_flags);
1305 
1306                         curcol += printf("%7s", numbuf);
1307                 } else {
1308                         uint64_t bsize = p->lsize / block_size;
1309 
1310                         /*
1311                          * Round up only when using blocks > 1 byte, otherwise
1312                          * 'normal' sizes display 1 byte too large.
1313                          */
1314                         if (p->lsize % block_size != 0)
1315                                 bsize++;
 
1409                         for (i = 0; i < sacnt; i++) {
1410                                 if (p->exttr[i].name != NULL) {
1411                                         (void) printf("%s", p->exttr[i].name);
1412                                         k--;
1413                                         if (vopt && (k != 0))
1414                                                 (void) printf(",");
1415                                 }
1416                         }
1417                 }
1418                 (void) printf("}\n");
1419         }
1420         /* Display file timestamps and extended system attribute timestamps */
1421         if (tmflg && alltm) {
1422                 new_line();
1423                 print_time(p);
1424                 new_line();
1425         }
1426         if (vflg) {
1427                 new_line();
1428                 if (p->aclp) {
1429                         acl_printacl(p->aclp, num_cols, Vflg);
1430                 }
1431         }
1432         /* Free extended system attribute lists */
1433         if (saflg || tmflg)
1434                 free_sysattr(p);
1435 }
1436 
1437 /* print various r,w,x permissions */
1438 static void
1439 pmode(mode_t aflag)
1440 {
1441         /* these arrays are declared static to allow initializations */
1442         static int      m0[] = { 1, S_IRUSR, 'r', '-' };
1443         static int      m1[] = { 1, S_IWUSR, 'w', '-' };
1444         static int      m2[] = { 3, S_ISUID|S_IXUSR, 's', S_IXUSR,
1445             'x', S_ISUID, 'S', '-' };
1446         static int      m3[] = { 1, S_IRGRP, 'r', '-' };
1447         static int      m4[] = { 1, S_IWGRP, 'w', '-' };
1448         static int      m5[] = { 4, S_ISGID|S_IXGRP, 's', S_IXGRP,
1449                                 'x', S_ISGID|LS_NOTREG, 'S',
 
2197                 } else if (val < c->val) {
2198                         parent = &c->lesschild;
2199                         c = c->lesschild;
2200                 } else {
2201                         parent = &c->grtrchild;
2202                         c = c->grtrchild;
2203                 }
2204         }
2205 
2206         /* not in the cache, make a new entry for it */
2207         c = calloc(1, sizeof (struct cachenode));
2208         if (c == NULL) {
2209                 perror("ls");
2210                 exit(2);
2211         }
2212         *parent = c;
2213         c->val = val;
2214         return (c);
2215 }
2216 
2217 /*
2218  * get name from cache, or passwd file for a given uid;
2219  * lastuid is set to uid.
2220  */
2221 static char *
2222 getname(uid_t uid)
2223 {
2224         struct passwd *pwent;
2225         struct cachenode *c;
2226 
2227         if ((uid == lastuid) && lastuname)
2228                 return (lastuname);
2229 
2230         c = findincache(&names, uid);
2231         if (c->initted == 0) {
2232                 if ((pwent = getpwuid(uid)) != NULL) {
2233                         SCPYN(&c->name[0], pwent->pw_name);
2234                 } else {
2235                         (void) sprintf(&c->name[0], "%-8u", (int)uid);
2236                 }
 
 | 
 
 
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright (c) 2012, Joyent, Inc. All rights reserved.
  25  * Copyright 2015 Gary Mills
  26  *
  27  * Copyright 2016 Nexenta Systems, Inc.  All rights reserved.
  28  */
  29 
  30 /*
  31  * Copyright 2017 Jason King.  All rights reserved.
  32  * Use is subject to license terms.
  33  */
  34 
  35 /*      Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T     */
  36 /*        All Rights Reserved   */
  37 
  38 /*      Copyright (c) 1987, 1988 Microsoft Corporation  */
  39 /*        All Rights Reserved   */
  40 
  41 /*
  42  * List files or directories
  43  */
  44 
  45 #include <sys/param.h>
  46 #include <sys/types.h>
  47 #include <sys/mkdev.h>
 
 
 215         int cycle_detected;     /* cycle detected visiting this directory */
 216         struct ditem *myancinfo;        /* this directory's ancestry info */
 217         struct dchain *dc_next; /* next directory in the chain */
 218 };
 219 
 220 static struct dchain *dfirst;   /* start of the dir chain */
 221 static struct dchain *cdfirst;  /* start of the current dir chain */
 222 static struct dchain *dtemp;    /* temporary - used for linking */
 223 static char *curdir;            /* the current directory */
 224 
 225 static int      first = 1;      /* true if first line is not yet printed */
 226 static int      nfiles = 0;     /* number of flist entries in current use */
 227 static int      nargs = 0;      /* number of flist entries used for arguments */
 228 static int      maxfils = 0;    /* number of flist/lbuf entries allocated */
 229 static int      maxn = 0;       /* number of flist entries with lbufs asigned */
 230 static int      quantn = 64;    /* allocation growth quantum */
 231 
 232 static struct lbuf      *nxtlbf;        /* ptr to next lbuf to be assigned */
 233 static struct lbuf      **flist;        /* ptr to list of lbuf pointers */
 234 static struct lbuf      *gstat(char *, int, struct ditem *);
 235 static char             *get_sid_name(uid_t, boolean_t, boolean_t);
 236 static char             *getname(uid_t);
 237 static char             *getgroup(gid_t);
 238 static char             *makename(char *, char *);
 239 static void             pentry(struct lbuf *);
 240 static void             column(void);
 241 static void             pmode(mode_t aflag);
 242 static void             selection(int *);
 243 static void             new_line(void);
 244 static void             rddir(char *, struct ditem *);
 245 static int              strcol(unsigned char *);
 246 static void             pem(struct lbuf **, struct lbuf **, int);
 247 static void             pdirectory(char *, int, int, int, struct ditem *);
 248 static struct cachenode *findincache(struct cachenode **, long);
 249 static void             csi_pprintf(unsigned char *);
 250 static void             pprintf(char *, char *);
 251 static int              compar(struct lbuf **pp1, struct lbuf **pp2);
 252 static void             record_ancestry(char *, struct stat *, struct lbuf *,
 253                             int, struct ditem *);
 254 static void             ls_color_init(void);
 255 static ls_color_t       *ls_color_find(const char *, mode_t);
 
 
 762                         statreq++;
 763                         Cflg = 0;
 764                         xflg = 0;
 765                         mflg = 0;
 766                         atflg = 0;
 767                         continue;
 768                 case 'L':
 769                         Lflg++;
 770                         /* -H and -L are mutually exclusive */
 771                         Hflg = 0;
 772                         continue;
 773                 case 'm':
 774                         Cflg = 0;
 775                         mflg = 1;
 776 #ifdef XPG4
 777                         lflg = 0;
 778 #endif
 779                         continue;
 780                 case 'n':
 781                         nflg++;
 782                         if (nflg == 1) {
 783                                 lflg++;
 784                                 statreq++;
 785                                 Cflg = 0;
 786                                 xflg = 0;
 787                                 mflg = 0;
 788                                 atflg = 0;
 789                         }
 790                         continue;
 791                 case 'o':
 792                         oflg++;
 793                         lflg++;
 794                         statreq++;
 795                         continue;
 796                 case 'p':
 797                         pflg++;
 798                         statreq++;
 799                         continue;
 800                 case 'q':
 801                         qflg = 1;
 802                         bflg = 0;
 803                         continue;
 804                 case 'r':
 805                         rflg = -1;
 806                         continue;
 807                 case 'R':
 808                         Rflg++;
 809                         statreq++;
 
1229         else
1230                 row = 0;
1231 
1232         nrows = (lp - slp - 1) / ncols + 1;
1233         for (i = 0; i < nrows; i++, row++) {
1234                 for (col = 0; col < ncols; col++) {
1235                         ep = slp + (nrows * col) + row;
1236                         if (ep < lp)
1237                                 pentry(*ep);
1238                 }
1239                 new_line();
1240         }
1241 }
1242 
1243 /*
1244  * print one output entry;
1245  * if uid/gid is not found in the appropriate
1246  * file(passwd/group), then print uid/gid instead of
1247  * user/group name;
1248  */
1249 #define         DUMP_EPHEMERAL(x)       printf("%-8lu ", (ulong_t)(x))
1250 static void
1251 pentry(struct lbuf *ap)
1252 {
1253         struct lbuf *p;
1254         char *dmark = "";       /* Used if -p or -F option active */
1255         char *cp;
1256         char *str;
1257 
1258         if (noflist) {
1259                 (void) printf("%s\n", (ap->lflags & ISARG) ? ap->ln.namep :
1260                     ap->ln.lname);
1261                 return;
1262         }
1263 
1264         p = ap;
1265         column();
1266         if (iflg) {
1267                 if (mflg && !lflg)
1268                         curcol += printf("%llu ", (long long)p->lnum);
1269                 else
1270                         curcol += printf("%10llu ", (long long)p->lnum);
1271         }
1272         if (sflg) {
1273                 curcol += printf((mflg && !lflg) ? "%lld " :
1274                     (p->lblocks < 10000) ? "%4lld " : "%lld ",
1275                     (p->ltype != 'b' && p->ltype != 'c') ?
1276                     p->lblocks : 0LL);
1277         }
1278         if (lflg) {
1279                 boolean_t       res;
1280 
1281                 (void) putchar(p->ltype);
1282                 curcol++;
1283                 pmode(p->lflags);
1284 
1285                 /* ACL: additional access mode flag */
1286                 (void) putchar(p->acl);
1287                 curcol++;
1288 
1289                 curcol += printf("%3lu ", (ulong_t)p->lnl);
1290                 if (oflg) {
1291                         boolean_t       usr = B_TRUE;
1292 
1293                         if (nflg == 0) {        /* -n not specified; resolve */
1294                                 if (p->luid > MAXUID) {
1295                                         res = B_FALSE;
1296                                         cp = get_sid_name(p->luid, usr, res);
1297                                 } else {
1298                                         cp = getname(p->luid);
1299                                 }
1300                                 curcol += printf("%-8s ", cp);
1301 
1302                         } else if (nflg == 1) { /* -n specified; force SID's */
1303                                 if (p->luid > MAXUID) {
1304                                         res = B_TRUE;
1305 
1306                                         cp = get_sid_name(p->luid, usr, res);
1307                                         curcol += printf("%-8s ", cp);
1308                                 } else {
1309                                         curcol += DUMP_EPHEMERAL(p->luid);
1310                                 }
1311                         } else          /* -nn specified; force ephemerals */
1312                                 curcol += DUMP_EPHEMERAL(p->luid);
1313                 }
1314                 if (gflg) {
1315                         boolean_t       usr = B_FALSE;
1316 
1317                         if (nflg == 0) {        /* -n not specified; resolve */
1318                                 if (p->lgid > MAXUID) {
1319                                         res = B_FALSE;
1320                                         cp = get_sid_name(p->lgid, usr, res);
1321                                 } else {
1322                                         cp = getgroup(p->lgid);
1323                                 }
1324                                 curcol += printf("%-8s ", cp);
1325 
1326                         } else if (nflg == 1) { /* -n specified; force SID's */
1327                                 if (p->lgid > MAXUID) {
1328                                         res = B_TRUE;
1329 
1330                                         cp = get_sid_name(p->lgid, usr, res);
1331                                         curcol += printf("%-8s ", cp);
1332                                 } else {
1333                                         curcol += DUMP_EPHEMERAL(p->lgid);
1334                                 }
1335                         } else          /* -nn specified; force ephemerals */
1336                                 curcol += DUMP_EPHEMERAL(p->lgid);
1337                 }
1338                 if (p->ltype == 'b' || p->ltype == 'c') {
1339                         curcol += printf("%3u, %2u",
1340                             (uint_t)major((dev_t)p->lsize),
1341                             (uint_t)minor((dev_t)p->lsize));
1342                 } else if (hflg) {
1343                         char numbuf[NN_NUMBUF_SZ];
1344 
1345                         nicenum_scale(p->lsize, 1, numbuf, sizeof (numbuf),
1346                             nicenum_flags);
1347 
1348                         curcol += printf("%7s", numbuf);
1349                 } else {
1350                         uint64_t bsize = p->lsize / block_size;
1351 
1352                         /*
1353                          * Round up only when using blocks > 1 byte, otherwise
1354                          * 'normal' sizes display 1 byte too large.
1355                          */
1356                         if (p->lsize % block_size != 0)
1357                                 bsize++;
 
1451                         for (i = 0; i < sacnt; i++) {
1452                                 if (p->exttr[i].name != NULL) {
1453                                         (void) printf("%s", p->exttr[i].name);
1454                                         k--;
1455                                         if (vopt && (k != 0))
1456                                                 (void) printf(",");
1457                                 }
1458                         }
1459                 }
1460                 (void) printf("}\n");
1461         }
1462         /* Display file timestamps and extended system attribute timestamps */
1463         if (tmflg && alltm) {
1464                 new_line();
1465                 print_time(p);
1466                 new_line();
1467         }
1468         if (vflg) {
1469                 new_line();
1470                 if (p->aclp) {
1471                         int flgs = ACL_SID_FMT;
1472 
1473                         flgs |= Vflg ? ACL_COMPACT_FMT : 0;
1474                         flgs |= (nflg == 1) ? ACL_NORESOLVE : 0;
1475                         flgs |= (nflg >= 2) ? ACL_EPHEMERAL : 0;
1476 
1477                         acl_printacl(p->aclp, num_cols, flgs);
1478                 }
1479         }
1480         /* Free extended system attribute lists */
1481         if (saflg || tmflg)
1482                 free_sysattr(p);
1483 }
1484 
1485 /* print various r,w,x permissions */
1486 static void
1487 pmode(mode_t aflag)
1488 {
1489         /* these arrays are declared static to allow initializations */
1490         static int      m0[] = { 1, S_IRUSR, 'r', '-' };
1491         static int      m1[] = { 1, S_IWUSR, 'w', '-' };
1492         static int      m2[] = { 3, S_ISUID|S_IXUSR, 's', S_IXUSR,
1493             'x', S_ISUID, 'S', '-' };
1494         static int      m3[] = { 1, S_IRGRP, 'r', '-' };
1495         static int      m4[] = { 1, S_IWGRP, 'w', '-' };
1496         static int      m5[] = { 4, S_ISGID|S_IXGRP, 's', S_IXGRP,
1497                                 'x', S_ISGID|LS_NOTREG, 'S',
 
2245                 } else if (val < c->val) {
2246                         parent = &c->lesschild;
2247                         c = c->lesschild;
2248                 } else {
2249                         parent = &c->grtrchild;
2250                         c = c->grtrchild;
2251                 }
2252         }
2253 
2254         /* not in the cache, make a new entry for it */
2255         c = calloc(1, sizeof (struct cachenode));
2256         if (c == NULL) {
2257                 perror("ls");
2258                 exit(2);
2259         }
2260         *parent = c;
2261         c->val = val;
2262         return (c);
2263 }
2264 
2265 /*
2266  * SID MAX String Length: "http://stackoverflow.com/questions/1140528/"
2267  */
2268 #define SID_STR_MAX     185                     /* +1 for null char */
2269 static char *
2270 get_sid_name(uid_t id, boolean_t user, boolean_t res)
2271 {
2272         static char     *sid = NULL;
2273         char            *p = NULL;
2274 
2275         if (sid_string_by_id(id, user, &sid, res)) {
2276                 if ((p = getname(id)) == NULL) {
2277                         /*
2278                          * getname() already converts to ephemeral if id
2279                          * is not found in passwd or group file(s). This
2280                          * should be an extreme case.
2281                          */
2282                         static char      buf[SID_STR_MAX] = {'\0'};
2283 
2284                         (void) sprintf(buf, "%-8u", (int)id);
2285                         p = buf;
2286                 }
2287         } else
2288                 p = sid;
2289 
2290         return (p);
2291 }
2292 
2293 /*
2294  * get name from cache, or passwd file for a given uid;
2295  * lastuid is set to uid.
2296  */
2297 static char *
2298 getname(uid_t uid)
2299 {
2300         struct passwd *pwent;
2301         struct cachenode *c;
2302 
2303         if ((uid == lastuid) && lastuname)
2304                 return (lastuname);
2305 
2306         c = findincache(&names, uid);
2307         if (c->initted == 0) {
2308                 if ((pwent = getpwuid(uid)) != NULL) {
2309                         SCPYN(&c->name[0], pwent->pw_name);
2310                 } else {
2311                         (void) sprintf(&c->name[0], "%-8u", (int)uid);
2312                 }
 
 |