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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <sys/stat.h> 30 #include <locale.h> 31 #include <unistd.h> 32 #include <stdlib.h> 33 #include <stdio.h> 34 35 #include "dconf.h" 36 #include "minfree.h" 37 #include "utils.h" 38 39 static const char USAGE[] = "\ 40 Usage: %s [-nuy] [-c kernel | curproc | all ] [-d dump-device | swap ]\n\ 41 [-m min {k|m|%%} ] [-s savecore-dir] [-r root-dir]\n"; 42 43 static const char OPTS[] = "nuyc:d:m:s:r:"; 44 45 static const char PATH_DEVICE[] = "/dev/dump"; 46 static const char PATH_CONFIG[] = "/etc/dumpadm.conf"; 47 48 int 49 main(int argc, char *argv[]) 50 { 51 const char *pname = getpname(argv[0]); 52 53 u_longlong_t minf; 54 struct stat st; 55 int c; 56 int dflag = 0; /* for checking in use during -d ops */ 57 int dcmode = DC_CURRENT; /* kernel settings override unless -u */ 58 int modified = 0; /* have we modified the dump config? */ 59 char *minfstr = NULL; /* string value of -m argument */ 60 dumpconf_t dc; /* current configuration */ 61 62 (void) setlocale(LC_ALL, ""); 63 (void) textdomain(TEXT_DOMAIN); 64 65 /* 66 * Take an initial lap through argv hunting for -r root-dir, 67 * so that we can chroot before opening the configuration file. 68 * We also handle -u and any bad options at this point. 69 */ 70 while (optind < argc) { 71 while ((c = getopt(argc, argv, OPTS)) != (int)EOF) { 72 if (c == 'r' && chroot(optarg) == -1) 73 die(gettext("failed to chroot to %s"), optarg); 74 else if (c == 'u') 75 dcmode = DC_OVERRIDE; 76 else if (c == '?') { 77 (void) fprintf(stderr, gettext(USAGE), pname); 78 return (E_USAGE); 79 } 80 } 81 82 if (optind < argc) { 83 warn(gettext("illegal argument -- %s\n"), argv[optind]); 84 (void) fprintf(stderr, gettext(USAGE), pname); 85 return (E_USAGE); 86 } 87 } 88 89 if (geteuid() != 0) 90 die(gettext("you must be root to use %s\n"), pname); 91 92 /* 93 * If no config file exists yet, we're going to create an empty one, 94 * so set the modified flag to force writing out the file. 95 */ 96 if (access(PATH_CONFIG, F_OK) == -1) 97 modified++; 98 99 /* 100 * Now open and read in the initial values from the config file. 101 * If it doesn't exist, we create an empty file and dc is 102 * initialized with the default values. 103 */ 104 if (dconf_open(&dc, PATH_DEVICE, PATH_CONFIG, dcmode) == -1) 105 return (E_ERROR); 106 107 /* 108 * Take another lap through argv, processing options and 109 * modifying the dumpconf_t as appropriate. 110 */ 111 for (optind = 1; optind < argc; optind++) { 112 while ((c = getopt(argc, argv, OPTS)) != (int)EOF) { 113 switch (c) { 114 case 'c': 115 if (dconf_str2content(&dc, optarg) == -1) 116 return (E_USAGE); 117 modified++; 118 break; 119 case 'd': 120 if (dconf_str2device(&dc, optarg) == -1) 121 return (E_USAGE); 122 dflag++; 123 modified++; 124 break; 125 126 case 'm': 127 minfstr = optarg; 128 break; 129 130 case 'n': 131 dc.dc_enable = DC_OFF; 132 modified++; 133 break; 134 135 case 's': 136 if (stat(optarg, &st) == -1 || 137 !S_ISDIR(st.st_mode)) { 138 warn(gettext("%s is missing or not a " 139 "directory\n"), optarg); 140 return (E_USAGE); 141 } 142 143 if (dconf_str2savdir(&dc, optarg) == -1) 144 return (E_USAGE); 145 modified++; 146 break; 147 148 case 'y': 149 dc.dc_enable = DC_ON; 150 modified++; 151 break; 152 } 153 } 154 } 155 156 if (minfstr != NULL) { 157 if (minfree_compute(dc.dc_savdir, minfstr, &minf) == -1) 158 return (E_USAGE); 159 if (minfree_write(dc.dc_savdir, minf) == -1) 160 return (E_ERROR); 161 } 162 163 if (dcmode == DC_OVERRIDE) { 164 /* 165 * In override mode, we try to force an update. If this 166 * fails, we re-load the kernel configuration and write that 167 * out to the file in order to force the file in sync. 168 */ 169 if (dconf_update(&dc, 0) == -1) 170 (void) dconf_getdev(&dc); 171 if (dconf_write(&dc) == -1) 172 return (E_ERROR); 173 174 } else if (modified) { 175 /* 176 * If we're modifying the configuration, then try 177 * to update it, and write out the file if successful. 178 */ 179 if (dconf_update(&dc, dflag) == -1 || 180 dconf_write(&dc) == -1) 181 return (E_ERROR); 182 } 183 184 if (dcmode == DC_CURRENT) 185 dconf_print(&dc, stdout); 186 187 if (dconf_close(&dc) == -1) 188 warn(gettext("failed to close configuration file")); 189 190 return (E_SUCCESS); 191 } 192