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