xref: /illumos-gate/usr/src/cmd/sgs/ar/common/main.c (revision b55148877d473978f0b46d593fd6213fa526fcc5)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*	Copyright (c) 1988 AT&T	*/
23 /*	  All Rights Reserved  	*/
24 
25 /*
26  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
27  * Use is subject to license terms.
28  */
29 
30 #pragma ident	"%Z%%M%	%I%	%E% SMI"
31 
32 #include "inc.h"
33 #include "extern.h"
34 
35 static char *arnam;
36 
37 /*
38  * Function prototypes
39  */
40 static void setup(int, char **, Cmd_info *);
41 static void setcom(Cmd_info *, int (*)());
42 static void usage(void);
43 static void sigexit(int sig);
44 static int notfound(Cmd_info *);
45 static void check_swap();
46 
47 #define	OPTSTR	":a:b:i:vucsrdxtplmqVCTzM"
48 
49 int
50 main(int argc, char **argv)
51 {
52 	int i;
53 	int fd;
54 	Cmd_info *cmd_info;
55 	int ret;
56 	char *new = NULL;
57 	char *data = NULL;
58 
59 	(void) setlocale(LC_ALL, "");
60 #if !defined(TEXT_DOMAIN)	/* Should be defined by cc -D */
61 #define	TEXT_DOMAIN "SYS_TEST"	/* Use this only if it weren't */
62 #endif
63 	(void) textdomain(TEXT_DOMAIN);
64 
65 	for (i = 0; signum[i]; i++)
66 		if (signal(signum[i], SIG_IGN) != SIG_IGN)
67 			(void) signal(signum[i], sigexit);
68 	/*
69 	 * Initialize cmd_info
70 	 */
71 	cmd_info = (Cmd_info *)calloc(1, sizeof (Cmd_info));
72 	if (cmd_info == NULL) {
73 		error_message(MALLOC_ERROR, PLAIN_ERROR, (char *)0);
74 		exit(1);
75 	}
76 
77 	if (argc < 2)
78 		usage();
79 
80 	/*
81 	 * Option handling.
82 	 */
83 	if (argv[1][0] != '-') {
84 		new = (char *)malloc(strlen(argv[1]) + 2);
85 		if (new == NULL) {
86 			error_message(MALLOC_ERROR, PLAIN_ERROR, (char *)0);
87 			exit(1);
88 		}
89 		(void) strcpy(new, "-");
90 		(void) strcat(new, argv[1]);
91 		argv[1] = new;
92 	}
93 	setup(argc, argv, cmd_info);
94 
95 	/*
96 	 * Check SWAP
97 	 */
98 	if (opt_FLAG((cmd_info), z_FLAG))
99 		check_swap();
100 
101 	if (cmd_info->comfun == 0) {
102 		if (!(opt_FLAG((cmd_info), d_FLAG) ||
103 		    opt_FLAG(cmd_info, r_FLAG) ||
104 		    opt_FLAG(cmd_info, q_FLAG) || opt_FLAG(cmd_info, t_FLAG) ||
105 		    opt_FLAG(cmd_info, p_FLAG) || opt_FLAG(cmd_info, m_FLAG) ||
106 		    opt_FLAG(cmd_info, x_FLAG))) {
107 			error_message(USAGE_01_ERROR, PLAIN_ERROR, (char *)0);
108 			exit(1);
109 		}
110 	}
111 
112 	cmd_info->modified = opt_FLAG(cmd_info, s_FLAG);
113 	fd = getaf(cmd_info);
114 
115 	if ((fd == -1) &&
116 	    (opt_FLAG(cmd_info, d_FLAG) || opt_FLAG(cmd_info, t_FLAG) ||
117 	    opt_FLAG(cmd_info, p_FLAG) || opt_FLAG(cmd_info, m_FLAG) ||
118 	    opt_FLAG(cmd_info, x_FLAG) ||
119 	    (opt_FLAG(cmd_info, r_FLAG) && (opt_FLAG(cmd_info, a_FLAG) ||
120 	    opt_FLAG(cmd_info, b_FLAG))))) {
121 		error_message(NOT_FOUND_01_ERROR,
122 		PLAIN_ERROR, (char *)0, arnam);
123 		exit(1);
124 	}
125 
126 	(*cmd_info->comfun)(cmd_info);
127 #ifdef BROWSER
128 	sb_data.fd = NULL;
129 	sb_data.failed = 0;
130 #endif
131 	if (cmd_info->modified) {
132 		data = writefile(cmd_info);
133 	} else
134 		(void) close(fd);
135 #ifdef BROWSER
136 	sbfocus_close(&sb_data);
137 #endif
138 
139 	ret = notfound(cmd_info);
140 
141 	/*
142 	 * Check SWAP
143 	 */
144 	if (opt_FLAG((cmd_info), z_FLAG))
145 		check_swap();
146 
147 	free(data);
148 	free(new);
149 	free(cmd_info);
150 	return (ret);
151 
152 }
153 
154 /*
155  * Option hadning function.
156  *	Using getopt(), following xcu4 convention.
157  */
158 static void
159 setup(int argc, char *argv[], Cmd_info *cmd_info)
160 {
161 	int Vflag = 0;
162 	int c;
163 	int usage_err = 0;
164 
165 	while ((c = getopt(argc, argv, OPTSTR)) != -1) {
166 		switch (c) {
167 		case 'a': /* position after named archive member file */
168 			cmd_info->opt_flgs |= a_FLAG;
169 			cmd_info->ponam = trim(optarg);
170 			break;
171 		case 'b': /* position before named archive member file */
172 		case 'i': /* position before named archive member: same as b */
173 			cmd_info->opt_flgs |= b_FLAG;
174 			cmd_info->ponam = trim(optarg);
175 			break;
176 		case 'c': /* supress messages */
177 			cmd_info->opt_flgs |= c_FLAG;
178 			break;
179 		case 'd':
180 			/*
181 			 * key operation:
182 			 * delete files from the archive
183 			 */
184 			setcom(cmd_info, dcmd);
185 			cmd_info->opt_flgs |= d_FLAG;
186 			break;
187 		case 'l': /* temporary directory */
188 			cmd_info->opt_flgs |= l_FLAG;
189 			break;
190 		case 'm':
191 			/*
192 			 * key operation:
193 			 * move files to end of the archive
194 			 * or as indicated by position flag
195 			 */
196 			setcom(cmd_info, mcmd);
197 			cmd_info->opt_flgs |= m_FLAG;
198 			break;
199 		case 'p':
200 			/*
201 			 * key operation:
202 			 * print files in the archive
203 			 */
204 			setcom(cmd_info, pcmd);
205 			cmd_info->opt_flgs |= p_FLAG;
206 			break;
207 		case 'q':
208 			/*
209 			 * key operation:
210 			 * quickly append files to end of the archive
211 			 */
212 			setcom(cmd_info, qcmd);
213 			cmd_info->opt_flgs |= q_FLAG;
214 			break;
215 		case 'r':
216 			/*
217 			 * key operation:
218 			 * replace or add files to the archive
219 			 */
220 			setcom(cmd_info, rcmd);
221 			cmd_info->opt_flgs |= r_FLAG;
222 			break;
223 		case 's': /* force symbol table regeneration */
224 			cmd_info->opt_flgs |= s_FLAG;
225 			break;
226 		case 't':
227 			/*
228 			 * key operation:
229 			 * print table of contents
230 			 */
231 			setcom(cmd_info, tcmd);
232 			cmd_info->opt_flgs |= t_FLAG;
233 			break;
234 		case 'u': /* update: change archive dependent on file dates */
235 			cmd_info->opt_flgs |= u_FLAG;
236 			break;
237 		case 'v': /* verbose */
238 			cmd_info->opt_flgs |= v_FLAG;
239 			break;
240 		case 'x':
241 			/*
242 			 * key operation:
243 			 * extract files from the archive
244 			 */
245 			setcom(cmd_info, xcmd);
246 			cmd_info->opt_flgs |= x_FLAG;
247 			break;
248 		case 'z':
249 			cmd_info->opt_flgs |= z_FLAG;
250 			break;
251 		case 'V':
252 			/*
253 			 * print version information.
254 			 * adjust command line access accounting
255 			 */
256 			if (Vflag == 0) {
257 				(void) fprintf(stderr, "ar: %s %s\n",
258 				    (const char *)SGU_PKG,
259 				    (const char *)SGU_REL);
260 					Vflag++;
261 			}
262 			break;
263 		case 'C':
264 			cmd_info->OPT_flgs |= C_FLAG;
265 			break;
266 		case 'M':
267 			cmd_info->OPT_flgs |= M_FLAG;
268 			break;
269 		case 'T':
270 			cmd_info->OPT_flgs |= T_FLAG;
271 			break;
272 		case ':':
273 			error_message(USAGE_02_ERROR,
274 			PLAIN_ERROR, (char *)0, optopt);
275 			usage_err++;
276 			break;
277 		case '?':
278 			error_message(USAGE_03_ERROR,
279 			PLAIN_ERROR, (char *)0, optopt);
280 			usage_err++;
281 			break;
282 		}
283 	}
284 
285 	if (usage_err || argc - optind < 1)
286 		usage();
287 
288 	cmd_info->arnam = arnam = argv[optind];
289 	cmd_info->namv = &argv[optind+1];
290 	cmd_info->namc = argc - optind - 1;
291 }
292 
293 
294 /*
295  * Set the function to be called to do the key operation.
296  * Check that only one key is indicated.
297  */
298 static void
299 setcom(Cmd_info *cmd_info, int (*fun)())
300 {
301 	if (cmd_info->comfun != 0) {
302 		error_message(USAGE_04_ERROR, PLAIN_ERROR, (char *)0);
303 		exit(1);
304 	}
305 	cmd_info->comfun = fun;
306 }
307 
308 static void
309 usage(void)
310 {
311 	(void) fprintf(stderr, gettext(
312 "usage: ar -d[-vV] archive file ...\n"
313 "       ar -m[-abivV] [posname] archive file ...\n"
314 "       ar -p[-vV][-s] archive [file ...]\n"
315 "       ar -q[-cuvV] [-abi] [posname] [file ...]\n"
316 "       ar -r[-cuvV] [-abi] [posname] [file ...]\n"
317 "       ar -t[-vV][-s] archive [file ...]\n"
318 "       ar -x[-vV][-sCT] archive [file ...]\n"));
319 	exit(1);
320 }
321 
322 /*ARGSUSED0*/
323 static void
324 sigexit(int sig)
325 {
326 	exit(100);
327 }
328 
329 /* tells the user which of the listed files were not found in the archive */
330 
331 static int
332 notfound(Cmd_info *cmd_info)
333 {
334 	int i, n;
335 
336 	n = 0;
337 	for (i = 0; i < cmd_info->namc; i++)
338 		if (cmd_info->namv[i]) {
339 			error_message(NOT_FOUND_03_ERROR,
340 			PLAIN_ERROR, (char *)0, cmd_info->namv[i]);
341 			n++;
342 		}
343 	return (n);
344 }
345 
346 /*
347  * Debugging info
348  */
349 static void
350 check_swap(void)
351 {
352 	(void) system("/usr/sbin/swap -s");
353 }
354