home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / bin / ls / print.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-12-05  |  7.2 KB  |  289 lines

  1. /*
  2.  * Copyright (c) 1989 The Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * This code is derived from software contributed to Berkeley by
  6.  * Michael Fischbein.
  7.  *
  8.  * Redistribution and use in source and binary forms, with or without
  9.  * modification, are permitted provided that the following conditions
  10.  * are met:
  11.  * 1. Redistributions of source code must retain the above copyright
  12.  *    notice, this list of conditions and the following disclaimer.
  13.  * 2. Redistributions in binary form must reproduce the above copyright
  14.  *    notice, this list of conditions and the following disclaimer in the
  15.  *    documentation and/or other materials provided with the distribution.
  16.  * 3. All advertising materials mentioning features or use of this software
  17.  *    must display the following acknowledgement:
  18.  *    This product includes software developed by the University of
  19.  *    California, Berkeley and its contributors.
  20.  * 4. Neither the name of the University nor the names of its contributors
  21.  *    may be used to endorse or promote products derived from this software
  22.  *    without specific prior written permission.
  23.  *
  24.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  25.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  26.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  27.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  28.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  29.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  30.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  31.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  32.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  33.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  34.  * SUCH DAMAGE.
  35.  */
  36.  
  37. #ifndef lint
  38. static char sccsid[] = "@(#)print.c    5.37 (Berkeley) 7/20/92";
  39. #endif /* not lint */
  40.  
  41. #include <sys/param.h>
  42. #include <sys/stat.h>
  43. #include <fts.h>
  44. #include <time.h>
  45. #include <errno.h>
  46. #include <grp.h>
  47. #include <pwd.h>
  48. #include <utmp.h>
  49. #include <unistd.h>
  50. #include <tzfile.h>
  51. #include <stdlib.h>
  52. #include <stdio.h>
  53. #include <string.h>
  54. #include "ls.h"
  55. #include "extern.h"
  56.  
  57. static int    printaname __P((FTSENT *, u_long, u_long));
  58. static void    printlink __P((FTSENT *));
  59. static void    printtime __P((time_t));
  60. static int    printtype __P((u_int));
  61.  
  62. #define    IS_NOPRINT(p)    ((p)->fts_number == NO_PRINT)
  63.  
  64. void
  65. printscol(dp)
  66.     DISPLAY *dp;
  67. {
  68.     register FTSENT *p;
  69.  
  70.     for (p = dp->list; p; p = p->fts_link) {
  71.         if (IS_NOPRINT(p))
  72.             continue;
  73.         (void)printaname(p, dp->s_inode, dp->s_block);
  74.         (void)putchar('\n');
  75.     }
  76. }
  77.  
  78. void
  79. printlong(dp)
  80.     DISPLAY *dp;
  81. {
  82.     register FTSENT *p;
  83.     register struct stat *sp;
  84.     NAMES *np;
  85.     char buf[20];
  86.  
  87.     if (dp->list->fts_level != FTS_ROOTLEVEL && (f_longform || f_size))
  88.         (void)printf("total %lu\n", howmany(dp->btotal, blocksize));
  89.  
  90.     for (p = dp->list; p; p = p->fts_link) {
  91.         if (IS_NOPRINT(p))
  92.             continue;
  93.         sp = p->fts_statp;
  94.         if (f_inode)
  95.             (void)printf("%*lu ", dp->s_inode, sp->st_ino);
  96.         if (f_size)
  97.             (void)printf("%*qd ",
  98.                 dp->s_block, howmany(sp->st_blocks, blocksize));
  99.         (void)strmode(sp->st_mode, buf);
  100.         np = p->fts_pointer;
  101.         (void)printf("%s %*u %-*s  %-*s  ", buf, dp->s_nlink,
  102.             sp->st_nlink, dp->s_user, np->user, dp->s_group,
  103.             np->group);
  104.         if (f_flags)
  105.             (void)printf("%-*s ", dp->s_flags, np->flags);
  106.         if (S_ISCHR(sp->st_mode) || S_ISBLK(sp->st_mode))
  107.             (void)printf("%3d, %3d ",
  108.                 major(sp->st_rdev), minor(sp->st_rdev));
  109.         else if (dp->bcfile)
  110.             (void)printf("%*s%*qd ",
  111.                 8 - dp->s_size, "", dp->s_size, sp->st_size);
  112.         else
  113.             (void)printf("%*qd ", dp->s_size, sp->st_size);
  114.         if (f_accesstime)
  115.             printtime(sp->st_atime);
  116.         else if (f_statustime)
  117.             printtime(sp->st_ctime);
  118.         else
  119.             printtime(sp->st_mtime);
  120.         (void)printf("%s", p->fts_name);
  121.         if (f_type)
  122.             (void)printtype(sp->st_mode);
  123.         if (S_ISLNK(sp->st_mode))
  124.             printlink(p);
  125.         (void)putchar('\n');
  126.     }
  127. }
  128.  
  129. #define    TAB    8
  130.  
  131. void
  132. printcol(dp)
  133.     DISPLAY *dp;
  134. {
  135.     extern int termwidth;
  136.     static FTSENT **array;
  137.     static int lastentries = -1;
  138.     register FTSENT *p;
  139.     register int base, chcnt, cnt, col, colwidth, num;
  140.     int endcol, numcols, numrows, row;
  141.  
  142.     /*
  143.      * Have to do random access in the linked list -- build a table
  144.      * of pointers.
  145.      */
  146.     if (dp->entries > lastentries) {
  147.         lastentries = dp->entries;
  148.         if ((array =
  149.             realloc(array, dp->entries * sizeof(FTSENT *))) == NULL) {
  150.             err(0, "%s", strerror(errno));
  151.             printscol(dp);
  152.         }
  153.     }
  154.     for (p = dp->list, num = 0; p; p = p->fts_link)
  155.         if (p->fts_number != NO_PRINT)
  156.             array[num++] = p;
  157.  
  158.     colwidth = dp->maxlen;
  159.     if (f_inode)
  160.         colwidth += dp->s_inode + 1;
  161.     if (f_size)
  162.         colwidth += dp->s_block + 1;
  163.     if (f_type)
  164.         colwidth += 1;
  165.  
  166.     colwidth = (colwidth + TAB) & ~(TAB - 1);
  167.     if (termwidth < 2 * colwidth) {
  168.         printscol(dp);
  169.         return;
  170.     }
  171.  
  172.     numcols = termwidth / colwidth;
  173.     numrows = num / numcols;
  174.     if (num % numcols)
  175.         ++numrows;
  176.  
  177.     if (dp->list->fts_level != FTS_ROOTLEVEL && (f_longform || f_size))
  178.         (void)printf("total %lu\n", howmany(dp->btotal, blocksize));
  179.     for (row = 0; row < numrows; ++row) {
  180.         endcol = colwidth;
  181.         for (base = row, chcnt = col = 0; col < numcols; ++col) {
  182.             chcnt += printaname(array[base], dp->s_inode,
  183.                 dp->s_block);
  184.             if ((base += numrows) >= num)
  185.                 break;
  186.             while ((cnt = (chcnt + TAB & ~(TAB - 1))) <= endcol) {
  187.                 (void)putchar('\t');
  188.                 chcnt = cnt;
  189.             }
  190.             endcol += colwidth;
  191.         }
  192.         (void)putchar('\n');
  193.     }
  194. }
  195.  
  196. /*
  197.  * print [inode] [size] name
  198.  * return # of characters printed, no trailing characters.
  199.  */
  200. static int
  201. printaname(p, inodefield, sizefield)
  202.     register FTSENT *p;
  203.     u_long sizefield, inodefield;
  204. {
  205.     struct stat *sp;
  206.     int chcnt;
  207.  
  208.     sp = p->fts_statp;
  209.     chcnt = 0;
  210.     if (f_inode)
  211.         chcnt += printf("%*lu ", inodefield, sp->st_ino);
  212.     if (f_size)
  213.         chcnt += printf("%*qd ",
  214.             sizefield, howmany(sp->st_blocks, blocksize));
  215.     chcnt += printf("%s", p->fts_name);
  216.     if (f_type)
  217.         chcnt += printtype(sp->st_mode);
  218.     return (chcnt);
  219. }
  220.  
  221. static void
  222. printtime(ftime)
  223.     time_t ftime;
  224. {
  225.     int i;
  226.     char *longstring;
  227.  
  228.     longstring = ctime(&ftime);
  229.     for (i = 4; i < 11; ++i)
  230.         (void)putchar(longstring[i]);
  231.  
  232. #define    SIXMONTHS    ((DAYSPERNYEAR / 2) * SECSPERDAY)
  233.     if (f_sectime)
  234.         for (i = 11; i < 24; i++)
  235.             (void)putchar(longstring[i]);
  236.     else if (ftime + SIXMONTHS > time(NULL))
  237.         for (i = 11; i < 16; ++i)
  238.             (void)putchar(longstring[i]);
  239.     else {
  240.         (void)putchar(' ');
  241.         for (i = 20; i < 24; ++i)
  242.             (void)putchar(longstring[i]);
  243.     }
  244.     (void)putchar(' ');
  245. }
  246.  
  247. static int
  248. printtype(mode)
  249.     u_int mode;
  250. {
  251.     switch(mode & S_IFMT) {
  252.     case S_IFDIR:
  253.         (void)putchar('/');
  254.         return (1);
  255.     case S_IFLNK:
  256.         (void)putchar('@');
  257.         return (1);
  258.     case S_IFSOCK:
  259.         (void)putchar('=');
  260.         return (1);
  261.     }
  262.     if (mode & (S_IXUSR | S_IXGRP | S_IXOTH)) {
  263.         (void)putchar('*');
  264.         return (1);
  265.     }
  266.     return (0);
  267. }
  268.  
  269. static void
  270. printlink(p)
  271.     FTSENT *p;
  272. {
  273.     int lnklen;
  274.     char name[MAXPATHLEN + 1], path[MAXPATHLEN + 1];
  275.  
  276.  
  277.     if (p->fts_level == FTS_ROOTLEVEL)
  278.         (void)snprintf(name, sizeof(name), "%s", p->fts_name);
  279.     else 
  280.         (void)snprintf(name, sizeof(name),
  281.             "%s/%s", p->fts_path, p->fts_name);
  282.     if ((lnklen = readlink(name, path, sizeof(name) - 1)) == -1) {
  283.         (void)fprintf(stderr, "\nls: %s: %s\n", name, strerror(errno));
  284.         return;
  285.     }
  286.     path[lnklen] = '\0';
  287.     (void)printf(" -> %s", path);
  288. }
  289.