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
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.
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]
23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
31 #pragma ident "%Z%%M% %I% %E% SMI"
34 * Implements the "putdev" command.
36 #include <sys/types.h>
48 * General Purpose Constants
49 * TRUE Boolean TRUE (if not already defined)
50 * FALSE Boolean FALSE (if not already defined)
51 * NULL Null address (if not already defined)
65 * EX_ERROR Usage or internal error
66 * EX_DEVTAB Had trouble accessing/reading/writing the device table
67 * EX_EXISTS The specified alias already exists
68 * EX_ATTRIB One or more attributes requested for removal was not
69 * defined for the device
70 * EX_RELPATH Pathname supplied for cdevice, bdevice or pathname
71 * attributes was not a full pathname
86 #define E_USAGE "usage: putdev -a alias [attribute=value [...]]\n putdev -m device attribute=value [attribute=value [...]]\n putdev -d device [attribute [...]]"
87 #define E_ALIASIS "Alias already exists in table: %s"
88 #define E_NODEV "Device does not exist in table: %s"
89 #define E_NOALIAS "Cannot use \"alias\" as an attribute"
90 #define E_NOATTR "Attribute not found: %s"
91 #define E_NODEVTAB "Cannot open the device table: %s"
92 #define E_NOMKDTAB "Cannot create a new device table: %s"
93 #define E_INVALIAS "Not a valid device alias: %s"
94 #define E_MULTIPLE "Multiple definitions of an attribute are not allowed."
95 #define E_INTERNAL "Internal error, errno=%d"
96 #define E_RELPATH "Full pathname required for cdevice,bdevice and pathname attributes."
101 * stdmsg(r,l,s,t) Using fmtmsg(), write a standard message to the
102 * standard error stream.
104 * r The recoverability of the error
105 * l The label-component
106 * s The severity-component
107 * t The text-component
110 #define stdmsg(r,l,s,t) (void) fmtmsg(MM_PRINT|MM_UTIL|r,l,s,t,MM_NULLACT,MM_NULLTAG)
115 * msg Space for message's text-component
118 static char msg
[256]; /* Space for text of message */
124 * This function builds a standard label from the command used to invoke
125 * this process and the standard label prefix ("UX:")
128 * char *cmd The command used to invoke this process.
131 * Pointer to malloc()ed space containing the standard label,
132 * or (char *) NULL if an error occurred.
140 char *rtn
; /* Value to return */
141 char *p
; /* Temporary */
143 /* Find the 1st char of the basename of the command */
144 if (p
= strrchr(cmd
, '/')) p
++;
147 /* Allocate and build the string value to return */
148 if (rtn
= (char *) malloc(strlen("UX:")+strlen(p
)+1)) {
149 (void) strcpy(rtn
, "UX:");
150 (void) strcat(rtn
, p
);
154 /* Now that we've done all of that work, change the environment
155 * so that only the text-component is written by fmtmsg().
156 * (This should go away in SVR4.1)
159 (void) putenv("MSGVERB=text");
167 * putdev -a alias [attribute=value [...]]
168 * putdev -m alias attribute=value [attribute=value [...]]
169 * putdev -d alias [attribute [...]]
171 * Modify the device-table. If -a specified, add a record for <alias>
172 * to the table. If -m specified, modify the attributes specified for
173 * the <device> specified. If -d specified, remove the specified
174 * attributes from the specified device or remove the specified device.
177 * -a Add an alias description to the device table
178 * -m Modify an existing device description
179 * -d (if no attributes specified) remove the specified
180 * device from the device table, or (if attributes
181 * specified) remove the specified attributes from
182 * the specified device.
186 * 1 Usage error (includes specifying "alias" as an
188 * 2 The device table file could not be opened, read
190 * 3 If -a, the alias already exists. Otherwise, the
191 * specified device does not exist in the table
192 * 4 One of the specified attributes did not exist
193 * for the device and therefore wasn't removed
197 main(int argc
, char *argv
[])
200 char **plist
; /* Ptr to list of undef'nd attrs */
201 char *lbl
; /* Ptr to label for messages */
202 char *alias
; /* Ptr to <alias> on command-line */
203 char *device
; /* Ptr to <device> on command-line */
204 char *p
; /* Temp ptr to char */
205 int noerr
; /* FLAG, TRUE if all's well */
206 int a_seen
; /* TRUE if -a seen on command-line */
207 int m_seen
; /* TRUE if -m seen on command-line */
208 int d_seen
; /* TRUE if -a seen on command-line */
209 int optchar
; /* Option extracted */
210 int exitcd
; /* Value to return at exit */
211 int nattrs
; /* Number of attributes on command */
214 /* Generate the label for messages */
215 lbl
= mklbl(argv
[0]);
217 /* Extract arguments - validate usage */
223 while ((optchar
= getopt(argc
, argv
, "a:d:m:")) != EOF
) switch (optchar
) {
226 if (!(a_seen
|| m_seen
|| d_seen
)) {
234 if (!(a_seen
|| m_seen
|| d_seen
)) {
242 if (!(a_seen
|| m_seen
|| d_seen
)) {
255 /* Write a usage message if we've seen a blatant error */
256 if (!(a_seen
|| m_seen
|| d_seen
) || !noerr
) {
257 stdmsg(MM_NRECOV
, lbl
, MM_ERROR
, E_USAGE
);
264 nattrs
= argc
- optind
;
267 /* putdev -a alias [attr=value [...]] */
273 stdmsg(MM_NRECOV
, lbl
, MM_ERROR
, E_USAGE
);
277 /* Attempt to add the new alias */
278 if (!(_adddevtabrec(alias
, &argv
[optind
]))) {
280 /* Attempt failed. Write appropriate error message. */
285 * EINVAL indicates that <alias> is not valid or "alias"
286 * was mentioned as <attr> in <attr>=<value> pair. If the
287 * alias is a valid alias, assume that's the problem.
291 if (_validalias(alias
))
293 else (void) snprintf(p
=msg
, sizeof(msg
), E_INVALIAS
, alias
);
294 stdmsg(MM_NRECOV
, lbl
, MM_ERROR
, p
);
299 * EEXIST indicates that the alias <alias> already exists
300 * in the device table.
304 (void) snprintf(msg
, sizeof(msg
), E_ALIASIS
, alias
);
305 stdmsg(MM_NRECOV
, lbl
, MM_ERROR
, msg
);
310 * EACCES and ENOENT indicate problems reading or writing
317 if (access(p
, R_OK
) == 0)
318 (void) snprintf(msg
, sizeof(msg
), E_NOMKDTAB
, p
);
320 (void) snprintf(msg
, sizeof(msg
), E_NODEVTAB
, p
);
321 stdmsg(MM_NRECOV
, lbl
, MM_ERROR
, msg
);
326 * EAGAIN indicates that an attribute was defined on the
327 * command line more than once.
331 stdmsg(MM_NRECOV
, lbl
, MM_ERROR
, E_MULTIPLE
);
336 * ENXIO indicates that a relative pathname was supplied
337 * for the cdevice, bdevice or pathname attributes. Full
338 * pathnames are required for these attributes.
341 stdmsg(MM_NRECOV
, lbl
, MM_ERROR
, E_RELPATH
);
346 * Some other problem (odd?)
350 (void) sprintf(msg
, E_INTERNAL
, errno
);
351 stdmsg(MM_NRECOV
, lbl
, MM_ERROR
, msg
);
359 /* putdev -m device attr=value [...] */
366 stdmsg(MM_NRECOV
, lbl
, MM_ERROR
, E_USAGE
);
370 /* Attempt to modify a device's record */
371 if (!(_moddevtabrec(device
, &argv
[optind
]))) {
373 /* Modification attempt failed */
378 * EINVAL indicates that "alias" was used as an attribute
379 * in an <attr>=<value> pair.
383 stdmsg(MM_NRECOV
, lbl
, MM_ERROR
, E_NOALIAS
);
388 * ENODEV indicates that the device that was to
389 * be modified doesn't exist.
393 (void) snprintf(msg
, sizeof(msg
), E_NODEV
, device
);
394 stdmsg(MM_NRECOV
, lbl
, MM_ERROR
, msg
);
399 * ENOENT indicates that the device-table doesn't exist.
403 (void) snprintf(msg
, sizeof(msg
), E_NODEVTAB
, _devtabpath());
404 stdmsg(MM_NRECOV
, lbl
, MM_ERROR
, msg
);
409 * EACCES indicates that there was a problem reading the
410 * old device table or creating the new table. If the
411 * old table is readable, assume that we can't create the
412 * new table. Otherwise, assume that the old table isn't
418 if (access(p
, R_OK
) == 0)
419 (void) snprintf(msg
, sizeof(msg
), E_NOMKDTAB
, p
);
421 (void) snprintf(msg
, sizeof(msg
), E_NODEVTAB
, p
);
422 stdmsg(MM_NRECOV
, lbl
, MM_ERROR
, msg
);
427 * EAGAIN indicates that an attribute was specified more than
428 * once on the command line.
432 stdmsg(MM_NRECOV
, lbl
, MM_ERROR
, E_MULTIPLE
);
437 * ENXIO indicates that a relative pathname was supplied
438 * for the cdevice, bdevice or pathname attributes. Full
439 * pathnames are required for these attributes.
442 stdmsg(MM_NRECOV
, lbl
, MM_ERROR
, E_RELPATH
);
447 * Some strange problem...
451 (void) sprintf(msg
, E_INTERNAL
, errno
);
452 stdmsg(MM_NRECOV
, lbl
, MM_ERROR
, msg
);
461 /* putdev -d device [attr [...]] */
465 stdmsg(MM_NRECOV
, lbl
, MM_ERROR
, E_USAGE
);
470 * Determine case (removing a device or attributes
476 /* putdev -d device */
478 /* Attempt to remove the specified device */
479 if (!(_rmdevtabrec(device
))) switch(errno
) {
482 * ENODEV indicates that the named device is not
483 * defined in the device table.
487 (void) snprintf(msg
, sizeof(msg
), E_NODEV
, device
);
488 stdmsg(MM_NRECOV
, lbl
, MM_ERROR
, msg
);
493 * ENOENT indicates that the device table can't
498 (void) snprintf(msg
, sizeof(msg
), E_NODEVTAB
, _devtabpath());
499 stdmsg(MM_NRECOV
, lbl
, MM_ERROR
, msg
);
504 * EACCES indicates that there was a problem reading the
505 * old device table or creating the new table. If the
506 * old table is readable, assume that we can't create the
507 * new table. Otherwise, assume that the old table isn't
513 if (access(p
, R_OK
) == 0)
514 (void) snprintf(msg
, sizeof(msg
), E_NOMKDTAB
, p
);
516 (void) snprintf(msg
, sizeof(msg
), E_NODEVTAB
, p
);
517 stdmsg(MM_NRECOV
, lbl
, MM_ERROR
, msg
);
522 * Some strange problem...
526 (void) sprintf(msg
, E_INTERNAL
, errno
);
527 stdmsg(MM_NRECOV
, lbl
, MM_ERROR
, msg
);
534 /* putdev -d device attr [attr [...]] */
537 * Attempt to remove the specified attributes from the
540 if (!(_rmdevtabattrs(device
, &argv
[optind
], &plist
))) switch(errno
) {
543 * EINVAL indicates that a named attribute was not
544 * defined for the specified device or "alias" was
545 * requested. If "plist" points to a list of attrs,
546 * the former is the problem. Otherwise, the latter
553 for (; *plist
; plist
++) {
554 (void) snprintf(msg
, sizeof(msg
), E_NOATTR
, *plist
);
555 stdmsg(MM_RECOVER
, lbl
, MM_WARNING
, msg
);
558 stdmsg(MM_NRECOV
, lbl
, MM_ERROR
, E_NOALIAS
);
564 * ENODEV indicates that the named device is not
565 * defined in the device table.
569 (void) snprintf(msg
, sizeof(msg
), E_NODEV
, device
);
570 stdmsg(MM_NRECOV
, lbl
, MM_ERROR
, msg
);
575 * ENOENT indicates that the device table can't
580 (void) snprintf(msg
, sizeof(msg
), E_NODEVTAB
, _devtabpath());
581 stdmsg(MM_NRECOV
, lbl
, MM_ERROR
, msg
);
586 * EACCES indicates that there was a problem reading the
587 * old device table or creating the new table. If the
588 * old table is readable, assume that we can't create the
589 * new table. Otherwise, assume that the old table isn't
595 if (access(p
, R_OK
) == 0)
596 (void) snprintf(msg
, sizeof(msg
), E_NOMKDTAB
, p
);
598 (void) snprintf(msg
, sizeof(msg
), E_NODEVTAB
, p
);
599 stdmsg(MM_NRECOV
, lbl
, MM_ERROR
, msg
);
604 * Some strange problem...
608 (void) sprintf(msg
, E_INTERNAL
, errno
);
609 stdmsg(MM_NRECOV
, lbl
, MM_ERROR
, msg
);
614 } /* End "putdev -d device attr [...]" case */
616 } /* End passes usage-check case */
621 /* Done. Return exit code (determined above) */