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
main(int argc,char ** argv)76 main(int argc, char **argv)
77 {
78 int 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
set_verbose(boolean_t setting)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
get_verbose()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
print_version()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
usage()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
get_dbstatus(int argc,char ** argv)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
sync_server(int argc,char ** argv)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