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 are permitted 9 * provided that the above copyright notice and this paragraph are 10 * duplicated in all such forms and that any documentation, 11 * advertising materials, and other materials related to such 12 * distribution and use acknowledge that the software was developed 13 * by the University of California, Berkeley. The name of the 14 * University may not be used to endorse or promote products derived 15 * from this software without specific prior written permission. 16 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 19 */ 20 21 #ifndef lint 22 static char sccsid[] = "@(#)print.c 5.15 (Berkeley) 08/22/89"; 23 #endif /* not lint */ 24 25 #include <sys/param.h> 26 #include <sys/stat.h> 27 #include <stdio.h> 28 #include <grp.h> 29 #include <pwd.h> 30 #include <utmp.h> 31 #include <tzfile.h> 32 #include "ls.h" 33 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 printlong(stats, num) 45 LS *stats; 46 register int num; 47 { 48 if (f_total) 49 (void)printf("total %lu\n", f_kblocks ? 50 howmany(stats[0].lstat.st_btotal, 2) : 51 stats[0].lstat.st_btotal); 52 for (; num--; ++stats) { 53 if (f_inode) 54 (void)printf("%6lu ", stats->lstat.st_ino); 55 if (f_size) 56 (void)printf("%4ld ", f_kblocks ? 57 howmany(stats->lstat.st_blocks, 2) : 58 stats->lstat.st_blocks); 59 printperms(stats->lstat.st_mode); 60 (void)printf("%3u ", stats->lstat.st_nlink); 61 printowner(stats->lstat.st_uid); 62 if (f_group) 63 printgrp(stats->lstat.st_gid); 64 if (S_ISCHR(stats->lstat.st_mode) || 65 S_ISBLK(stats->lstat.st_mode)) 66 (void)printf("%3d,%4d ", major(stats->lstat.st_rdev), 67 minor(stats->lstat.st_rdev)); 68 else 69 (void)printf("%8ld ", stats->lstat.st_size); 70 if (f_accesstime) 71 printtime(stats->lstat.st_atime); 72 else if (f_statustime) 73 printtime(stats->lstat.st_ctime); 74 else 75 printtime(stats->lstat.st_mtime); 76 (void)printf("%s", stats->name); 77 if (f_type) 78 (void)printtype(stats->lstat.st_mode); 79 if (S_ISLNK(stats->lstat.st_mode)) 80 printlink(stats->name); 81 (void)putchar('\n'); 82 } 83 } 84 85 #define TAB 8 86 87 printcol(stats, num) 88 LS *stats; 89 int num; 90 { 91 extern int termwidth; 92 register int base, chcnt, cnt, col, colwidth; 93 int endcol, numcols, numrows, row; 94 95 colwidth = stats[0].lstat.st_maxlen; 96 if (f_inode) 97 colwidth += 6; 98 if (f_size) 99 colwidth += 5; 100 if (f_type) 101 colwidth += 1; 102 colwidth = (colwidth + TAB) & ~(TAB - 1); 103 104 numcols = termwidth / colwidth; 105 numrows = num / numcols; 106 if (num % numcols) 107 ++numrows; 108 109 if (f_size && f_total) 110 (void)printf("total %lu\n", f_kblocks ? 111 howmany(stats[0].lstat.st_btotal, 2) : 112 stats[0].lstat.st_btotal); 113 for (row = 0; row < numrows; ++row) { 114 endcol = colwidth; 115 for (base = row, chcnt = col = 0; col < numcols; ++col) { 116 chcnt += printaname(stats + base); 117 if ((base += numrows) >= num) 118 break; 119 while ((cnt = (chcnt + TAB & ~(TAB - 1))) <= endcol) { 120 (void)putchar('\t'); 121 chcnt = cnt; 122 } 123 endcol += colwidth; 124 } 125 putchar('\n'); 126 } 127 } 128 129 /* 130 * print [inode] [size] name 131 * return # of characters printed, no trailing characters 132 */ 133 printaname(lp) 134 LS *lp; 135 { 136 int chcnt; 137 138 chcnt = 0; 139 if (f_inode) 140 chcnt += printf("%5lu ", lp->lstat.st_ino); 141 if (f_size) 142 chcnt += printf("%4ld ", f_kblocks ? 143 howmany(lp->lstat.st_blocks, 2) : lp->lstat.st_blocks); 144 chcnt += printf("%s", lp->name); 145 if (f_type) 146 chcnt += printtype(lp->lstat.st_mode); 147 return(chcnt); 148 } 149 150 #define NCACHE 64 /* power of 2 */ 151 #define LSMASK NCACHE - 1 /* bits to store with */ 152 printowner(uid) 153 uid_t uid; 154 { 155 static struct ncache { 156 uid_t uid; 157 char name[UT_NAMESIZE]; 158 } c_uid[NCACHE]; 159 register struct passwd *pw; 160 register struct ncache *cp; 161 162 cp = c_uid + (uid & LSMASK); 163 if (cp->uid != uid || !*cp->name) { 164 /* if can't find owner, print out number instead */ 165 if (!(pw = getpwuid(uid))) { 166 (void)printf("%-*u ", UT_NAMESIZE, uid); 167 return; 168 } 169 cp->uid = uid; 170 (void)strncpy(cp->name, pw->pw_name, UT_NAMESIZE); 171 } 172 (void)printf("%-*.*s ", UT_NAMESIZE, UT_NAMESIZE, cp->name); 173 } 174 175 printgrp(gid) 176 gid_t gid; 177 { 178 static struct ncache { 179 gid_t gid; 180 char name[UT_NAMESIZE]; 181 } c_gid[NCACHE]; 182 register struct group *gr; 183 register struct ncache *cp; 184 185 cp = c_gid + (gid & LSMASK); 186 if (cp->gid != gid || !*cp->name) { 187 /* can't find group, print out number instead */ 188 if (!(gr = getgrgid(gid))) { 189 (void)printf("%-*u ", UT_NAMESIZE, gid); 190 return; 191 } 192 cp->gid = gid; 193 (void)strncpy(cp->name, gr->gr_name, UT_NAMESIZE); 194 } 195 (void)printf("%-*.*s ", UT_NAMESIZE, UT_NAMESIZE, cp->name); 196 } 197 198 printtime(ftime) 199 time_t ftime; 200 { 201 int i; 202 char *longstring, *ctime(); 203 time_t time(); 204 205 longstring = ctime((long *)&ftime); 206 for (i = 4; i < 11; ++i) 207 (void)putchar(longstring[i]); 208 209 #define SIXMONTHS ((DAYSPERNYEAR / 2) * SECSPERDAY) 210 if (ftime + SIXMONTHS > time((time_t *)NULL)) 211 for (i = 11; i < 16; ++i) 212 (void)putchar(longstring[i]); 213 else { 214 (void)putchar(' '); 215 for (i = 20; i < 24; ++i) 216 (void)putchar(longstring[i]); 217 } 218 (void)putchar(' '); 219 } 220 221 /* 222 * do the permissions printing, passed the mode 223 */ 224 printperms(mode) 225 mode_t mode; 226 { 227 /* print type */ 228 switch (mode & S_IFMT) { 229 case S_IFDIR: /* directory */ 230 (void)putchar('d'); 231 break; 232 case S_IFCHR: /* character special */ 233 (void)putchar('c'); 234 break; 235 case S_IFBLK: /* block special */ 236 (void)putchar('b'); 237 break; 238 case S_IFREG: /* regular */ 239 (void)putchar('-'); 240 break; 241 case S_IFLNK: /* symbolic link */ 242 (void)putchar('l'); 243 break; 244 case S_IFSOCK: /* socket */ 245 (void)putchar('s'); 246 break; 247 #ifdef S_IFIFO 248 case S_IFIFO: /* fifo */ 249 (void)putchar('p'); 250 break; 251 #endif 252 default: /* unknown */ 253 (void)putchar('?'); 254 break; 255 } 256 /* usr */ 257 if (mode & S_IRUSR) 258 (void)putchar('r'); 259 else 260 (void)putchar('-'); 261 if (mode & S_IWUSR) 262 (void)putchar('w'); 263 else 264 (void)putchar('-'); 265 switch (mode & (S_IXUSR | S_ISUID)) { 266 case 0: 267 (void)putchar('-'); 268 break; 269 case S_IXUSR: 270 (void)putchar('x'); 271 break; 272 case S_ISUID: 273 (void)putchar('S'); 274 break; 275 case S_IXUSR | S_ISUID: 276 (void)putchar('s'); 277 break; 278 } 279 /* group */ 280 if (mode & S_IRGRP) 281 (void)putchar('r'); 282 else 283 (void)putchar('-'); 284 if (mode & S_IWGRP) 285 (void)putchar('w'); 286 else 287 (void)putchar('-'); 288 switch (mode & (S_IXGRP | S_ISGID)) { 289 case 0: 290 (void)putchar('-'); 291 break; 292 case S_IXGRP: 293 (void)putchar('x'); 294 break; 295 case S_ISGID: 296 (void)putchar('S'); 297 break; 298 case S_IXGRP | S_ISGID: 299 (void)putchar('s'); 300 break; 301 } 302 /* other */ 303 if (mode & S_IROTH) 304 (void)putchar('r'); 305 else 306 (void)putchar('-'); 307 if (mode & S_IWOTH) 308 (void)putchar('w'); 309 else 310 (void)putchar('-'); 311 switch (mode & (S_IXOTH | S_ISVTX)) { 312 case 0: 313 (void)putchar('-'); 314 break; 315 case S_IXOTH: 316 (void)putchar('x'); 317 break; 318 case S_ISVTX: 319 (void)putchar('T'); 320 break; 321 case S_IXOTH | S_ISVTX: 322 (void)putchar('t'); 323 break; 324 } 325 } 326 327 printtype(mode) 328 mode_t mode; 329 { 330 switch(mode & S_IFMT) { 331 case S_IFDIR: 332 (void)putchar('/'); 333 return(1); 334 case S_IFLNK: 335 (void)putchar('@'); 336 return(1); 337 case S_IFSOCK: 338 (void)putchar('='); 339 return(1); 340 } 341 if (mode & (S_IXUSR | S_IXGRP | S_IXOTH)) { 342 (void)putchar('*'); 343 return(1); 344 } 345 return(0); 346 } 347 348 printlink(name) 349 char *name; 350 { 351 int lnklen; 352 char path[MAXPATHLEN + 1], *strerror(); 353 354 if ((lnklen = readlink(name, path, MAXPATHLEN)) == -1) { 355 (void)fprintf(stderr, "\nls: %s: %s\n", name, strerror(errno)); 356 return; 357 } 358 path[lnklen] = '\0'; 359 (void)printf(" -> %s", path); 360 } 361