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
main(int argc,char ** argv)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
set_verbose(boolean_t setting)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
get_verbose()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
log_pkgerr(LogMsgType type,PKG_ERR * err)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
print_version()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
usage()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
get_dbstatus(int argc,char ** argv)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
sync_server(int argc,char ** argv)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