157195Smuller /*-
257195Smuller * Copyright (c) 1992 Keith Muller.
3*60676Sbostic * Copyright (c) 1992, 1993
4*60676Sbostic * The Regents of the University of California. All rights reserved.
557195Smuller *
657195Smuller * This code is derived from software contributed to Berkeley by
757195Smuller * Keith Muller of the University of California, San Diego.
857195Smuller *
957195Smuller * %sccs.include.redist.c%
1057195Smuller */
1157195Smuller
1257195Smuller #ifndef lint
13*60676Sbostic static char sccsid[] = "@(#)gen_subs.c 8.1 (Berkeley) 05/31/93";
1457195Smuller #endif /* not lint */
1557195Smuller
1657195Smuller #include <sys/types.h>
1757195Smuller #include <sys/time.h>
1857195Smuller #include <sys/stat.h>
1957195Smuller #include <sys/param.h>
2057195Smuller #include <stdio.h>
2157195Smuller #include <ctype.h>
2257195Smuller #include <tzfile.h>
2357195Smuller #include <utmp.h>
2457195Smuller #include <unistd.h>
2557195Smuller #include <stdlib.h>
2657195Smuller #include <string.h>
2757195Smuller #include "pax.h"
2857195Smuller #include "extern.h"
2957195Smuller
3057195Smuller /*
3157195Smuller * a collection of general purpose subroutines used by pax
3257195Smuller */
3357195Smuller
3457195Smuller /*
3557195Smuller * constants used by ls_list() when printing out archive members
3657195Smuller */
3757195Smuller #define MODELEN 20
3857195Smuller #define DATELEN 64
3957195Smuller #define SIXMONTHS ((DAYSPERNYEAR / 2) * SECSPERDAY)
4057195Smuller #define CURFRMT "%b %e %H:%M"
4157195Smuller #define OLDFRMT "%b %e %Y"
4257195Smuller #ifndef UT_NAMESIZE
4357195Smuller #define UT_NAMESIZE 8
4457195Smuller #endif
4557195Smuller #define UT_GRPSIZE 6
4657195Smuller
4757195Smuller /*
4857195Smuller * ls_list()
4957195Smuller * list the members of an archive in ls format
5057195Smuller */
5157195Smuller
5257195Smuller #if __STDC__
5357195Smuller void
ls_list(register ARCHD * arcn,time_t now)5457195Smuller ls_list(register ARCHD *arcn, time_t now)
5557195Smuller #else
5657195Smuller void
5757195Smuller ls_list(arcn, now)
5857195Smuller register ARCHD *arcn;
5957195Smuller time_t now;
6057195Smuller #endif
6157195Smuller {
6257195Smuller register struct stat *sbp;
6357195Smuller char f_mode[MODELEN];
6457195Smuller char f_date[DATELEN];
6557195Smuller char *timefrmt;
6657195Smuller
6757195Smuller /*
6857195Smuller * if not verbose, just print the file name
6957195Smuller */
7057195Smuller if (!vflag) {
7157195Smuller (void)printf("%s\n", arcn->name);
7257195Smuller (void)fflush(stdout);
7357195Smuller return;
7457195Smuller }
7557195Smuller
7657195Smuller /*
7757195Smuller * user wants long mode
7857195Smuller */
7957195Smuller sbp = &(arcn->sb);
8057195Smuller strmode(sbp->st_mode, f_mode);
8157195Smuller
8257195Smuller if (ltmfrmt == NULL) {
8357195Smuller /*
8457195Smuller * no locale specified format. time format based on age
8557195Smuller * compared to the time pax was started.
8657195Smuller */
8757195Smuller if ((sbp->st_mtime + SIXMONTHS) <= now)
8857195Smuller timefrmt = OLDFRMT;
8957195Smuller else
9057195Smuller timefrmt = CURFRMT;
9157195Smuller } else
9257195Smuller timefrmt = ltmfrmt;
9357195Smuller
9457195Smuller /*
9557195Smuller * print file mode, link count, uid, gid and time
9657195Smuller */
9757195Smuller if (strftime(f_date,DATELEN,timefrmt,localtime(&(sbp->st_mtime))) == 0)
9857195Smuller f_date[0] = '\0';
9957195Smuller (void)printf("%s%2u %-*s %-*s ", f_mode, sbp->st_nlink, UT_NAMESIZE,
10057195Smuller name_uid(sbp->st_uid, 1), UT_GRPSIZE,
10157195Smuller name_gid(sbp->st_gid, 1));
10257195Smuller
10357195Smuller /*
10457195Smuller * print device id's for devices, or sizes for other nodes
10557195Smuller */
10657195Smuller if ((arcn->type == PAX_CHR) || (arcn->type == PAX_BLK))
10757195Smuller # ifdef NET2_STAT
10857195Smuller (void)printf("%4u,%4u ", MAJOR(sbp->st_rdev),
10957195Smuller # else
11057195Smuller (void)printf("%4lu,%4lu ", MAJOR(sbp->st_rdev),
11157195Smuller # endif
11257195Smuller MINOR(sbp->st_rdev));
11357195Smuller else {
11457195Smuller # ifdef NET2_STAT
11557195Smuller (void)printf("%9lu ", sbp->st_size);
11657195Smuller # else
11757195Smuller (void)printf("%9qu ", sbp->st_size);
11857195Smuller # endif
11957195Smuller }
12057195Smuller
12157195Smuller /*
12257195Smuller * print name and link info for hard and soft links
12357195Smuller */
12457195Smuller (void)printf("%s %s", f_date, arcn->name);
12557195Smuller if ((arcn->type == PAX_HLK) || (arcn->type == PAX_HRG))
12657195Smuller (void)printf(" == %s\n", arcn->ln_name);
12757195Smuller else if (arcn->type == PAX_SLK)
12857195Smuller (void)printf(" => %s\n", arcn->ln_name);
12957195Smuller else
13057195Smuller (void)putchar('\n');
13157195Smuller (void)fflush(stdout);
13257195Smuller return;
13357195Smuller }
13457195Smuller
13557195Smuller /*
13657195Smuller * tty_ls()
13757195Smuller * print a short summary of file to tty.
13857195Smuller */
13957195Smuller
14057195Smuller #if __STDC__
14157195Smuller void
ls_tty(register ARCHD * arcn)14257195Smuller ls_tty(register ARCHD *arcn)
14357195Smuller #else
14457195Smuller void
14557195Smuller ls_tty(arcn)
14657195Smuller register ARCHD *arcn;
14757195Smuller #endif
14857195Smuller {
14957195Smuller char f_date[DATELEN];
15057195Smuller char f_mode[MODELEN];
15157195Smuller char *timefrmt;
15257195Smuller
15357195Smuller if (ltmfrmt == NULL) {
15457195Smuller /*
15557195Smuller * no locale specified format
15657195Smuller */
15757195Smuller if ((arcn->sb.st_mtime + SIXMONTHS) <= time((time_t *)NULL))
15857195Smuller timefrmt = OLDFRMT;
15957195Smuller else
16057195Smuller timefrmt = CURFRMT;
16157195Smuller } else
16257195Smuller timefrmt = ltmfrmt;
16357195Smuller
16457195Smuller /*
16557195Smuller * convert time to string, and print
16657195Smuller */
16757195Smuller if (strftime(f_date, DATELEN, timefrmt,
16857195Smuller localtime(&(arcn->sb.st_mtime))) == 0)
16957195Smuller f_date[0] = '\0';
17057195Smuller strmode(arcn->sb.st_mode, f_mode);
17157195Smuller tty_prnt("%s%s %s\n", f_mode, f_date, arcn->name);
17257195Smuller return;
17357195Smuller }
17457195Smuller
17557195Smuller /*
17657195Smuller * zf_strncpy()
17757195Smuller * copy src to dest up to len chars (stopping at first '\0'), when src is
17857195Smuller * shorter than len, pads to len with '\0'. big performance win (and
17957195Smuller * a lot easier to code) over strncpy(), then a strlen() then a
18057195Smuller * bzero(). (or doing the bzero() first).
18157195Smuller */
18257195Smuller
18357195Smuller #if __STDC__
18457195Smuller void
zf_strncpy(register char * dest,register char * src,int len)18557195Smuller zf_strncpy(register char *dest, register char *src, int len)
18657195Smuller #else
18757195Smuller void
18857195Smuller zf_strncpy(dest, src, len)
18957195Smuller register char *dest;
19057195Smuller register char *src;
19157195Smuller int len;
19257195Smuller #endif
19357195Smuller {
19457195Smuller register char *stop;
19557195Smuller
19657195Smuller stop = dest + len;
19757195Smuller while ((dest < stop) && (*src != '\0'))
19857195Smuller *dest++ = *src++;
19957195Smuller while (dest < stop)
20057195Smuller *dest++ = '\0';
20157195Smuller return;
20257195Smuller }
20357195Smuller
20457195Smuller /*
20557195Smuller * l_strncpy()
20657195Smuller * copy src to dest up to len chars (stopping at first '\0')
20757195Smuller * Return:
20857195Smuller * number of chars copied. (Note this is a real performance win over
20957195Smuller * doing a strncpy() then a strlen()
21057195Smuller */
21157195Smuller
21257195Smuller #if __STDC__
21357195Smuller int
l_strncpy(register char * dest,register char * src,int len)21457195Smuller l_strncpy(register char *dest, register char *src, int len)
21557195Smuller #else
21657195Smuller int
21757195Smuller l_strncpy(dest, src, len)
21857195Smuller register char *dest;
21957195Smuller register char *src;
22057195Smuller int len;
22157195Smuller #endif
22257195Smuller {
22357195Smuller register char *stop;
22457195Smuller register char *start;
22557195Smuller
22657195Smuller stop = dest + len;
22757195Smuller start = dest;
22857195Smuller while ((dest < stop) && (*src != '\0'))
22957195Smuller *dest++ = *src++;
23057195Smuller if (dest < stop)
23157195Smuller *dest = '\0';
23257195Smuller return(dest - start);
23357195Smuller }
23457195Smuller
23557195Smuller /*
23657195Smuller * asc_ul()
23757195Smuller * convert hex/octal character string into a u_long. We do not have to
23857195Smuller * check for overflow! (the headers in all supported formats are not large
23957195Smuller * enough to create an overflow).
24057195Smuller * NOTE: strings passed to us are NOT TERMINATED.
24157195Smuller * Return:
24257195Smuller * unsigned long value
24357195Smuller */
24457195Smuller
24557195Smuller #if __STDC__
24657195Smuller u_long
asc_ul(register char * str,int len,register int base)24757195Smuller asc_ul(register char *str, int len, register int base)
24857195Smuller #else
24957195Smuller u_long
25057195Smuller asc_ul(str, len, base)
25157195Smuller register char *str;
25257195Smuller int len;
25357195Smuller register int base;
25457195Smuller #endif
25557195Smuller {
25657195Smuller register char *stop;
25757195Smuller u_long tval = 0;
25857195Smuller
25957195Smuller stop = str + len;
26057195Smuller
26157195Smuller /*
26257195Smuller * skip over leading blanks and zeros
26357195Smuller */
26457195Smuller while ((str < stop) && ((*str == ' ') || (*str == '0')))
26557195Smuller ++str;
26657195Smuller
26757195Smuller /*
26857195Smuller * for each valid digit, shift running value (tval) over to next digit
26957195Smuller * and add next digit
27057195Smuller */
27157195Smuller if (base == HEX) {
27257195Smuller while (str < stop) {
27357195Smuller if ((*str >= '0') && (*str <= '9'))
27457195Smuller tval = (tval << 4) + (*str++ - '0');
27557195Smuller else if ((*str >= 'A') && (*str <= 'F'))
27657195Smuller tval = (tval << 4) + 10 + (*str++ - 'A');
27757195Smuller else if ((*str >= 'a') && (*str <= 'f'))
27857195Smuller tval = (tval << 4) + 10 + (*str++ - 'a');
27957195Smuller else
28057195Smuller break;
28157195Smuller }
28257195Smuller } else {
28357195Smuller while ((str < stop) && (*str >= '0') && (*str <= '7'))
28457195Smuller tval = (tval << 3) + (*str++ - '0');
28557195Smuller }
28657195Smuller return(tval);
28757195Smuller }
28857195Smuller
28957195Smuller /*
29057195Smuller * ul_asc()
29157195Smuller * convert an unsigned long into an hex/oct ascii string. pads with LEADING
29257195Smuller * ascii 0's to fill string completely
29357195Smuller * NOTE: the string created is NOT TERMINATED.
29457195Smuller */
29557195Smuller
29657195Smuller #if __STDC__
29757195Smuller int
ul_asc(u_long val,register char * str,register int len,register int base)29857195Smuller ul_asc(u_long val, register char *str, register int len, register int base)
29957195Smuller #else
30057195Smuller int
30157195Smuller ul_asc(val, str, len, base)
30257195Smuller u_long val;
30357195Smuller register char *str;
30457195Smuller register int len;
30557195Smuller register int base;
30657195Smuller #endif
30757195Smuller {
30857195Smuller register char *pt;
30957195Smuller u_long digit;
31057195Smuller
31157195Smuller /*
31257195Smuller * WARNING str is not '\0' terminated by this routine
31357195Smuller */
31457195Smuller pt = str + len - 1;
31557195Smuller
31657195Smuller /*
31757195Smuller * do a tailwise conversion (start at right most end of string to place
31857195Smuller * least significant digit). Keep shifting until conversion value goes
31957195Smuller * to zero (all digits were converted)
32057195Smuller */
32157195Smuller if (base == HEX) {
32257195Smuller while (pt >= str) {
32357195Smuller if ((digit = (val & 0xf)) < 10)
32457195Smuller *pt-- = '0' + (char)digit;
32557195Smuller else
32657195Smuller *pt-- = 'a' + (char)(digit - 10);
32757195Smuller if ((val = (val >> 4)) == (u_long)0)
32857195Smuller break;
32957195Smuller }
33057195Smuller } else {
33157195Smuller while (pt >= str) {
33257195Smuller *pt-- = '0' + (char)(val & 0x7);
33357195Smuller if ((val = (val >> 3)) == (u_long)0)
33457195Smuller break;
33557195Smuller }
33657195Smuller }
33757195Smuller
33857195Smuller /*
33957195Smuller * pad with leading ascii ZEROS. We return -1 if we ran out of space.
34057195Smuller */
34157195Smuller while (pt >= str)
34257195Smuller *pt-- = '0';
34357195Smuller if (val != (u_long)0)
34457195Smuller return(-1);
34557195Smuller return(0);
34657195Smuller }
34757195Smuller
34857195Smuller #ifndef NET2_STAT
34957195Smuller /*
35057195Smuller * asc_uqd()
35157195Smuller * convert hex/octal character string into a u_quad_t. We do not have to
35257195Smuller * check for overflow! (the headers in all supported formats are not large
35357195Smuller * enough to create an overflow).
35457195Smuller * NOTE: strings passed to us are NOT TERMINATED.
35557195Smuller * Return:
35657195Smuller * u_quad_t value
35757195Smuller */
35857195Smuller
35957195Smuller #if __STDC__
36057195Smuller u_quad_t
asc_uqd(register char * str,int len,register int base)36157195Smuller asc_uqd(register char *str, int len, register int base)
36257195Smuller #else
36357195Smuller u_quad_t
36457195Smuller asc_uqd(str, len, base)
36557195Smuller register char *str;
36657195Smuller int len;
36757195Smuller register int base;
36857195Smuller #endif
36957195Smuller {
37057195Smuller register char *stop;
37157195Smuller u_quad_t tval = 0;
37257195Smuller
37357195Smuller stop = str + len;
37457195Smuller
37557195Smuller /*
37657195Smuller * skip over leading blanks and zeros
37757195Smuller */
37857195Smuller while ((str < stop) && ((*str == ' ') || (*str == '0')))
37957195Smuller ++str;
38057195Smuller
38157195Smuller /*
38257195Smuller * for each valid digit, shift running value (tval) over to next digit
38357195Smuller * and add next digit
38457195Smuller */
38557195Smuller if (base == HEX) {
38657195Smuller while (str < stop) {
38757195Smuller if ((*str >= '0') && (*str <= '9'))
38857195Smuller tval = (tval << 4) + (*str++ - '0');
38957195Smuller else if ((*str >= 'A') && (*str <= 'F'))
39057195Smuller tval = (tval << 4) + 10 + (*str++ - 'A');
39157195Smuller else if ((*str >= 'a') && (*str <= 'f'))
39257195Smuller tval = (tval << 4) + 10 + (*str++ - 'a');
39357195Smuller else
39457195Smuller break;
39557195Smuller }
39657195Smuller } else {
39757195Smuller while ((str < stop) && (*str >= '0') && (*str <= '7'))
39857195Smuller tval = (tval << 3) + (*str++ - '0');
39957195Smuller }
40057195Smuller return(tval);
40157195Smuller }
40257195Smuller
40357195Smuller /*
40457195Smuller * uqd_asc()
40557195Smuller * convert an u_quad_t into a hex/oct ascii string. pads with LEADING
40657195Smuller * ascii 0's to fill string completely
40757195Smuller * NOTE: the string created is NOT TERMINATED.
40857195Smuller */
40957195Smuller
41057195Smuller #if __STDC__
41157195Smuller int
uqd_asc(u_quad_t val,register char * str,register int len,register int base)41257195Smuller uqd_asc(u_quad_t val, register char *str, register int len, register int base)
41357195Smuller #else
41457195Smuller int
41557195Smuller uqd_asc(val, str, len, base)
41657195Smuller u_quad_t val;
41757195Smuller register char *str;
41857195Smuller register int len;
41957195Smuller register int base;
42057195Smuller #endif
42157195Smuller {
42257195Smuller register char *pt;
42357195Smuller u_quad_t digit;
42457195Smuller
42557195Smuller /*
42657195Smuller * WARNING str is not '\0' terminated by this routine
42757195Smuller */
42857195Smuller pt = str + len - 1;
42957195Smuller
43057195Smuller /*
43157195Smuller * do a tailwise conversion (start at right most end of string to place
43257195Smuller * least significant digit). Keep shifting until conversion value goes
43357195Smuller * to zero (all digits were converted)
43457195Smuller */
43557195Smuller if (base == HEX) {
43657195Smuller while (pt >= str) {
43757195Smuller if ((digit = (val & 0xf)) < 10)
43857195Smuller *pt-- = '0' + (char)digit;
43957195Smuller else
44057195Smuller *pt-- = 'a' + (char)(digit - 10);
44157195Smuller if ((val = (val >> 4)) == (u_quad_t)0)
44257195Smuller break;
44357195Smuller }
44457195Smuller } else {
44557195Smuller while (pt >= str) {
44657195Smuller *pt-- = '0' + (char)(val & 0x7);
44757195Smuller if ((val = (val >> 3)) == (u_quad_t)0)
44857195Smuller break;
44957195Smuller }
45057195Smuller }
45157195Smuller
45257195Smuller /*
45357195Smuller * pad with leading ascii ZEROS. We return -1 if we ran out of space.
45457195Smuller */
45557195Smuller while (pt >= str)
45657195Smuller *pt-- = '0';
45757195Smuller if (val != (u_quad_t)0)
45857195Smuller return(-1);
45957195Smuller return(0);
46057195Smuller }
46157195Smuller #endif
462