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 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 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