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 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
29
30
31 #pragma ident "%Z%%M% %I% %E% SMI"
32
33 /*
34 * Implements the "putdgrp" command.
35 */
36 #include <sys/types.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include <errno.h>
41 #include <unistd.h>
42 #include <fmtmsg.h>
43 #include <devmgmt.h>
44 #include <devtab.h>
45
46
47 /*
48 * General Purpose Constants
49 * TRUE Boolean TRUE (if not already defined)
50 * FALSE Boolean FALSE (if not already defined)
51 */
52
53 #ifndef TRUE
54 #define TRUE (1)
55 #endif
56
57 #ifndef FALSE
58 #define FALSE (0)
59 #endif
60
61 /*
62 * Exit codes
63 * EX_OK All went well
64 * EX_ERROR Usage or internal error
65 * EX_DGROUP Had trouble accessing/reading/writing the
66 * device-group table
67 * EX_NODGRP The specified device-group does not exist
68 * EX_NOMEM One or more device-group members requested for
69 * removal was not defined for the device
70 */
71
72 #define EX_OK 0
73 #define EX_ERROR 1
74 #define EX_DGROUP 2
75 #define EX_NODGRP 3
76 #define EX_NOMEM 4
77
78
79 /*
80 * Error messages
81 */
82
83 #define E_USAGE "usage: putdgrp [-d] dgroup [device [...]]"
84 #define E_NODGRP "Device-group does not exist in table: %s"
85 #define E_NOTAMEM "Device-group member not found: %s"
86 #define E_NODGRPTAB "Cannot open the device-group table: %s"
87 #define E_NOMKTAB "Cannot create a new device-group table: %s"
88 #define E_INTERNAL "Internal error, errno=%d"
89
90
91 /*
92 * Macros
93 * stdmsg(r,l,s,t) Using fmtmsg(), write a standard message to the
94 * standard error stream.
95 * Where:
96 * r The recoverability of the error
97 * l The label-component
98 * s The severity-component
99 * t The text-component
100 */
101
102 #define stdmsg(r,l,s,t) (void) fmtmsg(MM_PRINT|MM_UTIL|r,l,s,t,MM_NULLACT,MM_NULLTAG)
103
104
105 /*
106 * Static data
107 * msg Space for message's text-component
108 */
109
110 static char msg[256]; /* Space for text of message */
111
112 /*
113 * char *mklbl(cmd)
114 * char *cmd
115 *
116 * This function builds a standard label from the command used to invoke
117 * this process and the standard label prefix ("UX:")
118 *
119 * Arguments:
120 * char *cmd The command used to invoke this process.
121 *
122 * Returns: char *
123 * Pointer to malloc()ed space containing the standard label,
124 * or (char *) NULL if an error occurred.
125 */
126
127 static char *
mklbl(cmd)128 mklbl(cmd)
129 char *cmd;
130 {
131 /* Automatic data */
132 char *rtn; /* Value to return */
133 char *p; /* Temporary */
134
135 /* Find the 1st char of the basename of the command */
136 if (p = strrchr(cmd, '/')) p++;
137 else p = cmd;
138
139 /* Allocate and build the string value to return */
140 if (rtn = (char *) malloc(strlen("UX:")+strlen(p)+1)) {
141 (void) strcpy(rtn, "UX:");
142 (void) strcat(rtn, p);
143 }
144
145 /* Now that we've done all of this work, set up the environemnt
146 * so that only the text-component is written (some requirements
147 * say that standard messages are to be non-standard in SVR4.0,
148 * this is supposed to change in SVR4.1)
149 */
150
151 (void) putenv("MSGVERB=text");
152
153 /* Done */
154 return(rtn);
155 }
156
157 /*
158 * putdgrp [-d] dgroup [device [...]]
159 *
160 * Options:
161 * -d
162 *
163 * Arguments:
164 * dgroup
165 * device
166 *
167 * Exit values:
168 */
169
170 int
main(int argc,char * argv[])171 main(int argc, char *argv[])
172 {
173 /* Automatic data */
174 char **plist; /* Ptr to list of nonmembers */
175 char *lbl; /* Ptr to label for messages */
176 char *dgroup; /* Ptr to <dgroup> on command-line */
177 char *p; /* Temp ptr to char */
178 int noerr; /* FLAG, TRUE if all's well */
179 int d_seen; /* TRUE if -a seen on command-line */
180 int optchar; /* Option extracted */
181 int exitcd; /* Value to return at exit */
182 int nmems; /* Number of members on the cmd */
183
184
185 /* Generate the label for messages */
186 lbl = mklbl(argv[0]);
187
188 /* Extract arguments - validate usage */
189 noerr = TRUE;
190 d_seen = FALSE;
191 opterr = FALSE;
192 while ((optchar = getopt(argc, argv, "d:")) != EOF) switch (optchar) {
193
194 case 'd':
195 if (!d_seen)
196 {
197 d_seen = TRUE;
198 dgroup = optarg;
199 }
200 else noerr = FALSE;
201 break;
202
203 case '?':
204 default:
205 noerr = FALSE;
206 }
207
208
209 /* Write a usage message if we've seen a blatant error */
210 if (!noerr || (!d_seen && ((nmems = argc - optind - 1) < 0)) ||
211 (d_seen && ((nmems = argc - optind) < 0))) {
212 stdmsg(MM_NRECOV, lbl, MM_ERROR, E_USAGE);
213 exit(EX_ERROR);
214 }
215
216
217 /* Set up */
218 exitcd = EX_OK;
219
220
221 /* -d on the command line ? */
222 if (d_seen) {
223
224 /*
225 * Determine case (removing a device group or members
226 * of that device group.
227 */
228
229 if (nmems == 0) {
230
231 /* putdgrp -d dgroup */
232
233 /* Attempt to remove the specified device */
234 if (!(_rmdgrptabrec(dgroup))) switch(errno) {
235
236 /*
237 * EINVAL indicates that the named device-group was
238 * not found in the device-group table.
239 */
240
241 case EINVAL:
242 (void) snprintf(msg, sizeof(msg), E_NODGRP, dgroup);
243 stdmsg(MM_NRECOV, lbl, MM_ERROR, msg);
244 exitcd = EX_NODGRP;
245 break;
246
247 /*
248 * ENOENT indicates that the device-group table can't
249 * be found.
250 */
251
252 case ENOENT:
253 (void) snprintf(msg, sizeof(msg), E_NODGRPTAB, _dgrptabpath());
254 stdmsg(MM_NRECOV, lbl, MM_ERROR, msg);
255 exitcd = EX_DGROUP;
256 break;
257
258 /*
259 * EACCES indicates that there was a problem reading the
260 * old device-group table or creating the new table. If the
261 * old table is readable, assume that we can't create the
262 * new table. Otherwise, assume that the old table isn't
263 * accessible.
264 */
265
266 case EACCES:
267 p = _dgrptabpath();
268 if (access(p, R_OK) == 0)
269 (void) snprintf(msg, sizeof(msg), E_NOMKTAB, p);
270 else
271 (void) snprintf(msg, sizeof(msg), E_NODGRPTAB, p);
272 stdmsg(MM_NRECOV, lbl, MM_ERROR, msg);
273 exitcd = EX_DGROUP;
274 break;
275
276 /*
277 * Some strange problem...
278 */
279
280 default:
281 (void) snprintf(msg, sizeof(msg), E_INTERNAL, errno);
282 stdmsg(MM_NRECOV, lbl, MM_ERROR, msg);
283 exitcd = EX_ERROR;
284
285 } /* End switch */
286 }
287 else {
288
289 /* putdgrp -d dgroup device [device [...]] */
290
291 /*
292 * Attempt to remove the specified devices from the
293 * specified device-group.
294 */
295 if (!(_rmdgrpmems(dgroup, &argv[optind], &plist))) switch(errno) {
296
297 /*
298 * ENODEV indicates that a named device was not part
299 * of the specified device group.
300 */
301
302 case ENODEV:
303 exitcd = EX_NOMEM;
304 for (; *plist; plist++) {
305 (void) snprintf(msg, sizeof(msg), E_NOTAMEM, *plist);
306 stdmsg(MM_RECOVER, lbl, MM_WARNING, msg);
307 }
308 break;
309
310 /*
311 * EINVAL indicates that the named device-group is not
312 * defined in the device-group table.
313 */
314
315 case EINVAL:
316 (void) snprintf(msg, sizeof(msg), E_NODGRP, dgroup);
317 stdmsg(MM_NRECOV, lbl, MM_ERROR, msg);
318 exitcd = EX_NODGRP;
319 break;
320
321 /*
322 * ENOENT indicates that the device table can't
323 * be found.
324 */
325
326 case ENOENT:
327 (void) snprintf(msg, sizeof(msg), E_NODGRPTAB, _dgrptabpath());
328 stdmsg(MM_NRECOV, lbl, MM_ERROR, msg);
329 exitcd = EX_DGROUP;
330 break;
331
332 /*
333 * EACCES indicates that there was a problem reading the
334 * old device table or creating the new table. If the
335 * old table is readable, assume that we can't create the
336 * new table. Otherwise, assume that the old table isn't
337 * accessible.
338 */
339
340 case EACCES:
341 p = _dgrptabpath();
342 if (access(p, R_OK) == 0)
343 (void) snprintf(msg, sizeof(msg), E_NOMKTAB, p);
344 else
345 (void) snprintf(msg, sizeof(msg), E_NODGRPTAB, p);
346 stdmsg(MM_NRECOV, lbl, MM_ERROR, msg);
347 exitcd = EX_DGROUP;
348 break;
349
350 /*
351 * Some strange problem...
352 */
353
354 default:
355 (void) sprintf(msg, E_INTERNAL, errno);
356 stdmsg(MM_NRECOV, lbl, MM_ERROR, msg);
357 exitcd = EX_ERROR;
358
359 } /* End switch */
360
361 } /* End "putdgrp -d device attr [...]" case */
362
363
364 } /* End -d case */
365
366 else {
367 /* Standard case (no -d on the command) */
368 if (!(_adddgrptabrec(argv[optind], &argv[optind+1]))) switch(errno) {
369
370 /*
371 * ENOENT indicates that the device-group table does not exist.
372 */
373
374 case ENOENT:
375 (void) snprintf(msg, sizeof(msg), E_NODGRPTAB, _dgrptabpath());
376 stdmsg(MM_NRECOV, lbl, MM_ERROR, msg);
377 exitcd = EX_DGROUP;
378 break;
379
380 /*
381 * EACCES indicates that the device-group table could not be
382 * opened or the new device-group table could not be created.
383 */
384
385 case EACCES:
386 p = _dgrptabpath();
387 if (access(p, R_OK) == 0)
388 (void) snprintf(msg, sizeof(msg), E_NOMKTAB, p);
389 else
390 (void) snprintf(msg, sizeof(msg), E_NODGRPTAB, p);
391 stdmsg(MM_NRECOV, lbl, MM_ERROR, msg);
392 exitcd = EX_DGROUP;
393 break;
394
395 /*
396 * Some strange error (memory?)
397 */
398
399 default:
400 (void) sprintf(msg, E_INTERNAL, errno);
401 stdmsg(MM_NRECOV, lbl, MM_ERROR, msg);
402 exitcd = EX_ERROR;
403 }
404 }
405
406 /* Done. Return exit code (determined above) */
407 return(exitcd);
408 } /* main() */
409