1*57195Smuller /*- 2*57195Smuller * Copyright (c) 1992 Keith Muller. 3*57195Smuller * Copyright (c) 1992 The Regents of the University of California. 4*57195Smuller * All rights reserved. 5*57195Smuller * 6*57195Smuller * This code is derived from software contributed to Berkeley by 7*57195Smuller * Keith Muller of the University of California, San Diego. 8*57195Smuller * 9*57195Smuller * %sccs.include.redist.c% 10*57195Smuller */ 11*57195Smuller 12*57195Smuller #ifndef lint 13*57195Smuller static char sccsid[] = "@(#)gen_subs.c 1.1 (Berkeley) 12/17/92"; 14*57195Smuller #endif /* not lint */ 15*57195Smuller 16*57195Smuller #include <sys/types.h> 17*57195Smuller #include <sys/time.h> 18*57195Smuller #include <sys/stat.h> 19*57195Smuller #include <sys/param.h> 20*57195Smuller #include <stdio.h> 21*57195Smuller #include <ctype.h> 22*57195Smuller #include <tzfile.h> 23*57195Smuller #include <utmp.h> 24*57195Smuller #include <unistd.h> 25*57195Smuller #include <stdlib.h> 26*57195Smuller #include <string.h> 27*57195Smuller #include "pax.h" 28*57195Smuller #include "extern.h" 29*57195Smuller 30*57195Smuller /* 31*57195Smuller * a collection of general purpose subroutines used by pax 32*57195Smuller */ 33*57195Smuller 34*57195Smuller /* 35*57195Smuller * constants used by ls_list() when printing out archive members 36*57195Smuller */ 37*57195Smuller #define MODELEN 20 38*57195Smuller #define DATELEN 64 39*57195Smuller #define SIXMONTHS ((DAYSPERNYEAR / 2) * SECSPERDAY) 40*57195Smuller #define CURFRMT "%b %e %H:%M" 41*57195Smuller #define OLDFRMT "%b %e %Y" 42*57195Smuller #ifndef UT_NAMESIZE 43*57195Smuller #define UT_NAMESIZE 8 44*57195Smuller #endif 45*57195Smuller #define UT_GRPSIZE 6 46*57195Smuller 47*57195Smuller /* 48*57195Smuller * ls_list() 49*57195Smuller * list the members of an archive in ls format 50*57195Smuller */ 51*57195Smuller 52*57195Smuller #if __STDC__ 53*57195Smuller void 54*57195Smuller ls_list(register ARCHD *arcn, time_t now) 55*57195Smuller #else 56*57195Smuller void 57*57195Smuller ls_list(arcn, now) 58*57195Smuller register ARCHD *arcn; 59*57195Smuller time_t now; 60*57195Smuller #endif 61*57195Smuller { 62*57195Smuller register struct stat *sbp; 63*57195Smuller char f_mode[MODELEN]; 64*57195Smuller char f_date[DATELEN]; 65*57195Smuller char *timefrmt; 66*57195Smuller 67*57195Smuller /* 68*57195Smuller * if not verbose, just print the file name 69*57195Smuller */ 70*57195Smuller if (!vflag) { 71*57195Smuller (void)printf("%s\n", arcn->name); 72*57195Smuller (void)fflush(stdout); 73*57195Smuller return; 74*57195Smuller } 75*57195Smuller 76*57195Smuller /* 77*57195Smuller * user wants long mode 78*57195Smuller */ 79*57195Smuller sbp = &(arcn->sb); 80*57195Smuller strmode(sbp->st_mode, f_mode); 81*57195Smuller 82*57195Smuller if (ltmfrmt == NULL) { 83*57195Smuller /* 84*57195Smuller * no locale specified format. time format based on age 85*57195Smuller * compared to the time pax was started. 86*57195Smuller */ 87*57195Smuller if ((sbp->st_mtime + SIXMONTHS) <= now) 88*57195Smuller timefrmt = OLDFRMT; 89*57195Smuller else 90*57195Smuller timefrmt = CURFRMT; 91*57195Smuller } else 92*57195Smuller timefrmt = ltmfrmt; 93*57195Smuller 94*57195Smuller /* 95*57195Smuller * print file mode, link count, uid, gid and time 96*57195Smuller */ 97*57195Smuller if (strftime(f_date,DATELEN,timefrmt,localtime(&(sbp->st_mtime))) == 0) 98*57195Smuller f_date[0] = '\0'; 99*57195Smuller (void)printf("%s%2u %-*s %-*s ", f_mode, sbp->st_nlink, UT_NAMESIZE, 100*57195Smuller name_uid(sbp->st_uid, 1), UT_GRPSIZE, 101*57195Smuller name_gid(sbp->st_gid, 1)); 102*57195Smuller 103*57195Smuller /* 104*57195Smuller * print device id's for devices, or sizes for other nodes 105*57195Smuller */ 106*57195Smuller if ((arcn->type == PAX_CHR) || (arcn->type == PAX_BLK)) 107*57195Smuller # ifdef NET2_STAT 108*57195Smuller (void)printf("%4u,%4u ", MAJOR(sbp->st_rdev), 109*57195Smuller # else 110*57195Smuller (void)printf("%4lu,%4lu ", MAJOR(sbp->st_rdev), 111*57195Smuller # endif 112*57195Smuller MINOR(sbp->st_rdev)); 113*57195Smuller else { 114*57195Smuller # ifdef NET2_STAT 115*57195Smuller (void)printf("%9lu ", sbp->st_size); 116*57195Smuller # else 117*57195Smuller (void)printf("%9qu ", sbp->st_size); 118*57195Smuller # endif 119*57195Smuller } 120*57195Smuller 121*57195Smuller /* 122*57195Smuller * print name and link info for hard and soft links 123*57195Smuller */ 124*57195Smuller (void)printf("%s %s", f_date, arcn->name); 125*57195Smuller if ((arcn->type == PAX_HLK) || (arcn->type == PAX_HRG)) 126*57195Smuller (void)printf(" == %s\n", arcn->ln_name); 127*57195Smuller else if (arcn->type == PAX_SLK) 128*57195Smuller (void)printf(" => %s\n", arcn->ln_name); 129*57195Smuller else 130*57195Smuller (void)putchar('\n'); 131*57195Smuller (void)fflush(stdout); 132*57195Smuller return; 133*57195Smuller } 134*57195Smuller 135*57195Smuller /* 136*57195Smuller * tty_ls() 137*57195Smuller * print a short summary of file to tty. 138*57195Smuller */ 139*57195Smuller 140*57195Smuller #if __STDC__ 141*57195Smuller void 142*57195Smuller ls_tty(register ARCHD *arcn) 143*57195Smuller #else 144*57195Smuller void 145*57195Smuller ls_tty(arcn) 146*57195Smuller register ARCHD *arcn; 147*57195Smuller #endif 148*57195Smuller { 149*57195Smuller char f_date[DATELEN]; 150*57195Smuller char f_mode[MODELEN]; 151*57195Smuller char *timefrmt; 152*57195Smuller 153*57195Smuller if (ltmfrmt == NULL) { 154*57195Smuller /* 155*57195Smuller * no locale specified format 156*57195Smuller */ 157*57195Smuller if ((arcn->sb.st_mtime + SIXMONTHS) <= time((time_t *)NULL)) 158*57195Smuller timefrmt = OLDFRMT; 159*57195Smuller else 160*57195Smuller timefrmt = CURFRMT; 161*57195Smuller } else 162*57195Smuller timefrmt = ltmfrmt; 163*57195Smuller 164*57195Smuller /* 165*57195Smuller * convert time to string, and print 166*57195Smuller */ 167*57195Smuller if (strftime(f_date, DATELEN, timefrmt, 168*57195Smuller localtime(&(arcn->sb.st_mtime))) == 0) 169*57195Smuller f_date[0] = '\0'; 170*57195Smuller strmode(arcn->sb.st_mode, f_mode); 171*57195Smuller tty_prnt("%s%s %s\n", f_mode, f_date, arcn->name); 172*57195Smuller return; 173*57195Smuller } 174*57195Smuller 175*57195Smuller /* 176*57195Smuller * zf_strncpy() 177*57195Smuller * copy src to dest up to len chars (stopping at first '\0'), when src is 178*57195Smuller * shorter than len, pads to len with '\0'. big performance win (and 179*57195Smuller * a lot easier to code) over strncpy(), then a strlen() then a 180*57195Smuller * bzero(). (or doing the bzero() first). 181*57195Smuller */ 182*57195Smuller 183*57195Smuller #if __STDC__ 184*57195Smuller void 185*57195Smuller zf_strncpy(register char *dest, register char *src, int len) 186*57195Smuller #else 187*57195Smuller void 188*57195Smuller zf_strncpy(dest, src, len) 189*57195Smuller register char *dest; 190*57195Smuller register char *src; 191*57195Smuller int len; 192*57195Smuller #endif 193*57195Smuller { 194*57195Smuller register char *stop; 195*57195Smuller 196*57195Smuller stop = dest + len; 197*57195Smuller while ((dest < stop) && (*src != '\0')) 198*57195Smuller *dest++ = *src++; 199*57195Smuller while (dest < stop) 200*57195Smuller *dest++ = '\0'; 201*57195Smuller return; 202*57195Smuller } 203*57195Smuller 204*57195Smuller /* 205*57195Smuller * l_strncpy() 206*57195Smuller * copy src to dest up to len chars (stopping at first '\0') 207*57195Smuller * Return: 208*57195Smuller * number of chars copied. (Note this is a real performance win over 209*57195Smuller * doing a strncpy() then a strlen() 210*57195Smuller */ 211*57195Smuller 212*57195Smuller #if __STDC__ 213*57195Smuller int 214*57195Smuller l_strncpy(register char *dest, register char *src, int len) 215*57195Smuller #else 216*57195Smuller int 217*57195Smuller l_strncpy(dest, src, len) 218*57195Smuller register char *dest; 219*57195Smuller register char *src; 220*57195Smuller int len; 221*57195Smuller #endif 222*57195Smuller { 223*57195Smuller register char *stop; 224*57195Smuller register char *start; 225*57195Smuller 226*57195Smuller stop = dest + len; 227*57195Smuller start = dest; 228*57195Smuller while ((dest < stop) && (*src != '\0')) 229*57195Smuller *dest++ = *src++; 230*57195Smuller if (dest < stop) 231*57195Smuller *dest = '\0'; 232*57195Smuller return(dest - start); 233*57195Smuller } 234*57195Smuller 235*57195Smuller /* 236*57195Smuller * asc_ul() 237*57195Smuller * convert hex/octal character string into a u_long. We do not have to 238*57195Smuller * check for overflow! (the headers in all supported formats are not large 239*57195Smuller * enough to create an overflow). 240*57195Smuller * NOTE: strings passed to us are NOT TERMINATED. 241*57195Smuller * Return: 242*57195Smuller * unsigned long value 243*57195Smuller */ 244*57195Smuller 245*57195Smuller #if __STDC__ 246*57195Smuller u_long 247*57195Smuller asc_ul(register char *str, int len, register int base) 248*57195Smuller #else 249*57195Smuller u_long 250*57195Smuller asc_ul(str, len, base) 251*57195Smuller register char *str; 252*57195Smuller int len; 253*57195Smuller register int base; 254*57195Smuller #endif 255*57195Smuller { 256*57195Smuller register char *stop; 257*57195Smuller u_long tval = 0; 258*57195Smuller 259*57195Smuller stop = str + len; 260*57195Smuller 261*57195Smuller /* 262*57195Smuller * skip over leading blanks and zeros 263*57195Smuller */ 264*57195Smuller while ((str < stop) && ((*str == ' ') || (*str == '0'))) 265*57195Smuller ++str; 266*57195Smuller 267*57195Smuller /* 268*57195Smuller * for each valid digit, shift running value (tval) over to next digit 269*57195Smuller * and add next digit 270*57195Smuller */ 271*57195Smuller if (base == HEX) { 272*57195Smuller while (str < stop) { 273*57195Smuller if ((*str >= '0') && (*str <= '9')) 274*57195Smuller tval = (tval << 4) + (*str++ - '0'); 275*57195Smuller else if ((*str >= 'A') && (*str <= 'F')) 276*57195Smuller tval = (tval << 4) + 10 + (*str++ - 'A'); 277*57195Smuller else if ((*str >= 'a') && (*str <= 'f')) 278*57195Smuller tval = (tval << 4) + 10 + (*str++ - 'a'); 279*57195Smuller else 280*57195Smuller break; 281*57195Smuller } 282*57195Smuller } else { 283*57195Smuller while ((str < stop) && (*str >= '0') && (*str <= '7')) 284*57195Smuller tval = (tval << 3) + (*str++ - '0'); 285*57195Smuller } 286*57195Smuller return(tval); 287*57195Smuller } 288*57195Smuller 289*57195Smuller /* 290*57195Smuller * ul_asc() 291*57195Smuller * convert an unsigned long into an hex/oct ascii string. pads with LEADING 292*57195Smuller * ascii 0's to fill string completely 293*57195Smuller * NOTE: the string created is NOT TERMINATED. 294*57195Smuller */ 295*57195Smuller 296*57195Smuller #if __STDC__ 297*57195Smuller int 298*57195Smuller ul_asc(u_long val, register char *str, register int len, register int base) 299*57195Smuller #else 300*57195Smuller int 301*57195Smuller ul_asc(val, str, len, base) 302*57195Smuller u_long val; 303*57195Smuller register char *str; 304*57195Smuller register int len; 305*57195Smuller register int base; 306*57195Smuller #endif 307*57195Smuller { 308*57195Smuller register char *pt; 309*57195Smuller u_long digit; 310*57195Smuller 311*57195Smuller /* 312*57195Smuller * WARNING str is not '\0' terminated by this routine 313*57195Smuller */ 314*57195Smuller pt = str + len - 1; 315*57195Smuller 316*57195Smuller /* 317*57195Smuller * do a tailwise conversion (start at right most end of string to place 318*57195Smuller * least significant digit). Keep shifting until conversion value goes 319*57195Smuller * to zero (all digits were converted) 320*57195Smuller */ 321*57195Smuller if (base == HEX) { 322*57195Smuller while (pt >= str) { 323*57195Smuller if ((digit = (val & 0xf)) < 10) 324*57195Smuller *pt-- = '0' + (char)digit; 325*57195Smuller else 326*57195Smuller *pt-- = 'a' + (char)(digit - 10); 327*57195Smuller if ((val = (val >> 4)) == (u_long)0) 328*57195Smuller break; 329*57195Smuller } 330*57195Smuller } else { 331*57195Smuller while (pt >= str) { 332*57195Smuller *pt-- = '0' + (char)(val & 0x7); 333*57195Smuller if ((val = (val >> 3)) == (u_long)0) 334*57195Smuller break; 335*57195Smuller } 336*57195Smuller } 337*57195Smuller 338*57195Smuller /* 339*57195Smuller * pad with leading ascii ZEROS. We return -1 if we ran out of space. 340*57195Smuller */ 341*57195Smuller while (pt >= str) 342*57195Smuller *pt-- = '0'; 343*57195Smuller if (val != (u_long)0) 344*57195Smuller return(-1); 345*57195Smuller return(0); 346*57195Smuller } 347*57195Smuller 348*57195Smuller #ifndef NET2_STAT 349*57195Smuller /* 350*57195Smuller * asc_uqd() 351*57195Smuller * convert hex/octal character string into a u_quad_t. We do not have to 352*57195Smuller * check for overflow! (the headers in all supported formats are not large 353*57195Smuller * enough to create an overflow). 354*57195Smuller * NOTE: strings passed to us are NOT TERMINATED. 355*57195Smuller * Return: 356*57195Smuller * u_quad_t value 357*57195Smuller */ 358*57195Smuller 359*57195Smuller #if __STDC__ 360*57195Smuller u_quad_t 361*57195Smuller asc_uqd(register char *str, int len, register int base) 362*57195Smuller #else 363*57195Smuller u_quad_t 364*57195Smuller asc_uqd(str, len, base) 365*57195Smuller register char *str; 366*57195Smuller int len; 367*57195Smuller register int base; 368*57195Smuller #endif 369*57195Smuller { 370*57195Smuller register char *stop; 371*57195Smuller u_quad_t tval = 0; 372*57195Smuller 373*57195Smuller stop = str + len; 374*57195Smuller 375*57195Smuller /* 376*57195Smuller * skip over leading blanks and zeros 377*57195Smuller */ 378*57195Smuller while ((str < stop) && ((*str == ' ') || (*str == '0'))) 379*57195Smuller ++str; 380*57195Smuller 381*57195Smuller /* 382*57195Smuller * for each valid digit, shift running value (tval) over to next digit 383*57195Smuller * and add next digit 384*57195Smuller */ 385*57195Smuller if (base == HEX) { 386*57195Smuller while (str < stop) { 387*57195Smuller if ((*str >= '0') && (*str <= '9')) 388*57195Smuller tval = (tval << 4) + (*str++ - '0'); 389*57195Smuller else if ((*str >= 'A') && (*str <= 'F')) 390*57195Smuller tval = (tval << 4) + 10 + (*str++ - 'A'); 391*57195Smuller else if ((*str >= 'a') && (*str <= 'f')) 392*57195Smuller tval = (tval << 4) + 10 + (*str++ - 'a'); 393*57195Smuller else 394*57195Smuller break; 395*57195Smuller } 396*57195Smuller } else { 397*57195Smuller while ((str < stop) && (*str >= '0') && (*str <= '7')) 398*57195Smuller tval = (tval << 3) + (*str++ - '0'); 399*57195Smuller } 400*57195Smuller return(tval); 401*57195Smuller } 402*57195Smuller 403*57195Smuller /* 404*57195Smuller * uqd_asc() 405*57195Smuller * convert an u_quad_t into a hex/oct ascii string. pads with LEADING 406*57195Smuller * ascii 0's to fill string completely 407*57195Smuller * NOTE: the string created is NOT TERMINATED. 408*57195Smuller */ 409*57195Smuller 410*57195Smuller #if __STDC__ 411*57195Smuller int 412*57195Smuller uqd_asc(u_quad_t val, register char *str, register int len, register int base) 413*57195Smuller #else 414*57195Smuller int 415*57195Smuller uqd_asc(val, str, len, base) 416*57195Smuller u_quad_t val; 417*57195Smuller register char *str; 418*57195Smuller register int len; 419*57195Smuller register int base; 420*57195Smuller #endif 421*57195Smuller { 422*57195Smuller register char *pt; 423*57195Smuller u_quad_t digit; 424*57195Smuller 425*57195Smuller /* 426*57195Smuller * WARNING str is not '\0' terminated by this routine 427*57195Smuller */ 428*57195Smuller pt = str + len - 1; 429*57195Smuller 430*57195Smuller /* 431*57195Smuller * do a tailwise conversion (start at right most end of string to place 432*57195Smuller * least significant digit). Keep shifting until conversion value goes 433*57195Smuller * to zero (all digits were converted) 434*57195Smuller */ 435*57195Smuller if (base == HEX) { 436*57195Smuller while (pt >= str) { 437*57195Smuller if ((digit = (val & 0xf)) < 10) 438*57195Smuller *pt-- = '0' + (char)digit; 439*57195Smuller else 440*57195Smuller *pt-- = 'a' + (char)(digit - 10); 441*57195Smuller if ((val = (val >> 4)) == (u_quad_t)0) 442*57195Smuller break; 443*57195Smuller } 444*57195Smuller } else { 445*57195Smuller while (pt >= str) { 446*57195Smuller *pt-- = '0' + (char)(val & 0x7); 447*57195Smuller if ((val = (val >> 3)) == (u_quad_t)0) 448*57195Smuller break; 449*57195Smuller } 450*57195Smuller } 451*57195Smuller 452*57195Smuller /* 453*57195Smuller * pad with leading ascii ZEROS. We return -1 if we ran out of space. 454*57195Smuller */ 455*57195Smuller while (pt >= str) 456*57195Smuller *pt-- = '0'; 457*57195Smuller if (val != (u_quad_t)0) 458*57195Smuller return(-1); 459*57195Smuller return(0); 460*57195Smuller } 461*57195Smuller #endif 462