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