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 *  listdgrp.c
35 *
36 *  Contains
37 *	listdgrp	Writes on the standard output stream a list of devices
38 *			that belong to the specified device group
39 */
40
41#include	<sys/types.h>
42#include	<stdio.h>
43#include	<stdlib.h>
44#include	<string.h>
45#include	<errno.h>
46#include	<devmgmt.h>
47#include	<devtab.h>
48#include	<fmtmsg.h>
49
50
51/*
52 *  Local Definitions
53 *	TRUE		Boolean TRUE value (if not already defined)
54 *	FALSE		Boolean not-TRUE value (if not already defined)
55 */
56
57#ifndef	TRUE
58#define	TRUE		('t')
59#endif
60
61#ifndef	FALSE
62#define	FALSE		(0)
63#endif
64
65/*
66 *  Messages:
67 *	M_USAGE		Command usage error
68 *	M_NODGRP	Device group not found
69 *	M_DGRPTAB	Device-group table not found
70 *	M_ERROR		Internal error
71 */
72
73#define	M_USAGE		"usage: listdgrp dgroup"
74#define	M_NODGRP	"Device group not found: %s"
75#define	M_DGRPTAB	"Cannot open device-group table: %s"
76#define	M_ERROR		"Internal error, errno=%d"
77
78
79/*
80 *  Exit codes
81 *	EX_OK		Exiting okay, no problem
82 *	EX_ERROR	Some problem with the command
83 *	EX_NODGRPTAB	Device group table could not be opened
84 *	EX_NODGROUP	Device group couldn't be found
85 */
86
87#define	EX_OK		0
88#define	EX_ERROR	1
89#define	EX_NODGRPTAB	2
90#define	EX_NODGROUP	3
91
92
93/*
94 *  Macros
95 *	stdmsg(r,l,s,t)	    Write a message in standard format
96 *				r	Recoverability flag
97 *				l	Label
98 *				s	Severity
99 *				t	Tag
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 *  Global Variables
106 */
107
108
109/*
110 *  Static Variables
111 *
112 *	lbl	Buffer for the message label
113 */
114
115static	char	lbl[MM_MXLABELLN+1];
116static	char	msg[MM_MXTXTLN+1];
117
118/*
119 *  listdgrp <dgroup>
120 *
121 *	List the devices that belong to the device group <dgroup>.
122 *	It writes the list to the standard output file (stdout)
123 *	in a new-line list.
124 *
125 *  Returns:
126 *	0	Ok
127 *	1	Syntax or other error
128 *	2	Device table can't be opened
129 *	3	Device group doesn't exist
130 */
131
132int
133main(int argc, char **argv)
134{
135
136	/*
137	 *  Automatic data
138	 */
139
140	char	      **devices;	/* List of devices in the group */
141	char	      **pp;		/* Running pointer to device names */
142	char	       *cmdname;	/* Simple command name */
143	char	       *dgrptab;	/* The device-group table name */
144	char	       *dgroup;		/* Device group to list */
145	int		exitcode;	/* Value to return to the caller */
146	int		sev;		/* Message severity */
147	int		optchar;	/* Option char (from getopt()) */
148	int		usageerr;	/* TRUE if syntax error on command */
149
150
151	/* Build the message label from the (simple) command name */
152	if ((cmdname = strrchr(argv[0], '/')) != (char *) NULL) cmdname++;
153	else cmdname = argv[0];
154	(void) strlcat(strcpy(lbl, "UX:"), cmdname, sizeof(lbl));
155
156	/* Only write the text component of a message (this goes away in SVR4.1) */
157	(void) putenv("MSGVERB=text");
158
159	/*
160	 *  Parse the command line:
161	 *	- Options
162	 *	- Device group to display
163	 */
164
165	/*
166	 *  Extract options from the command line
167	 */
168
169	/* Initializations */
170	usageerr = FALSE;	/* No errors on the command line (yet) */
171
172	/*
173	 *  Loop until all of the command line options have been parced
174	 *  (and don't let getopt() write messages)
175	 */
176
177	opterr = FALSE;
178	while ((optchar = getopt(argc, argv, "")) != EOF) switch (optchar) {
179
180	/* Default case -- command usage error */
181	case '?':
182	default:
183	    usageerr = TRUE;
184	    break;
185	}
186
187	/* Check the argument count and extract the device group name */
188	if (usageerr || (optind != argc-1)) usageerr = TRUE;
189	else dgroup = argv[optind];
190
191	/* If there is a usage error, write an appropriate message and exit */
192	if (usageerr) {
193	    stdmsg(MM_NRECOV, lbl, MM_ERROR, M_USAGE);
194	    exit(EX_ERROR);
195	}
196
197	/* Open the device-group file (if there's one to be opened) */
198	if (!_opendgrptab("r")) {
199	    if (dgrptab = _dgrptabpath()) {
200		(void) snprintf(msg, sizeof(msg), M_DGRPTAB, dgrptab);
201		exitcode = EX_NODGRPTAB;
202		sev = MM_ERROR;
203	    } else {
204		(void) sprintf(msg, M_ERROR, errno);
205		exitcode = EX_ERROR;
206		sev = MM_HALT;
207	    }
208	    stdmsg(MM_NRECOV, lbl, sev, msg);
209	    exit(exitcode);
210	}
211
212
213	/*
214	 * Get the list of devices associated with the device group.
215	 * If we get one, write the list to the standard output.
216	 * Otherwise, write an appropriate error message
217	 */
218
219	exitcode = EX_OK;
220	if (devices = listdgrp(dgroup)) {
221	    for (pp = devices ; *pp ; pp++) (void) puts(*pp);
222	}
223	else {
224	    if (errno == EINVAL) {
225		(void) snprintf(msg, sizeof(msg), M_NODGRP, dgroup);
226		stdmsg(MM_NRECOV, lbl, MM_ERROR, msg);
227		exitcode = EX_NODGROUP;
228	    }
229	    else {
230		(void) sprintf(msg, M_ERROR, errno);
231		stdmsg(MM_NRECOV, lbl, MM_HALT, msg);
232		exitcode = EX_ERROR;
233	    }
234	}
235
236	/* Finished (now wasn't that special?) */
237	return(exitcode);
238}
239