Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:19

0001 /*  $NetBSD: print.c,v 1.40 2004/11/17 17:00:00 mycroft Exp $   */
0002 
0003 /*
0004  * Copyright (c) 1989, 1993, 1994
0005  *  The Regents of the University of California.  All rights reserved.
0006  *
0007  * This code is derived from software contributed to Berkeley by
0008  * Michael Fischbein.
0009  *
0010  * Redistribution and use in source and binary forms, with or without
0011  * modification, are permitted provided that the following conditions
0012  * are met:
0013  * 1. Redistributions of source code must retain the above copyright
0014  *    notice, this list of conditions and the following disclaimer.
0015  * 2. Redistributions in binary form must reproduce the above copyright
0016  *    notice, this list of conditions and the following disclaimer in the
0017  *    documentation and/or other materials provided with the distribution.
0018  * 3. Neither the name of the University nor the names of its contributors
0019  *    may be used to endorse or promote products derived from this software
0020  *    without specific prior written permission.
0021  *
0022  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
0023  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0024  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0025  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
0026  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
0027  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
0028  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
0029  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
0030  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
0031  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
0032  * SUCH DAMAGE.
0033  */
0034 
0035 #ifdef HAVE_CONFIG_H
0036 #include "config.h"
0037 #endif
0038 
0039 #if 0
0040 #include <sys/cdefs.h>
0041 #ifndef lint
0042 #if 0
0043 static char sccsid[] = "@(#)print.c 8.5 (Berkeley) 7/28/94";
0044 #else
0045 __RCSID("$NetBSD: print.c,v 1.40 2004/11/17 17:00:00 mycroft Exp $");
0046 #endif
0047 #endif /* not lint */
0048 #endif
0049 
0050 #include <inttypes.h>
0051 
0052 #include <rtems.h>
0053 #include <rtems/inttypes.h>
0054 #include <rtems/libio.h>
0055 
0056 #include <sys/param.h>
0057 #include <sys/stat.h>
0058 
0059 #include "err.h"
0060 #include <errno.h>
0061 #include "fts.h"
0062 #include <grp.h>
0063 #include <pwd.h>
0064 #include <stdio.h>
0065 #include <stdlib.h>
0066 #include <string.h>
0067 #include <time.h>
0068 //#include <tzfile.h>
0069 #include <unistd.h>
0070 //#include <util.h>
0071 
0072 #include "internal.h"
0073 #include "extern-ls.h"
0074 
0075 #define DAYSPERNYEAR ((time_t)365)
0076 #define SECSPERDAY   ((time_t)60 * (time_t)60 * (time_t)24)
0077 
0078 
0079 #if RTEMS_REMOVED
0080 extern int termwidth;
0081 #endif
0082 
0083 static int  printaname(rtems_shell_ls_globals* globals, FTSENT *, int, int);
0084 static void printlink(rtems_shell_ls_globals* globals, FTSENT *);
0085 static void printtime(rtems_shell_ls_globals* globals, time_t);
0086 static int  printtype(u_int);
0087 
0088 #if RTEMS_REMOVED
0089 static time_t   now;
0090 #endif
0091 
0092 #define IS_NOPRINT(p)   ((p)->fts_number == NO_PRINT)
0093 
0094 void
0095 printscol(rtems_shell_ls_globals* globals, DISPLAY *dp)
0096 {
0097     FTSENT *p;
0098 
0099     for (p = dp->list; p; p = p->fts_link) {
0100         if (IS_NOPRINT(p))
0101             continue;
0102         (void)printaname(globals, p, dp->s_inode, dp->s_block);
0103         (void)putchar('\n');
0104     }
0105 }
0106 
0107 void
0108 printlong(rtems_shell_ls_globals* globals, DISPLAY *dp)
0109 {
0110     struct stat *sp;
0111     FTSENT *p;
0112     NAMES *np;
0113     char buf[20]; //, szbuf[5];
0114 
0115     now = time(NULL);
0116 
0117     if (dp->list->fts_level != FTS_ROOTLEVEL && (f_longform || f_size)) {
0118 #if RTEMS_REMOVED
0119         if (f_humanize) {
0120             if ((humanize_number(szbuf, sizeof(szbuf), dp->stotal,
0121                 "", HN_AUTOSCALE,
0122                 (HN_DECIMAL | HN_B | HN_NOSPACE))) == -1)
0123                 err(exit_jump, 1, "humanize_number");
0124             (void)printf("total %s\n", szbuf);
0125         } else {
0126 #endif
0127             (void)printf("total %llu\n",
0128                 (unsigned long long)(howmany(dp->btotal, blocksize)));
0129 #if RTEMS_REMOVED
0130         }
0131 #endif
0132     }
0133 
0134     for (p = dp->list; p; p = p->fts_link) {
0135         if (IS_NOPRINT(p))
0136             continue;
0137         sp = p->fts_statp;
0138         if (f_inode)
0139             (void)printf("%*" PRIuino_t " ", dp->s_inode,
0140                 sp->st_ino);
0141         if (f_size && !f_humanize) {
0142             (void)printf("%*llu ", dp->s_block,
0143                 (unsigned long long)howmany(sp->st_blocks, blocksize));
0144         }
0145         (void)strmode(sp->st_mode, buf);
0146         np = p->fts_pointer;
0147         (void)printf("%s %*lu ", buf, dp->s_nlink,
0148             (unsigned long)sp->st_nlink);
0149         if (!f_grouponly)
0150             (void)printf("%-*s  ", dp->s_user, np->user);
0151         (void)printf("%-*s  ", dp->s_group, np->group);
0152         if (f_flags)
0153             (void)printf("%-*s ", dp->s_flags, np->flags);
0154         if (S_ISCHR(sp->st_mode) || S_ISBLK(sp->st_mode))
0155             (void)printf("%*"PRIu32", %*"PRIu32" ",
0156                 dp->s_major, major(sp->st_rdev), dp->s_minor,
0157                 minor(sp->st_rdev));
0158         else
0159 #if RTEMS_REMOVED
0160             if (f_humanize) {
0161                 if ((humanize_number(szbuf, sizeof(szbuf),
0162                     sp->st_size, "", HN_AUTOSCALE,
0163                     (HN_DECIMAL | HN_B | HN_NOSPACE))) == -1)
0164                     err(1, "humanize_number");
0165                 (void)printf("%*s ", dp->s_size, szbuf);
0166             } else {
0167 #endif
0168       {
0169         unsigned long long size;
0170         if (sp->st_size < 0)
0171           size = sp->st_size * -1;
0172         else
0173           size = sp->st_size;
0174                 (void)printf("%*llu ", dp->s_size, size);
0175         }
0176         if (f_accesstime)
0177             printtime(globals, sp->st_atime);
0178         else if (f_statustime)
0179             printtime(globals, sp->st_ctime);
0180         else
0181             printtime(globals, sp->st_mtime);
0182         if (f_octal || f_octal_escape)
0183             (void)safe_print(globals, p->fts_name);
0184         else if (f_nonprint)
0185             (void)printescaped(globals, p->fts_name);
0186         else
0187             (void)printf("%s", p->fts_name);
0188 
0189         if (f_type || (f_typedir && S_ISDIR(sp->st_mode)))
0190             (void)printtype(sp->st_mode);
0191         if (S_ISLNK(sp->st_mode))
0192             printlink(globals, p);
0193         (void)putchar('\n');
0194     }
0195 }
0196 
0197 void
0198 printcol(rtems_shell_ls_globals* globals, DISPLAY *dp)
0199 {
0200     static FTSENT **array;
0201     static int lastentries = -1;
0202     FTSENT *p;
0203     int base, chcnt, col, colwidth, num;
0204     int numcols, numrows, row;
0205     //char szbuf[5];
0206 
0207     colwidth = dp->maxlen;
0208     if (f_inode)
0209         colwidth += dp->s_inode + 1;
0210     if (f_size) {
0211         if (f_humanize)
0212             colwidth += dp->s_size + 1;
0213         else
0214             colwidth += dp->s_block + 1;
0215     }
0216     if (f_type || f_typedir)
0217         colwidth += 1;
0218 
0219     colwidth += 1;
0220 
0221     if (termwidth < 2 * colwidth) {
0222         printscol(globals, dp);
0223         return;
0224     }
0225 
0226     /*
0227      * Have to do random access in the linked list -- build a table
0228      * of pointers.
0229      */
0230     if (dp->entries > lastentries) {
0231         lastentries = dp->entries;
0232         if ((array =
0233             realloc(array, dp->entries * sizeof(FTSENT *))) == NULL) {
0234             warn(NULL);
0235             printscol(globals, dp);
0236         }
0237     }
0238     for (p = dp->list, num = 0; p; p = p->fts_link)
0239         if (p->fts_number != NO_PRINT)
0240             array[num++] = p;
0241 
0242     numcols = termwidth / colwidth;
0243     colwidth = termwidth / numcols;     /* spread out if possible */
0244     numrows = num / numcols;
0245     if (num % numcols)
0246         ++numrows;
0247 
0248     if (dp->list->fts_level != FTS_ROOTLEVEL && (f_longform || f_size)) {
0249 #if RTEMS_REMOVED
0250         if (f_humanize) {
0251             if ((humanize_number(szbuf, sizeof(szbuf), dp->stotal,
0252                 "", HN_AUTOSCALE,
0253                 (HN_DECIMAL | HN_B | HN_NOSPACE))) == -1)
0254                 err(1, "humanize_number");
0255             (void)printf("total %s\n", szbuf);
0256         } else {
0257 #endif
0258             (void)printf("total %llu\n",
0259                 (unsigned long long)(howmany(dp->btotal, blocksize)));
0260 #if RTEMS_REMOVED
0261         }
0262 #endif
0263     }
0264     for (row = 0; row < numrows; ++row) {
0265         for (base = row, chcnt = col = 0; col < numcols; ++col) {
0266             chcnt = printaname(globals, array[base], dp->s_inode,
0267                 f_humanize && 0 ? dp->s_size : dp->s_block);
0268             if ((base += numrows) >= num)
0269                 break;
0270             while (chcnt++ < colwidth)
0271                 (void)putchar(' ');
0272         }
0273         (void)putchar('\n');
0274     }
0275 }
0276 
0277 void
0278 printacol(rtems_shell_ls_globals* globals, DISPLAY *dp)
0279 {
0280     FTSENT *p;
0281     int chcnt, col, colwidth;
0282     int numcols;
0283     //char szbuf[5];
0284 
0285     colwidth = dp->maxlen;
0286     if (f_inode)
0287         colwidth += dp->s_inode + 1;
0288     if (f_size) {
0289         if (f_humanize)
0290             colwidth += dp->s_size + 1;
0291         else
0292             colwidth += dp->s_block + 1;
0293     }
0294     if (f_type || f_typedir)
0295         colwidth += 1;
0296 
0297     colwidth += 1;
0298 
0299     if (termwidth < 2 * colwidth) {
0300         printscol(globals, dp);
0301         return;
0302     }
0303 
0304     numcols = termwidth / colwidth;
0305     colwidth = termwidth / numcols;     /* spread out if possible */
0306 
0307     if (dp->list->fts_level != FTS_ROOTLEVEL && (f_longform || f_size)) {
0308 #if RTEMS_REMOVED
0309         if (f_humanize) {
0310             if ((humanize_number(szbuf, sizeof(szbuf), dp->stotal,
0311                 "", HN_AUTOSCALE,
0312                 (HN_DECIMAL | HN_B | HN_NOSPACE))) == -1)
0313                 err(1, "humanize_number");
0314             (void)printf("total %s\n", szbuf);
0315         } else {
0316 #endif
0317             (void)printf("total %llu\n",
0318                 (unsigned long long)(howmany(dp->btotal, blocksize)));
0319 #if RTEMS_REMOVED
0320         }
0321 #endif
0322     }
0323     chcnt = col = 0;
0324     for (p = dp->list; p; p = p->fts_link) {
0325         if (IS_NOPRINT(p))
0326             continue;
0327         if (col >= numcols) {
0328         #ifdef __rtems__
0329         /*
0330          * chcnt is not using the value that it has been assigned
0331          * before being used again, resulting in a Coverity issue.
0332          * See CID 1255346
0333          */
0334             col = 0;
0335         #else
0336             chcnt = col = 0;
0337         #endif
0338             (void)putchar('\n');
0339         }
0340         chcnt = printaname(globals, p, dp->s_inode,
0341             f_humanize && 0 ? dp->s_size : dp->s_block);
0342         while (chcnt++ < colwidth)
0343             (void)putchar(' ');
0344         col++;
0345     }
0346     (void)putchar('\n');
0347 }
0348 
0349 void
0350 printstream(rtems_shell_ls_globals* globals, DISPLAY *dp)
0351 {
0352     FTSENT *p;
0353     int col;
0354     int extwidth;
0355 
0356     extwidth = 0;
0357     if (f_inode)
0358         extwidth += dp->s_inode + 1;
0359     if (f_size) {
0360         if (f_humanize)
0361             extwidth += dp->s_size + 1;
0362         else
0363             extwidth += dp->s_block + 1;
0364     }
0365     if (f_type)
0366         extwidth += 1;
0367 
0368     for (col = 0, p = dp->list; p != NULL; p = p->fts_link) {
0369         if (IS_NOPRINT(p))
0370             continue;
0371         if (col > 0) {
0372             (void)putchar(','), col++;
0373             if (col + 1 + extwidth + p->fts_namelen >= termwidth)
0374                 (void)putchar('\n'), col = 0;
0375             else
0376                 (void)putchar(' '), col++;
0377         }
0378         col += printaname(globals, p, dp->s_inode,
0379             f_humanize && 0 ? dp->s_size : dp->s_block);
0380     }
0381     (void)putchar('\n');
0382 }
0383 
0384 /*
0385  * print [inode] [size] name
0386  * return # of characters printed, no trailing characters.
0387  */
0388 static int
0389 printaname(rtems_shell_ls_globals* globals,
0390            FTSENT *p, int inodefield, int sizefield)
0391 {
0392     struct stat *sp;
0393     int chcnt;
0394     //char szbuf[5];
0395 
0396     sp = p->fts_statp;
0397     chcnt = 0;
0398     if (f_inode)
0399         chcnt += printf("%*" PRIuino_t " ", inodefield, sp->st_ino);
0400     if (f_size) {
0401 #if RTEMS_REMOVED
0402         if (f_humanize) {
0403             if ((humanize_number(szbuf, sizeof(szbuf), sp->st_size,
0404                 "", HN_AUTOSCALE,
0405                 (HN_DECIMAL | HN_B | HN_NOSPACE))) == -1)
0406                 err(1, "humanize_number");
0407             chcnt += printf("%*s ", sizefield, szbuf);
0408         } else {
0409 #endif
0410             chcnt += printf("%*llu ", sizefield,
0411                 (unsigned long long)howmany(sp->st_blocks, blocksize));
0412 #if RTEMS_REMOVED
0413         }
0414 #endif
0415     }
0416     if (f_octal || f_octal_escape)
0417         chcnt += safe_print(globals, p->fts_name);
0418     else if (f_nonprint)
0419         chcnt += printescaped(globals, p->fts_name);
0420     else
0421         chcnt += printf("%s", p->fts_name);
0422     if (f_type || (f_typedir && S_ISDIR(sp->st_mode)))
0423         chcnt += printtype(sp->st_mode);
0424     return (chcnt);
0425 }
0426 
0427 static void
0428 printtime(rtems_shell_ls_globals* globals, time_t ftime)
0429 {
0430     int i;
0431     char *longstring;
0432 
0433     longstring = ctime(&ftime);
0434     for (i = 4; i < 11; ++i)
0435         (void)putchar(longstring[i]);
0436 
0437 #define SIXMONTHS   ((DAYSPERNYEAR / 2) * SECSPERDAY)
0438     if (f_sectime)
0439         for (i = 11; i < 24; i++)
0440             (void)putchar(longstring[i]);
0441     else if (ftime + SIXMONTHS > now && ftime - SIXMONTHS < now)
0442         for (i = 11; i < 16; ++i)
0443             (void)putchar(longstring[i]);
0444     else {
0445         (void)putchar(' ');
0446         for (i = 20; i < 24; ++i)
0447             (void)putchar(longstring[i]);
0448     }
0449     (void)putchar(' ');
0450 }
0451 
0452 static int
0453 printtype(u_int mode)
0454 {
0455     switch (mode & S_IFMT) {
0456     case S_IFDIR:
0457         (void)putchar('/');
0458         return (1);
0459     case S_IFIFO:
0460         (void)putchar('|');
0461         return (1);
0462     case S_IFLNK:
0463         (void)putchar('@');
0464         return (1);
0465     case S_IFSOCK:
0466         (void)putchar('=');
0467         return (1);
0468 #if RTEMS_REMOVED
0469     case S_IFWHT:
0470         (void)putchar('%');
0471         return (1);
0472 #endif
0473     }
0474     if (mode & (S_IXUSR | S_IXGRP | S_IXOTH)) {
0475         (void)putchar('*');
0476         return (1);
0477     }
0478     return (0);
0479 }
0480 
0481 static void
0482 printlink(rtems_shell_ls_globals* globals, FTSENT *p)
0483 {
0484     int lnklen;
0485     char name[MAXPATHLEN + 1], path[MAXPATHLEN + 1];
0486 
0487     if (p->fts_level == FTS_ROOTLEVEL)
0488         (void)snprintf(name, sizeof(name), "%s", p->fts_name);
0489     else
0490         (void)snprintf(name, sizeof(name),
0491             "%s/%s", p->fts_parent->fts_accpath, p->fts_name);
0492     if ((lnklen = readlink(name, path, sizeof(path) - 1)) == -1) {
0493         (void)fprintf(stderr, "\nls: %s: %s\n", name, strerror(errno));
0494         return;
0495     }
0496     path[lnklen] = '\0';
0497     (void)printf(" -> ");
0498     if (f_octal || f_octal_escape)
0499         (void)safe_print(globals, path);
0500     else if (f_nonprint)
0501         (void)printescaped(globals, path);
0502     else
0503         (void)printf("%s", path);
0504 }