Home | History | Annotate | Download | only in common
      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