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