1/*	$NetBSD: pathconf.c,v 1.6 2003/08/07 10:04:40 agc Exp $	*/
2
3/*
4 * Copyright (c) 1993
5 *	The Regents of the University of California.  All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 *    may be used to endorse or promote products derived from this software
17 *    without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32#ifndef lint
33static char copyright[] =
34"@(#) Copyright (c) 1993\n\
35	The Regents of the University of California.  All rights reserved.\n";
36#endif /* not lint */
37
38#ifndef lint
39#if 0
40static char sccsid[] = "@(#)pathconf.c	8.1 (Berkeley) 6/6/93";
41#else
42static char rcsid[] = "$NetBSD: pathconf.c,v 1.6 2003/08/07 10:04:40 agc Exp $";
43#endif
44#endif /* not lint */
45
46#include <sys/param.h>
47#include <sys/sysctl.h>
48#include <sys/unistd.h>
49
50#include <errno.h>
51#include <stdio.h>
52#include <stdlib.h>
53#include <string.h>
54
55#define PC_NAMES { \
56	{ 0, 0 }, \
57	{ "link_max", CTLTYPE_INT }, \
58	{ "max_canon", CTLTYPE_INT }, \
59	{ "max_input", CTLTYPE_INT }, \
60	{ "name_max", CTLTYPE_INT }, \
61	{ "path_max", CTLTYPE_INT }, \
62	{ "pipe_buf", CTLTYPE_INT }, \
63	{ "chown_restricted", CTLTYPE_INT }, \
64	{ "no_trunc", CTLTYPE_INT }, \
65	{ "vdisable", CTLTYPE_INT }, \
66}
67#define PC_MAXID 10
68
69struct ctlname pcnames[] = PC_NAMES;
70char names[BUFSIZ];
71
72struct list {
73	struct	ctlname *list;
74	int	size;
75};
76struct list pclist = { pcnames, PC_MAXID };
77
78int	Aflag, aflag, nflag, wflag, stdinflag;
79
80int
81main(argc, argv)
82	int argc;
83	char *argv[];
84{
85	char *path;
86	int ch;
87
88	while ((ch = getopt(argc, argv, "Aan")) != -1) {
89		switch (ch) {
90
91		case 'A':
92			Aflag = 1;
93			break;
94
95		case 'a':
96			aflag = 1;
97			break;
98
99		case 'n':
100			nflag = 1;
101			break;
102
103		default:
104			usage();
105		}
106	}
107	argc -= optind;
108	argv += optind;
109
110	if (argc == 0)
111		usage();
112	path = *argv++;
113	if (strcmp(path, "-") == 0)
114		stdinflag = 1;
115	argc--;
116	if (Aflag || aflag) {
117		listall(path, &pclist);
118		exit(0);
119	}
120	if (argc == 0)
121		usage();
122	while (argc-- > 0)
123		parse(path, *argv, 1);
124	exit(0);
125}
126
127/*
128 * List all variables known to the system.
129 */
130listall(path, lp)
131	char *path;
132	struct list *lp;
133{
134	int lvl2;
135
136	if (lp->list == 0)
137		return;
138	for (lvl2 = 0; lvl2 < lp->size; lvl2++) {
139		if (lp->list[lvl2].ctl_name == 0)
140			continue;
141		parse(path, lp->list[lvl2].ctl_name, Aflag);
142	}
143}
144
145/*
146 * Parse a name into an index.
147 * Lookup and print out the attribute if it exists.
148 */
149parse(pathname, string, flags)
150	char *pathname;
151	char *string;
152	int flags;
153{
154	int indx, value;
155	char *bufp, buf[BUFSIZ];
156
157	bufp = buf;
158	snprintf(buf, BUFSIZ, "%s", string);
159	if ((indx = findname(string, "top", &bufp, &pclist)) == -1)
160		return;
161	if (bufp) {
162		fprintf(stderr, "name %s in %s is unknown\n", *bufp, string);
163		return;
164	}
165	if (stdinflag)
166		value = fpathconf(0, indx);
167	else
168		value = pathconf(pathname, indx);
169	if (value == -1) {
170		if (flags == 0)
171			return;
172		switch (errno) {
173		case EOPNOTSUPP:
174			fprintf(stderr, "%s: value is not available\n", string);
175			return;
176		case ENOTDIR:
177			fprintf(stderr, "%s: specification is incomplete\n",
178			    string);
179			return;
180		case ENOMEM:
181			fprintf(stderr, "%s: type is unknown to this program\n",
182			    string);
183			return;
184		default:
185			perror(string);
186			return;
187		}
188	}
189	if (!nflag)
190		fprintf(stdout, "%s = ", string);
191	fprintf(stdout, "%d\n", value);
192}
193
194/*
195 * Scan a list of names searching for a particular name.
196 */
197findname(string, level, bufp, namelist)
198	char *string;
199	const char *level;
200	char **bufp;
201	struct list *namelist;
202{
203	char *name;
204	int i;
205
206	if (namelist->list == 0 || (name = strsep(bufp, ".")) == NULL) {
207		fprintf(stderr, "%s: incomplete specification\n", string);
208		return (-1);
209	}
210	for (i = 0; i < namelist->size; i++)
211		if (namelist->list[i].ctl_name != NULL &&
212		    strcmp(name, namelist->list[i].ctl_name) == 0)
213			break;
214	if (i == namelist->size) {
215		fprintf(stderr, "%s level name %s in %s is invalid\n",
216		    level, name, string);
217		return (-1);
218	}
219	return (i);
220}
221
222usage()
223{
224
225	(void)fprintf(stderr, "usage:\t%s\n\t%s\n\t%s\n",
226	    "pathname [-n] variable ...",
227	    "pathname [-n] -a", "pathname [-n] -A");
228	exit(1);
229}
230