xref: /original-bsd/usr.bin/ar/ar.c (revision c3e32dec)
1 /*-
2  * Copyright (c) 1990, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Hugh Smith at The University of Guelph.
7  *
8  * %sccs.include.redist.c%
9  */
10 
11 #ifndef lint
12 static char copyright[] =
13 "@(#) Copyright (c) 1990, 1993\n\
14 	The Regents of the University of California.  All rights reserved.\n";
15 #endif /* not lint */
16 
17 #ifndef lint
18 static char sccsid[] = "@(#)ar.c	8.1 (Berkeley) 06/06/93";
19 #endif /* not lint */
20 
21 #include <sys/param.h>
22 #include <sys/errno.h>
23 #include <dirent.h>
24 #include <stdio.h>
25 #include <ar.h>
26 #include <string.h>
27 #include <stdlib.h>
28 #include <paths.h>
29 #include "archive.h"
30 #include "extern.h"
31 
32 CHDR chdr;
33 u_int options;
34 char *archive, *envtmp, *posarg, *posname;
35 static void badoptions(), usage();
36 
37 /*
38  * main --
39  *	main basically uses getopt to parse options and calls the appropriate
40  *	functions.  Some hacks that let us be backward compatible with 4.3 ar
41  *	option parsing and sanity checking.
42  */
43 main(argc, argv)
44 	int argc;
45 	char **argv;
46 {
47 	extern int optind;
48 	int c;
49 	char *p;
50 	int (*fcall)(), append(), contents(), delete(), extract(),
51 	    move(), print(), replace();
52 
53 	if (argc < 3)
54 		usage();
55 
56 	/*
57 	 * Historic versions didn't require a '-' in front of the options.
58 	 * Fix it, if necessary.
59 	*/
60 	if (*argv[1] != '-') {
61 		if (!(p = malloc((u_int)(strlen(argv[1]) + 2)))) {
62 			(void)fprintf(stderr, "ar: %s.\n", strerror(errno));
63 			exit(1);
64 		}
65 		*p = '-';
66 		(void)strcpy(p + 1, argv[1]);
67 		argv[1] = p;
68 	}
69 
70 	while ((c = getopt(argc, argv, "abcdilmopqrTtuvx")) != EOF) {
71 		switch(c) {
72 		case 'a':
73 			options |= AR_A;
74 			break;
75 		case 'b':
76 		case 'i':
77 			options |= AR_B;
78 			break;
79 		case 'c':
80 			options |= AR_C;
81 			break;
82 		case 'd':
83 			options |= AR_D;
84 			fcall = delete;
85 			break;
86 		case 'l':		/* not documented, compatibility only */
87 			envtmp = ".";
88 			break;
89 		case 'm':
90 			options |= AR_M;
91 			fcall = move;
92 			break;
93 		case 'o':
94 			options |= AR_O;
95 			break;
96 		case 'p':
97 			options |= AR_P;
98 			fcall = print;
99 			break;
100 		case 'q':
101 			options |= AR_Q;
102 			fcall = append;
103 			break;
104 		case 'r':
105 			options |= AR_R;
106 			fcall = replace;
107 			break;
108 		case 'T':
109 			options |= AR_TR;
110 			break;
111 		case 't':
112 			options |= AR_T;
113 			fcall = contents;
114 			break;
115 		case 'u':
116 			options |= AR_U;
117 			break;
118 		case 'v':
119 			options |= AR_V;
120 			break;
121 		case 'x':
122 			options |= AR_X;
123 			fcall = extract;
124 			break;
125 		default:
126 			usage();
127 		}
128 	}
129 
130 	argv += optind;
131 	argc -= optind;
132 
133 	/* One of -dmpqrtx required. */
134 	if (!(options & (AR_D|AR_M|AR_P|AR_Q|AR_R|AR_T|AR_X))) {
135 		(void)fprintf(stderr,
136 		    "ar: one of options -dmpqrtx is required.\n");
137 		usage();
138 	}
139 	/* Only one of -a and -bi allowed. */
140 	if (options & AR_A && options & AR_B) {
141 		(void)fprintf(stderr,
142 		    "ar: only one of -a and -[bi] options allowed.\n");
143 		usage();
144 	}
145 	/* -ab require a position argument. */
146 	if (options & (AR_A|AR_B)) {
147 		if (!(posarg = *argv++)) {
148 			(void)fprintf(stderr,
149 			    "ar: no position operand specified.\n");
150 			usage();
151 		}
152 		posname = rname(posarg);
153 	}
154 	/* -d only valid with -Tv. */
155 	if (options & AR_D && options & ~(AR_D|AR_TR|AR_V))
156 		badoptions("-d");
157 	/* -m only valid with -abiTv. */
158 	if (options & AR_M && options & ~(AR_A|AR_B|AR_M|AR_TR|AR_V))
159 		badoptions("-m");
160 	/* -p only valid with -Tv. */
161 	if (options & AR_P && options & ~(AR_P|AR_TR|AR_V))
162 		badoptions("-p");
163 	/* -q only valid with -cTv. */
164 	if (options & AR_Q && options & ~(AR_C|AR_Q|AR_TR|AR_V))
165 		badoptions("-q");
166 	/* -r only valid with -abcuTv. */
167 	if (options & AR_R && options & ~(AR_A|AR_B|AR_C|AR_R|AR_U|AR_TR|AR_V))
168 		badoptions("-r");
169 	/* -t only valid with -Tv. */
170 	if (options & AR_T && options & ~(AR_T|AR_TR|AR_V))
171 		badoptions("-t");
172 	/* -x only valid with -ouTv. */
173 	if (options & AR_X && options & ~(AR_O|AR_U|AR_TR|AR_V|AR_X))
174 		badoptions("-x");
175 
176 	if (!(archive = *argv++)) {
177 		(void)fprintf(stderr, "ar: no archive specified.\n");
178 		usage();
179 	}
180 
181 	/* -dmqr require a list of archive elements. */
182 	if (options & (AR_D|AR_M|AR_Q|AR_R) && !*argv) {
183 		(void)fprintf(stderr, "ar: no archive members specified.\n");
184 		usage();
185 	}
186 
187 	exit((*fcall)(argv));
188 }
189 
190 static void
191 badoptions(arg)
192 	char *arg;
193 {
194 	(void)fprintf(stderr,
195 	    "ar: illegal option combination for %s.\n", arg);
196 	usage();
197 }
198 
199 static void
200 usage()
201 {
202 	(void)fprintf(stderr, "usage:  ar -d [-Tv] archive file ...\n");
203 	(void)fprintf(stderr, "\tar -m [-Tv] archive file ...\n");
204 	(void)fprintf(stderr, "\tar -m [-abiTv] position archive file ...\n");
205 	(void)fprintf(stderr, "\tar -p [-Tv] archive [file ...]\n");
206 	(void)fprintf(stderr, "\tar -q [-cTv] archive file ...\n");
207 	(void)fprintf(stderr, "\tar -r [-cuTv] archive file ...\n");
208 	(void)fprintf(stderr, "\tar -r [-abciuTv] position archive file ...\n");
209 	(void)fprintf(stderr, "\tar -t [-Tv] archive [file ...]\n");
210 	(void)fprintf(stderr, "\tar -x [-ouTv] archive [file ...]\n");
211 	exit(1);
212 }
213