xref: /illumos-gate/usr/src/cmd/svr4pkg/pkgadm/main.c (revision 797f979d1fe26bfb1cdeb3e7a86ed24c0b654200)
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 
22 /*
23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 
28 /* unix system includes */
29 
30 #include <stdio.h>
31 #include <stdarg.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <sys/types.h>
35 #include <unistd.h>
36 #include <locale.h>
37 #include <sys/param.h>
38 #include <openssl/bio.h>
39 
40 #include <pkglib.h>
41 #include <pkgerr.h>
42 #include <keystore.h>
43 #include "pkgadm.h"
44 #include "pkgadm_msgs.h"
45 #include "libadm.h"
46 
47 /* initial error message buffer size */
48 
49 #define	ERR_BUFSIZE		2048
50 
51 /* Local Function Prototypes */
52 
53 static void			print_version();
54 int				get_dbstatus(int argc, char **argv);
55 int				sync_server(int argc, char **argv);
56 
57 /* holds subcommands and their definitions */
58 struct cmd {
59 	char		*c_name;
60 	int		(*c_func)(int, char **);
61 };
62 
63 struct cmd  cmds[] = {
64 	{ "dbstatus",		get_dbstatus},
65 	{ "lock",		admin_lock},
66 	{ "sync",		sync_server},
67 	/* last one must be all NULLs */
68 	{ NULL, NULL }
69 };
70 
71 struct cmd cert_cmds[] = {
72 	{ "addcert",		addcert},
73 	{ "listcert",		listcert},
74 	{ "removecert",		removecert},
75 	/* last one must be all NULLs */
76 	{ NULL, NULL }
77 };
78 
79 
80 /*
81  * Function:	main
82  *
83  * Return:	0	- subprocessing successful
84  *			  scripts and reboot
85  *	[other]	- subprocessing-specific failure
86  */
87 int
88 main(int argc, char **argv)
89 {
90 	char	cur_cmd;
91 	int	newargc;
92 	char	**newargv;
93 	int	i;
94 
95 	/* Should be defined by cc -D */
96 #if	!defined(TEXT_DOMAIN)
97 #define	TEXT_DOMAIN "SYS_TEST"
98 #endif
99 
100 	/* set the default text domain for messaging */
101 	(void) setlocale(LC_ALL, "");
102 	(void) textdomain(TEXT_DOMAIN);
103 
104 	if (getenv("PKGADM_VERBOSE")) {
105 		set_verbose(B_TRUE);
106 	}
107 
108 	/* Superficial check of the arguments. */
109 	if (argc <= 1) {
110 		log_msg(LOG_MSG_INFO, MSG_USAGE);
111 		return (1);
112 	}
113 
114 	/* first, process any arguments that can appear before the subcommand */
115 	while ((i = getopt(argc, argv, "vV?")) != EOF) {
116 		switch (i) {
117 		case 'v':	/* verbose mode enabled */
118 			set_verbose(B_TRUE);
119 			break;
120 		case 'V':
121 			print_version();
122 			return (0);
123 		case '?':
124 			log_msg(LOG_MSG_INFO, MSG_USAGE);
125 			return (0);
126 		}
127 	}
128 
129 	/* OK, hand it off to the subcommand processors */
130 	for (cur_cmd = 0; cmds[cur_cmd].c_name != NULL; cur_cmd++) {
131 		if (ci_streq(argv[optind], cmds[cur_cmd].c_name)) {
132 			/* make subcommand the first option */
133 			newargc = argc - optind;
134 			newargv = argv + optind;
135 			opterr = optind = 1; optopt = 0;
136 			return (cmds[cur_cmd].c_func(newargc, newargv));
137 		}
138 	}
139 
140 	/* initialize security library */
141 	sec_init();
142 
143 	/* OK, hand it off to the subcommand processors */
144 	for (cur_cmd = 0; cert_cmds[cur_cmd].c_name != NULL; cur_cmd++) {
145 		if (ci_streq(argv[optind], cert_cmds[cur_cmd].c_name)) {
146 			/* make subcommand the first option */
147 			newargc = argc - optind;
148 			newargv = argv + optind;
149 			opterr = optind = 1; optopt = 0;
150 			return (cert_cmds[cur_cmd].c_func(newargc, newargv));
151 		}
152 	}
153 
154 	/* bad subcommand */
155 	log_msg(LOG_MSG_ERR, MSG_BAD_SUB, argv[optind]);
156 	log_msg(LOG_MSG_INFO, MSG_USAGE);
157 	return (1);
158 }
159 
160 /*
161  * Name:	set_verbose
162  * Description:	Turns on verbose output
163  * Scope:	public
164  * Arguments:	verbose = B_TRUE indicates verbose mode
165  * Returns:	none
166  */
167 void
168 set_verbose(boolean_t setting)
169 {
170 	log_set_verbose(setting);
171 }
172 
173 /*
174  * Name:	get_verbose
175  * Description:	Returns whether or not to output verbose messages
176  * Scope:	public
177  * Arguments:	none
178  * Returns:	B_TRUE - verbose messages should be output
179  */
180 boolean_t
181 get_verbose()
182 {
183 	return (log_get_verbose());
184 }
185 
186 /*
187  * Name:	log_pkgerr
188  * Description:	Outputs pkgerr messages to logging facility.
189  * Scope:	public
190  * Arguments:	type - the severity of the message
191  *		err - error stack to dump to facility
192  * Returns:	none
193  */
194 void
195 log_pkgerr(LogMsgType type, PKG_ERR *err)
196 {
197 	int i;
198 	for (i = 0; i < pkgerr_num(err); i++) {
199 		log_msg(type, "%s", pkgerr_get(err, i));
200 	}
201 }
202 
203 /*
204  * Name:	print_Version
205  * Desc:  Prints Version of packaging tools
206  * Arguments: none
207  * Returns: none
208  */
209 static void
210 print_version()
211 {
212 	/* ignore any and all arguments, print version only */
213 	(void) fprintf(stdout, "%s\n", SUNW_PKGVERS);
214 }
215 
216 /*
217  * usage
218  *
219  * Outputs the usage string.
220  *
221  * Return:1
222  * Side effects: none
223  */
224 static int
225 usage()
226 {
227 	log_msg(LOG_MSG_INFO, MSG_USAGE);
228 	return (1);
229 }
230 
231 /*
232  * get_dbstatus
233  *
234  * Return 'text' as the db status.
235  * Use the command line to determine if there is an alternate root.
236  *
237  * Return: 0 on success, nonzero on failure
238  * Side effects: none
239  */
240 int
241 get_dbstatus(int argc, char **argv)
242 {
243 	/* Either accept 1 argument or 3 arguments where the second is -R */
244 	if (argc != 1 && (argc != 3 || strcmp(argv[1], "-R")))
245 		return (usage());
246 
247 	(void) printf("%s\n", PKGADM_DBSTATUS_TEXT);
248 
249 	return (0);
250 }
251 
252 /*
253  * sync
254  *
255  * Use the command line to determine if there is an alternate root.
256  *
257  * Return: 0 on success, nonzero on failure
258  * Flush the pkgserv's log.
259  */
260 int
261 sync_server(int argc, char **argv)
262 {
263 	int c;
264 	char *root = NULL;
265 	char *dryrundir = NULL;
266 	boolean_t quit = B_FALSE;
267 
268 	/*
269 	 * Options:
270 	 *   -q: Tell pkgserv daemon to quit.
271 	 *   -R: Alternate root specification.
272 	 *   -D: Dryrun directory specification.
273 	 *
274 	 * -R and -D help pkgadm to locate IPC files used for communication
275 	 * with pkgserv daemon. They should not be used together, though
276 	 * nothing prevents you from doing so. If you use both at once
277 	 * then IPC files will be searched in $ROOTDIR/$DRYRUNDIR directory.
278 	 * So if you want to terminate dryrun pkgserv process, you should
279 	 * always use only -D option.
280 	 */
281 	while ((c = getopt(argc, argv, "D:R:q")) != EOF) {
282 		switch (c) {
283 		case 'D':
284 			dryrundir = optarg;
285 			break;
286 		case 'R':
287 			root = optarg;
288 			break;
289 		case 'q':
290 			quit = B_TRUE;
291 			break;
292 		default:
293 			return (usage());
294 		}
295 	}
296 
297 	if (!pkgsync_needed(root, dryrundir, quit))
298 		return (0);
299 
300 	set_PKGpaths(root);
301 	set_cfdir(dryrundir);
302 
303 	if (pkgWlock(1) == 1) {
304 		/* Flush the log file */
305 		(void) pkgsync(root, dryrundir, quit);
306 		(void) relslock();
307 		return (0);
308 	}
309 
310 	return (1);
311 }
312