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