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