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