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 * %sccs.include.redist.c% 9 */ 10 11 #ifndef lint 12 static char sccsid[] = "@(#)print.c 5.27 (Berkeley) 12/12/91"; 13 #endif /* not lint */ 14 15 #include <sys/param.h> 16 #include <sys/stat.h> 17 #include <time.h> 18 #include <errno.h> 19 #include <grp.h> 20 #include <pwd.h> 21 #include <utmp.h> 22 #include <tzfile.h> 23 #include <stdio.h> 24 #include "ls.h" 25 #include "extern.h" 26 27 static int printaname __P((LS *)); 28 static void printlink __P((char *)); 29 static void printtime __P((time_t)); 30 static int printtype __P((u_int)); 31 static char *flags_from_fid __P((long)); 32 33 void 34 printscol(stats, num) 35 register LS *stats; 36 register int num; 37 { 38 for (; num--; ++stats) { 39 (void)printaname(stats); 40 (void)putchar('\n'); 41 } 42 } 43 44 void 45 printlong(stats, num) 46 LS *stats; 47 register int num; 48 { 49 char modep[15], *user_from_uid(), *group_from_gid(); 50 51 if (f_total) 52 (void)printf("total %lu\n", f_kblocks ? 53 howmany(stats[0].lstat.st_btotal, 2) : 54 stats[0].lstat.st_btotal); 55 for (; num--; ++stats) { 56 if (f_inode) 57 (void)printf("%6lu ", stats->lstat.st_ino); 58 if (f_size) 59 (void)printf("%4ld ", f_kblocks ? 60 howmany(stats->lstat.st_blocks, 2) : 61 stats->lstat.st_blocks); 62 (void)strmode(stats->lstat.st_mode, modep); 63 (void)printf("%s %3u %-*s ", modep, stats->lstat.st_nlink, 64 UT_NAMESIZE, user_from_uid(stats->lstat.st_uid, 0)); 65 if (f_group) 66 (void)printf("%-*s ", UT_NAMESIZE, 67 group_from_gid(stats->lstat.st_gid, 0)); 68 if (f_flags) 69 (void)printf("%-*s ", FLAGSWIDTH, 70 flags_from_fid(stats->lstat.st_flags)); 71 if (S_ISCHR(stats->lstat.st_mode) || 72 S_ISBLK(stats->lstat.st_mode)) 73 (void)printf("%3d, %3d ", major(stats->lstat.st_rdev), 74 minor(stats->lstat.st_rdev)); 75 else 76 (void)printf("%8ld ", stats->lstat.st_size); 77 if (f_accesstime) 78 printtime(stats->lstat.st_atime); 79 else if (f_statustime) 80 printtime(stats->lstat.st_ctime); 81 else 82 printtime(stats->lstat.st_mtime); 83 (void)printf("%s", stats->name); 84 if (f_type) 85 (void)printtype(stats->lstat.st_mode); 86 if (S_ISLNK(stats->lstat.st_mode)) 87 printlink(stats->name); 88 (void)putchar('\n'); 89 } 90 } 91 92 #define TAB 8 93 94 void 95 printcol(stats, num) 96 LS *stats; 97 int num; 98 { 99 extern int termwidth; 100 register int base, chcnt, cnt, col, colwidth; 101 int endcol, numcols, numrows, row; 102 103 colwidth = stats[0].lstat.st_maxlen; 104 if (f_inode) 105 colwidth += 6; 106 if (f_size) 107 colwidth += 5; 108 if (f_type) 109 colwidth += 1; 110 111 colwidth = (colwidth + TAB) & ~(TAB - 1); 112 if (termwidth < 2 * colwidth) { 113 printscol(stats, num); 114 return; 115 } 116 117 numcols = termwidth / colwidth; 118 numrows = num / numcols; 119 if (num % numcols) 120 ++numrows; 121 122 if (f_size && f_total) 123 (void)printf("total %lu\n", f_kblocks ? 124 howmany(stats[0].lstat.st_btotal, 2) : 125 stats[0].lstat.st_btotal); 126 for (row = 0; row < numrows; ++row) { 127 endcol = colwidth; 128 for (base = row, chcnt = col = 0; col < numcols; ++col) { 129 chcnt += printaname(stats + base); 130 if ((base += numrows) >= num) 131 break; 132 while ((cnt = (chcnt + TAB & ~(TAB - 1))) <= endcol) { 133 (void)putchar('\t'); 134 chcnt = cnt; 135 } 136 endcol += colwidth; 137 } 138 putchar('\n'); 139 } 140 } 141 142 /* 143 * print [inode] [size] name 144 * return # of characters printed, no trailing characters 145 */ 146 static int 147 printaname(lp) 148 LS *lp; 149 { 150 int chcnt; 151 152 chcnt = 0; 153 if (f_inode) 154 chcnt += printf("%5lu ", lp->lstat.st_ino); 155 if (f_size) 156 chcnt += printf("%4ld ", f_kblocks ? 157 howmany(lp->lstat.st_blocks, 2) : lp->lstat.st_blocks); 158 chcnt += printf("%s", lp->name); 159 if (f_type) 160 chcnt += printtype(lp->lstat.st_mode); 161 return (chcnt); 162 } 163 164 static void 165 printtime(ftime) 166 time_t ftime; 167 { 168 int i; 169 char *longstring; 170 171 longstring = ctime((time_t *)&ftime); 172 for (i = 4; i < 11; ++i) 173 (void)putchar(longstring[i]); 174 175 #define SIXMONTHS ((DAYSPERNYEAR / 2) * SECSPERDAY) 176 if (f_sectime) 177 for (i = 11; i < 24; i++) 178 (void)putchar(longstring[i]); 179 else if (ftime + SIXMONTHS > time((time_t *)NULL)) 180 for (i = 11; i < 16; ++i) 181 (void)putchar(longstring[i]); 182 else { 183 (void)putchar(' '); 184 for (i = 20; i < 24; ++i) 185 (void)putchar(longstring[i]); 186 } 187 (void)putchar(' '); 188 } 189 190 static int 191 printtype(mode) 192 u_int mode; 193 { 194 switch(mode & S_IFMT) { 195 case S_IFDIR: 196 (void)putchar('/'); 197 return (1); 198 case S_IFLNK: 199 (void)putchar('@'); 200 return (1); 201 case S_IFSOCK: 202 (void)putchar('='); 203 return (1); 204 } 205 if (mode & (S_IXUSR | S_IXGRP | S_IXOTH)) { 206 (void)putchar('*'); 207 return (1); 208 } 209 return (0); 210 } 211 212 static void 213 printlink(name) 214 char *name; 215 { 216 int lnklen; 217 char path[MAXPATHLEN + 1]; 218 219 if ((lnklen = readlink(name, path, MAXPATHLEN)) == -1) { 220 (void)fprintf(stderr, "\nls: %s: %s\n", name, strerror(errno)); 221 return; 222 } 223 path[lnklen] = '\0'; 224 (void)printf(" -> %s", path); 225 } 226 227 static char * 228 flags_from_fid(flags) 229 long flags; 230 { 231 static char buf[FLAGSWIDTH + 1]; 232 int size; 233 234 size = FLAGSWIDTH; 235 buf[0] = '\0'; 236 if (size && (flags & NODUMP)) { 237 strncat(buf, "nodump", size); 238 size -= 6; 239 } else { 240 strncat(buf, "dump", size); 241 size -= 4; 242 } 243 if (size && (flags & IMMUTABLE)) { 244 strncat(buf, ",nochg", size); 245 size -= 6; 246 } 247 if (size && (flags & ARCHIVED)) { 248 strncat(buf, ",arch", size); 249 size -= 5; 250 } 251 return (buf); 252 } 253