dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / cmd / sgs / ar / common / main.c
blobb2279f2412c37fff6b30684ae88744674f8e124d
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
21 /* Copyright (c) 1988 AT&T */
22 /* All Rights Reserved */
25 * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved.
28 #include "inc.h"
29 #include "conv.h"
32 * Forward declarations
34 static void setup(int, char **, Cmd_info *);
35 static void setcom(Cmd_info *, Cmd_func);
36 static void usage(void);
37 static void sigexit(int sig);
38 static int notfound(Cmd_info *);
39 static void check_swap();
41 const char *
42 _ar_msg(Msg mid)
44 return (gettext(MSG_ORIG(mid)));
48 void
49 establish_sighandler(void (*handler)())
51 static const int signum[] = {SIGHUP, SIGINT, SIGQUIT, 0};
52 int i;
54 if (handler == SIG_IGN) {
55 /* Ignore all the specified signals */
56 for (i = 0; signum[i]; i++)
57 (void) signal(signum[i], SIG_IGN);
59 } else {
61 * Set any signal that doesn't default to being ignored
62 * to our signal handler.
64 for (i = 0; signum[i]; i++)
65 if (signal(signum[i], SIG_IGN) != SIG_IGN)
66 (void) signal(signum[i], handler);
70 int
71 main(int argc, char **argv, char *envp[])
73 int fd;
74 Cmd_info *cmd_info;
75 int ret;
76 char *new = NULL;
79 * Check for a binary that better fits this architecture.
81 (void) conv_check_native(argv, envp);
84 * Establish locale.
86 (void) setlocale(LC_ALL, MSG_ORIG(MSG_STR_EMPTY));
87 (void) textdomain(MSG_ORIG(MSG_SUNW_OST_SGS));
89 /* Allow a graceful exit up until we start to write an archive */
90 establish_sighandler(sigexit);
93 * Initialize cmd_info
95 cmd_info = (Cmd_info *)calloc(1, sizeof (Cmd_info));
96 if (cmd_info == NULL) {
97 int err = errno;
98 (void) fprintf(stderr, MSG_INTL(MSG_MALLOC), strerror(err));
99 exit(1);
102 if (argc < 2)
103 usage();
106 * Option handling.
108 if (argv[1][0] != '-') {
109 new = (char *)malloc(strlen(argv[1]) + 2);
110 if (new == NULL) {
111 int err = errno;
112 (void) fprintf(stderr, MSG_INTL(MSG_MALLOC),
113 strerror(err));
114 exit(1);
116 (void) strcpy(new, MSG_ORIG(MSG_STR_HYPHEN));
117 (void) strcat(new, argv[1]);
118 argv[1] = new;
120 setup(argc, argv, cmd_info);
123 * Check SWAP
125 if (cmd_info->opt_flgs & z_FLAG)
126 check_swap();
128 if (cmd_info->comfun == NULL) {
129 if ((cmd_info->opt_flgs & (d_FLAG | r_FLAG | q_FLAG |
130 t_FLAG | p_FLAG | m_FLAG | x_FLAG)) == 0) {
131 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_01));
132 exit(1);
136 cmd_info->modified = (cmd_info->opt_flgs & s_FLAG);
137 fd = getaf(cmd_info);
139 if ((fd == -1) &&
140 (cmd_info->opt_flgs &
141 (d_FLAG | m_FLAG | p_FLAG | t_FLAG | x_FLAG)) ||
142 ((cmd_info->opt_flgs & r_FLAG) &&
143 (cmd_info->opt_flgs & (a_FLAG | b_FLAG)))) {
144 (void) fprintf(stderr, MSG_INTL(MSG_NOT_FOUND_AR),
145 cmd_info->arnam);
146 exit(1);
149 (*cmd_info->comfun)(cmd_info);
150 if (cmd_info->modified) {
151 writefile(cmd_info);
152 } else
153 (void) close(fd);
155 ret = notfound(cmd_info);
158 * Check SWAP
160 if (cmd_info->opt_flgs & z_FLAG)
161 check_swap();
163 free(new);
164 free(cmd_info);
165 return (ret);
170 * Option handing function.
171 * Using getopt(), following xcu4 convention.
173 static void
174 setup(int argc, char *argv[], Cmd_info *cmd_info)
176 int Vflag = 0;
177 int c;
178 int usage_err = 0;
180 while ((c = getopt(argc, argv, MSG_ORIG(MSG_STR_OPTIONS))) != -1) {
181 switch (c) {
182 case 'a': /* position after named archive member file */
183 cmd_info->opt_flgs |= a_FLAG;
184 cmd_info->ponam = trim(optarg);
185 break;
186 case 'b': /* position before named archive member file */
187 case 'i': /* position before named archive member: same as b */
188 cmd_info->opt_flgs |= b_FLAG;
189 cmd_info->ponam = trim(optarg);
190 break;
191 case 'c': /* supress messages */
192 cmd_info->opt_flgs |= c_FLAG;
193 break;
194 case 'd':
196 * key operation:
197 * delete files from the archive
199 setcom(cmd_info, dcmd);
200 cmd_info->opt_flgs |= d_FLAG;
201 break;
202 case 'l': /* ignored */
203 break;
204 case 'm':
206 * key operation:
207 * move files to end of the archive
208 * or as indicated by position flag
210 setcom(cmd_info, mcmd);
211 cmd_info->opt_flgs |= m_FLAG;
212 break;
213 case 'p':
215 * key operation:
216 * print files in the archive
218 setcom(cmd_info, pcmd);
219 cmd_info->opt_flgs |= p_FLAG;
220 break;
221 case 'q':
223 * key operation:
224 * quickly append files to end of the archive
226 setcom(cmd_info, qcmd);
227 cmd_info->opt_flgs |= q_FLAG;
228 break;
229 case 'r':
231 * key operation:
232 * replace or add files to the archive
234 setcom(cmd_info, rcmd);
235 cmd_info->opt_flgs |= r_FLAG;
236 break;
237 case 's': /* force symbol table regeneration */
238 cmd_info->opt_flgs |= s_FLAG;
239 break;
240 case 'S': /* Build SYM64 symbol table */
241 cmd_info->opt_flgs |= S_FLAG;
242 break;
243 case 't':
245 * key operation:
246 * print table of contents
248 setcom(cmd_info, tcmd);
249 cmd_info->opt_flgs |= t_FLAG;
250 break;
251 case 'u': /* update: change archive dependent on file dates */
252 cmd_info->opt_flgs |= u_FLAG;
253 break;
254 case 'v': /* verbose */
255 cmd_info->opt_flgs |= v_FLAG;
256 break;
257 case 'x':
259 * key operation:
260 * extract files from the archive
262 setcom(cmd_info, xcmd);
263 cmd_info->opt_flgs |= x_FLAG;
264 break;
265 case 'z':
266 cmd_info->opt_flgs |= z_FLAG;
267 break;
268 case 'V':
270 * print version information.
271 * adjust command line access accounting
273 if (Vflag == 0) {
274 (void) fprintf(stderr,
275 MSG_ORIG(MSG_FMT_VERSION),
276 (const char *)SGU_PKG,
277 (const char *)SGU_REL);
278 Vflag++;
280 break;
281 case 'C':
282 cmd_info->opt_flgs |= C_FLAG;
283 break;
284 case 'M':
286 * -M was an original undocumented AT&T feature that
287 * would force the use of mmap() instead of read()
288 * for pulling file data into the process before
289 * writing it to the archive. Ignored.
291 break;
292 case 'T':
293 cmd_info->opt_flgs |= T_FLAG;
294 break;
295 case ':':
296 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_02), optopt);
297 usage_err++;
298 break;
299 case '?':
300 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_03), optopt);
301 usage_err++;
302 break;
306 if (usage_err || argc - optind < 1)
307 usage();
309 cmd_info->arnam = argv[optind];
310 cmd_info->namv = &argv[optind+1];
311 cmd_info->namc = argc - optind - 1;
316 * Set the function to be called to do the key operation.
317 * Check that only one key is indicated.
319 static void
320 setcom(Cmd_info *cmd_info, Cmd_func *fun)
322 if (cmd_info->comfun != 0) {
323 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_04));
324 exit(1);
326 cmd_info->comfun = fun;
329 static void
330 usage(void)
332 (void) fprintf(stderr, MSG_INTL(MSG_USAGE));
333 exit(1);
336 /*ARGSUSED0*/
337 static void
338 sigexit(int sig)
340 exit(100);
343 /* tells the user which of the listed files were not found in the archive */
345 static int
346 notfound(Cmd_info *cmd_info)
348 int i, n;
350 n = 0;
351 for (i = 0; i < cmd_info->namc; i++)
352 if (cmd_info->namv[i]) {
353 (void) fprintf(stderr, MSG_INTL(MSG_NOT_FOUND_FILE),
354 cmd_info->namv[i]);
355 n++;
357 return (n);
361 * Debugging info
363 static void
364 check_swap(void)
366 (void) system(MSG_ORIG(MSG_CMD_SWAP));