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