10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
58324SAli.Bahrami@Sun.COM * Common Development and Distribution License (the "License").
68324SAli.Bahrami@Sun.COM * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
210Sstevel@tonic-gate /* Copyright (c) 1988 AT&T */
220Sstevel@tonic-gate /* All Rights Reserved */
230Sstevel@tonic-gate
240Sstevel@tonic-gate /*
25*12792SAli.Bahrami@Oracle.COM * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved.
260Sstevel@tonic-gate */
270Sstevel@tonic-gate
280Sstevel@tonic-gate #include "inc.h"
29*12792SAli.Bahrami@Oracle.COM #include "conv.h"
300Sstevel@tonic-gate
310Sstevel@tonic-gate /*
32*12792SAli.Bahrami@Oracle.COM * Forward declarations
330Sstevel@tonic-gate */
340Sstevel@tonic-gate static void setup(int, char **, Cmd_info *);
35*12792SAli.Bahrami@Oracle.COM static void setcom(Cmd_info *, Cmd_func);
36372Smike_s static void usage(void);
37372Smike_s static void sigexit(int sig);
380Sstevel@tonic-gate static int notfound(Cmd_info *);
390Sstevel@tonic-gate static void check_swap();
400Sstevel@tonic-gate
41*12792SAli.Bahrami@Oracle.COM const char *
_ar_msg(Msg mid)42*12792SAli.Bahrami@Oracle.COM _ar_msg(Msg mid)
43*12792SAli.Bahrami@Oracle.COM {
44*12792SAli.Bahrami@Oracle.COM return (gettext(MSG_ORIG(mid)));
45*12792SAli.Bahrami@Oracle.COM }
46*12792SAli.Bahrami@Oracle.COM
47*12792SAli.Bahrami@Oracle.COM
48*12792SAli.Bahrami@Oracle.COM void
establish_sighandler(void (* handler)())49*12792SAli.Bahrami@Oracle.COM establish_sighandler(void (*handler)())
50*12792SAli.Bahrami@Oracle.COM {
51*12792SAli.Bahrami@Oracle.COM static const int signum[] = {SIGHUP, SIGINT, SIGQUIT, 0};
52*12792SAli.Bahrami@Oracle.COM int i;
53*12792SAli.Bahrami@Oracle.COM
54*12792SAli.Bahrami@Oracle.COM if (handler == SIG_IGN) {
55*12792SAli.Bahrami@Oracle.COM /* Ignore all the specified signals */
56*12792SAli.Bahrami@Oracle.COM for (i = 0; signum[i]; i++)
57*12792SAli.Bahrami@Oracle.COM (void) signal(signum[i], SIG_IGN);
58*12792SAli.Bahrami@Oracle.COM
59*12792SAli.Bahrami@Oracle.COM } else {
60*12792SAli.Bahrami@Oracle.COM /*
61*12792SAli.Bahrami@Oracle.COM * Set any signal that doesn't default to being ignored
62*12792SAli.Bahrami@Oracle.COM * to our signal handler.
63*12792SAli.Bahrami@Oracle.COM */
64*12792SAli.Bahrami@Oracle.COM for (i = 0; signum[i]; i++)
65*12792SAli.Bahrami@Oracle.COM if (signal(signum[i], SIG_IGN) != SIG_IGN)
66*12792SAli.Bahrami@Oracle.COM (void) signal(signum[i], handler);
67*12792SAli.Bahrami@Oracle.COM }
68*12792SAli.Bahrami@Oracle.COM }
690Sstevel@tonic-gate
700Sstevel@tonic-gate int
main(int argc,char ** argv,char * envp[])71*12792SAli.Bahrami@Oracle.COM main(int argc, char **argv, char *envp[])
720Sstevel@tonic-gate {
730Sstevel@tonic-gate int fd;
740Sstevel@tonic-gate Cmd_info *cmd_info;
750Sstevel@tonic-gate int ret;
760Sstevel@tonic-gate char *new = NULL;
770Sstevel@tonic-gate
78*12792SAli.Bahrami@Oracle.COM #ifndef XPG4
79*12792SAli.Bahrami@Oracle.COM /*
80*12792SAli.Bahrami@Oracle.COM * Check for a binary that better fits this architecture.
81*12792SAli.Bahrami@Oracle.COM */
82*12792SAli.Bahrami@Oracle.COM (void) conv_check_native(argv, envp);
830Sstevel@tonic-gate #endif
840Sstevel@tonic-gate
85*12792SAli.Bahrami@Oracle.COM /*
86*12792SAli.Bahrami@Oracle.COM * Establish locale.
87*12792SAli.Bahrami@Oracle.COM */
88*12792SAli.Bahrami@Oracle.COM (void) setlocale(LC_ALL, MSG_ORIG(MSG_STR_EMPTY));
89*12792SAli.Bahrami@Oracle.COM (void) textdomain(MSG_ORIG(MSG_SUNW_OST_SGS));
90*12792SAli.Bahrami@Oracle.COM
91*12792SAli.Bahrami@Oracle.COM /* Allow a graceful exit up until we start to write an archive */
92*12792SAli.Bahrami@Oracle.COM establish_sighandler(sigexit);
93*12792SAli.Bahrami@Oracle.COM
940Sstevel@tonic-gate /*
950Sstevel@tonic-gate * Initialize cmd_info
960Sstevel@tonic-gate */
970Sstevel@tonic-gate cmd_info = (Cmd_info *)calloc(1, sizeof (Cmd_info));
980Sstevel@tonic-gate if (cmd_info == NULL) {
99*12792SAli.Bahrami@Oracle.COM int err = errno;
100*12792SAli.Bahrami@Oracle.COM (void) fprintf(stderr, MSG_INTL(MSG_MALLOC), strerror(err));
1010Sstevel@tonic-gate exit(1);
1020Sstevel@tonic-gate }
1030Sstevel@tonic-gate
1040Sstevel@tonic-gate if (argc < 2)
1050Sstevel@tonic-gate usage();
1060Sstevel@tonic-gate
1070Sstevel@tonic-gate /*
1080Sstevel@tonic-gate * Option handling.
1090Sstevel@tonic-gate */
1100Sstevel@tonic-gate if (argv[1][0] != '-') {
1110Sstevel@tonic-gate new = (char *)malloc(strlen(argv[1]) + 2);
1120Sstevel@tonic-gate if (new == NULL) {
113*12792SAli.Bahrami@Oracle.COM int err = errno;
114*12792SAli.Bahrami@Oracle.COM (void) fprintf(stderr, MSG_INTL(MSG_MALLOC),
115*12792SAli.Bahrami@Oracle.COM strerror(err));
1160Sstevel@tonic-gate exit(1);
1170Sstevel@tonic-gate }
118*12792SAli.Bahrami@Oracle.COM (void) strcpy(new, MSG_ORIG(MSG_STR_HYPHEN));
1190Sstevel@tonic-gate (void) strcat(new, argv[1]);
1200Sstevel@tonic-gate argv[1] = new;
1210Sstevel@tonic-gate }
1220Sstevel@tonic-gate setup(argc, argv, cmd_info);
1230Sstevel@tonic-gate
1240Sstevel@tonic-gate /*
1250Sstevel@tonic-gate * Check SWAP
1260Sstevel@tonic-gate */
127*12792SAli.Bahrami@Oracle.COM if (cmd_info->opt_flgs & z_FLAG)
1280Sstevel@tonic-gate check_swap();
1290Sstevel@tonic-gate
130*12792SAli.Bahrami@Oracle.COM if (cmd_info->comfun == NULL) {
131*12792SAli.Bahrami@Oracle.COM if ((cmd_info->opt_flgs & (d_FLAG | r_FLAG | q_FLAG |
132*12792SAli.Bahrami@Oracle.COM t_FLAG | p_FLAG | m_FLAG | x_FLAG)) == 0) {
133*12792SAli.Bahrami@Oracle.COM (void) fprintf(stderr, MSG_INTL(MSG_USAGE_01));
1340Sstevel@tonic-gate exit(1);
1350Sstevel@tonic-gate }
1360Sstevel@tonic-gate }
1370Sstevel@tonic-gate
138*12792SAli.Bahrami@Oracle.COM cmd_info->modified = (cmd_info->opt_flgs & s_FLAG);
1390Sstevel@tonic-gate fd = getaf(cmd_info);
1400Sstevel@tonic-gate
1410Sstevel@tonic-gate if ((fd == -1) &&
142*12792SAli.Bahrami@Oracle.COM (cmd_info->opt_flgs &
143*12792SAli.Bahrami@Oracle.COM (d_FLAG | m_FLAG | p_FLAG | t_FLAG | x_FLAG)) ||
144*12792SAli.Bahrami@Oracle.COM ((cmd_info->opt_flgs & r_FLAG) &&
145*12792SAli.Bahrami@Oracle.COM (cmd_info->opt_flgs & (a_FLAG | b_FLAG)))) {
146*12792SAli.Bahrami@Oracle.COM (void) fprintf(stderr, MSG_INTL(MSG_NOT_FOUND_AR),
147*12792SAli.Bahrami@Oracle.COM cmd_info->arnam);
1480Sstevel@tonic-gate exit(1);
1490Sstevel@tonic-gate }
1500Sstevel@tonic-gate
1510Sstevel@tonic-gate (*cmd_info->comfun)(cmd_info);
1520Sstevel@tonic-gate if (cmd_info->modified) {
153*12792SAli.Bahrami@Oracle.COM writefile(cmd_info);
1540Sstevel@tonic-gate } else
1550Sstevel@tonic-gate (void) close(fd);
1560Sstevel@tonic-gate
1570Sstevel@tonic-gate ret = notfound(cmd_info);
1580Sstevel@tonic-gate
1590Sstevel@tonic-gate /*
1600Sstevel@tonic-gate * Check SWAP
1610Sstevel@tonic-gate */
162*12792SAli.Bahrami@Oracle.COM if (cmd_info->opt_flgs & z_FLAG)
1630Sstevel@tonic-gate check_swap();
1640Sstevel@tonic-gate
1650Sstevel@tonic-gate free(new);
1660Sstevel@tonic-gate free(cmd_info);
1670Sstevel@tonic-gate return (ret);
1680Sstevel@tonic-gate
1690Sstevel@tonic-gate }
1700Sstevel@tonic-gate
1710Sstevel@tonic-gate /*
172*12792SAli.Bahrami@Oracle.COM * Option handing function.
1730Sstevel@tonic-gate * Using getopt(), following xcu4 convention.
1740Sstevel@tonic-gate */
1750Sstevel@tonic-gate static void
setup(int argc,char * argv[],Cmd_info * cmd_info)1760Sstevel@tonic-gate setup(int argc, char *argv[], Cmd_info *cmd_info)
1770Sstevel@tonic-gate {
1780Sstevel@tonic-gate int Vflag = 0;
1790Sstevel@tonic-gate int c;
1800Sstevel@tonic-gate int usage_err = 0;
1810Sstevel@tonic-gate
182*12792SAli.Bahrami@Oracle.COM while ((c = getopt(argc, argv, MSG_ORIG(MSG_STR_OPTIONS))) != -1) {
1830Sstevel@tonic-gate switch (c) {
1840Sstevel@tonic-gate case 'a': /* position after named archive member file */
1850Sstevel@tonic-gate cmd_info->opt_flgs |= a_FLAG;
1860Sstevel@tonic-gate cmd_info->ponam = trim(optarg);
1870Sstevel@tonic-gate break;
1880Sstevel@tonic-gate case 'b': /* position before named archive member file */
1890Sstevel@tonic-gate case 'i': /* position before named archive member: same as b */
1900Sstevel@tonic-gate cmd_info->opt_flgs |= b_FLAG;
1910Sstevel@tonic-gate cmd_info->ponam = trim(optarg);
1920Sstevel@tonic-gate break;
1930Sstevel@tonic-gate case 'c': /* supress messages */
1940Sstevel@tonic-gate cmd_info->opt_flgs |= c_FLAG;
1950Sstevel@tonic-gate break;
1960Sstevel@tonic-gate case 'd':
1970Sstevel@tonic-gate /*
1980Sstevel@tonic-gate * key operation:
1990Sstevel@tonic-gate * delete files from the archive
2000Sstevel@tonic-gate */
2010Sstevel@tonic-gate setcom(cmd_info, dcmd);
2020Sstevel@tonic-gate cmd_info->opt_flgs |= d_FLAG;
2030Sstevel@tonic-gate break;
204*12792SAli.Bahrami@Oracle.COM case 'l': /* ignored */
2050Sstevel@tonic-gate break;
2060Sstevel@tonic-gate case 'm':
2070Sstevel@tonic-gate /*
2080Sstevel@tonic-gate * key operation:
2090Sstevel@tonic-gate * move files to end of the archive
2100Sstevel@tonic-gate * or as indicated by position flag
2110Sstevel@tonic-gate */
2120Sstevel@tonic-gate setcom(cmd_info, mcmd);
2130Sstevel@tonic-gate cmd_info->opt_flgs |= m_FLAG;
2140Sstevel@tonic-gate break;
2150Sstevel@tonic-gate case 'p':
2160Sstevel@tonic-gate /*
2170Sstevel@tonic-gate * key operation:
2180Sstevel@tonic-gate * print files in the archive
2190Sstevel@tonic-gate */
2200Sstevel@tonic-gate setcom(cmd_info, pcmd);
2210Sstevel@tonic-gate cmd_info->opt_flgs |= p_FLAG;
2220Sstevel@tonic-gate break;
2230Sstevel@tonic-gate case 'q':
2240Sstevel@tonic-gate /*
2250Sstevel@tonic-gate * key operation:
2260Sstevel@tonic-gate * quickly append files to end of the archive
2270Sstevel@tonic-gate */
2280Sstevel@tonic-gate setcom(cmd_info, qcmd);
2290Sstevel@tonic-gate cmd_info->opt_flgs |= q_FLAG;
2300Sstevel@tonic-gate break;
2310Sstevel@tonic-gate case 'r':
2320Sstevel@tonic-gate /*
2330Sstevel@tonic-gate * key operation:
2340Sstevel@tonic-gate * replace or add files to the archive
2350Sstevel@tonic-gate */
2360Sstevel@tonic-gate setcom(cmd_info, rcmd);
2370Sstevel@tonic-gate cmd_info->opt_flgs |= r_FLAG;
2380Sstevel@tonic-gate break;
2390Sstevel@tonic-gate case 's': /* force symbol table regeneration */
2400Sstevel@tonic-gate cmd_info->opt_flgs |= s_FLAG;
2410Sstevel@tonic-gate break;
242*12792SAli.Bahrami@Oracle.COM case 'S': /* Build SYM64 symbol table */
243*12792SAli.Bahrami@Oracle.COM cmd_info->opt_flgs |= S_FLAG;
244*12792SAli.Bahrami@Oracle.COM break;
2450Sstevel@tonic-gate case 't':
2460Sstevel@tonic-gate /*
2470Sstevel@tonic-gate * key operation:
2480Sstevel@tonic-gate * print table of contents
2490Sstevel@tonic-gate */
2500Sstevel@tonic-gate setcom(cmd_info, tcmd);
2510Sstevel@tonic-gate cmd_info->opt_flgs |= t_FLAG;
2520Sstevel@tonic-gate break;
2530Sstevel@tonic-gate case 'u': /* update: change archive dependent on file dates */
2540Sstevel@tonic-gate cmd_info->opt_flgs |= u_FLAG;
2550Sstevel@tonic-gate break;
2560Sstevel@tonic-gate case 'v': /* verbose */
2570Sstevel@tonic-gate cmd_info->opt_flgs |= v_FLAG;
2580Sstevel@tonic-gate break;
2590Sstevel@tonic-gate case 'x':
2600Sstevel@tonic-gate /*
2610Sstevel@tonic-gate * key operation:
2620Sstevel@tonic-gate * extract files from the archive
2630Sstevel@tonic-gate */
2640Sstevel@tonic-gate setcom(cmd_info, xcmd);
2650Sstevel@tonic-gate cmd_info->opt_flgs |= x_FLAG;
2660Sstevel@tonic-gate break;
2670Sstevel@tonic-gate case 'z':
2680Sstevel@tonic-gate cmd_info->opt_flgs |= z_FLAG;
2690Sstevel@tonic-gate break;
2700Sstevel@tonic-gate case 'V':
2710Sstevel@tonic-gate /*
2720Sstevel@tonic-gate * print version information.
2730Sstevel@tonic-gate * adjust command line access accounting
2740Sstevel@tonic-gate */
2750Sstevel@tonic-gate if (Vflag == 0) {
276*12792SAli.Bahrami@Oracle.COM (void) fprintf(stderr,
277*12792SAli.Bahrami@Oracle.COM MSG_ORIG(MSG_FMT_VERSION),
2780Sstevel@tonic-gate (const char *)SGU_PKG,
2790Sstevel@tonic-gate (const char *)SGU_REL);
2800Sstevel@tonic-gate Vflag++;
2810Sstevel@tonic-gate }
2820Sstevel@tonic-gate break;
2830Sstevel@tonic-gate case 'C':
284*12792SAli.Bahrami@Oracle.COM cmd_info->opt_flgs |= C_FLAG;
2850Sstevel@tonic-gate break;
2860Sstevel@tonic-gate case 'M':
287*12792SAli.Bahrami@Oracle.COM /*
288*12792SAli.Bahrami@Oracle.COM * -M was an original undocumented AT&T feature that
289*12792SAli.Bahrami@Oracle.COM * would force the use of mmap() instead of read()
290*12792SAli.Bahrami@Oracle.COM * for pulling file data into the process before
291*12792SAli.Bahrami@Oracle.COM * writing it to the archive. Ignored.
292*12792SAli.Bahrami@Oracle.COM */
2930Sstevel@tonic-gate break;
2940Sstevel@tonic-gate case 'T':
295*12792SAli.Bahrami@Oracle.COM cmd_info->opt_flgs |= T_FLAG;
2960Sstevel@tonic-gate break;
2970Sstevel@tonic-gate case ':':
298*12792SAli.Bahrami@Oracle.COM (void) fprintf(stderr, MSG_INTL(MSG_USAGE_02), optopt);
2990Sstevel@tonic-gate usage_err++;
3000Sstevel@tonic-gate break;
3010Sstevel@tonic-gate case '?':
302*12792SAli.Bahrami@Oracle.COM (void) fprintf(stderr, MSG_INTL(MSG_USAGE_03), optopt);
3030Sstevel@tonic-gate usage_err++;
3040Sstevel@tonic-gate break;
3050Sstevel@tonic-gate }
3060Sstevel@tonic-gate }
3070Sstevel@tonic-gate
3080Sstevel@tonic-gate if (usage_err || argc - optind < 1)
3090Sstevel@tonic-gate usage();
3100Sstevel@tonic-gate
311*12792SAli.Bahrami@Oracle.COM cmd_info->arnam = argv[optind];
3120Sstevel@tonic-gate cmd_info->namv = &argv[optind+1];
3130Sstevel@tonic-gate cmd_info->namc = argc - optind - 1;
3140Sstevel@tonic-gate }
3150Sstevel@tonic-gate
3160Sstevel@tonic-gate
3170Sstevel@tonic-gate /*
3180Sstevel@tonic-gate * Set the function to be called to do the key operation.
3190Sstevel@tonic-gate * Check that only one key is indicated.
3200Sstevel@tonic-gate */
3210Sstevel@tonic-gate static void
setcom(Cmd_info * cmd_info,Cmd_func * fun)322*12792SAli.Bahrami@Oracle.COM setcom(Cmd_info *cmd_info, Cmd_func *fun)
3230Sstevel@tonic-gate {
3240Sstevel@tonic-gate if (cmd_info->comfun != 0) {
325*12792SAli.Bahrami@Oracle.COM (void) fprintf(stderr, MSG_INTL(MSG_USAGE_04));
3260Sstevel@tonic-gate exit(1);
3270Sstevel@tonic-gate }
3280Sstevel@tonic-gate cmd_info->comfun = fun;
3290Sstevel@tonic-gate }
3300Sstevel@tonic-gate
3310Sstevel@tonic-gate static void
usage(void)332372Smike_s usage(void)
3330Sstevel@tonic-gate {
334*12792SAli.Bahrami@Oracle.COM (void) fprintf(stderr, MSG_INTL(MSG_USAGE));
3350Sstevel@tonic-gate exit(1);
3360Sstevel@tonic-gate }
3370Sstevel@tonic-gate
3380Sstevel@tonic-gate /*ARGSUSED0*/
3390Sstevel@tonic-gate static void
sigexit(int sig)340372Smike_s sigexit(int sig)
3410Sstevel@tonic-gate {
3420Sstevel@tonic-gate exit(100);
3430Sstevel@tonic-gate }
3440Sstevel@tonic-gate
3450Sstevel@tonic-gate /* tells the user which of the listed files were not found in the archive */
3460Sstevel@tonic-gate
3470Sstevel@tonic-gate static int
notfound(Cmd_info * cmd_info)3480Sstevel@tonic-gate notfound(Cmd_info *cmd_info)
3490Sstevel@tonic-gate {
350372Smike_s int i, n;
3510Sstevel@tonic-gate
3520Sstevel@tonic-gate n = 0;
3530Sstevel@tonic-gate for (i = 0; i < cmd_info->namc; i++)
3540Sstevel@tonic-gate if (cmd_info->namv[i]) {
355*12792SAli.Bahrami@Oracle.COM (void) fprintf(stderr, MSG_INTL(MSG_NOT_FOUND_FILE),
356*12792SAli.Bahrami@Oracle.COM cmd_info->namv[i]);
3570Sstevel@tonic-gate n++;
3580Sstevel@tonic-gate }
3590Sstevel@tonic-gate return (n);
3600Sstevel@tonic-gate }
3610Sstevel@tonic-gate
3620Sstevel@tonic-gate /*
3630Sstevel@tonic-gate * Debugging info
3640Sstevel@tonic-gate */
3650Sstevel@tonic-gate static void
check_swap(void)366372Smike_s check_swap(void)
3670Sstevel@tonic-gate {
368*12792SAli.Bahrami@Oracle.COM (void) system(MSG_ORIG(MSG_CMD_SWAP));
3690Sstevel@tonic-gate }
370