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 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
23 /* All Rights Reserved */
24
25
26 /*
27 * Copyright (c) 1996-1998, 2001 by Sun Microsystems, Inc.
28 * All rights reserved.
29 */
30
31 #pragma ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.3 */
32 /*LINTLIBRARY*/
33
34 #include <stdio.h>
35 #include <ctype.h>
36 #include <string.h>
37 #include <limits.h>
38 #include <sys/types.h>
39 #include <sys/stat.h>
40 #include "valtools.h"
41 #include <stdlib.h>
42 #include <fcntl.h>
43 #include <unistd.h>
44 #include "libadm.h"
45
46 #define E_SYNTAX "does not meet suggested filename syntax standard"
47 #define E_READ "is not readable"
48 #define E_WRITE "is not writable"
49 #define E_EXEC "is not executable"
50 #define E_CREAT "cannot be created"
51 #define E_ABSOLUTE "must begin with a slash (/)"
52 #define E_RELATIVE "must not begin with a slash (/)"
53 #define E_EXIST "does not exist"
54 #define E_NEXIST "must not already exist"
55 #define E_BLK "must specify a block special device"
56 #define E_CHR "must specify a character special device"
57 #define E_DIR "must specify a directory"
58 #define E_REG "must be a regular file"
59 #define E_NONZERO "must be a file of non-zero length"
60
61 #define H_READ "must be readable"
62 #define H_WRITE "must be writable"
63 #define H_EXEC "must be executable"
64 #define H_CREAT "will be created if it does not exist"
65 #define H_ABSOLUTE E_ABSOLUTE
66 #define H_RELATIVE E_RELATIVE
67 #define H_EXIST "must already exist"
68 #define H_NEXIST "must not already exist"
69 #define H_BLK E_BLK
70 #define H_CHR E_CHR
71 #define H_DIR E_DIR
72 #define H_REG E_REG
73 #define H_NONZERO E_NONZERO
74
75 #define MSGSIZ 1024
76 #define STDHELP \
77 "A pathname is a filename, optionally preceded by parent directories."
78
79 static char *errstr;
80 static char *badset = "*?[]{}()<> \t'`\"\\|^";
81
82 static void
addhlp(char * msg,char * text)83 addhlp(char *msg, char *text)
84 {
85 static int count;
86
87 if (text == NULL) {
88 count = 0;
89 return;
90 }
91 if (!count++)
92 (void) strcat(msg, " The pathname you enter:");
93 (void) strcat(msg, "\\n\\t-\\ ");
94 (void) strcat(msg, text);
95 }
96
97 static char *
sethlp(int pflags)98 sethlp(int pflags)
99 {
100 char *msg;
101
102 msg = calloc(MSGSIZ, sizeof (char));
103 addhlp(msg, NULL); /* initialize count */
104 (void) strcpy(msg, STDHELP);
105
106 if (pflags & P_EXIST)
107 addhlp(msg, H_EXIST);
108 else if (pflags & P_NEXIST)
109 addhlp(msg, H_NEXIST);
110
111 if (pflags & P_ABSOLUTE)
112 addhlp(msg, H_ABSOLUTE);
113 else if (pflags & P_RELATIVE)
114 addhlp(msg, H_RELATIVE);
115
116 if (pflags & P_READ)
117 addhlp(msg, H_READ);
118 if (pflags & P_WRITE)
119 addhlp(msg, H_WRITE);
120 if (pflags & P_EXEC)
121 addhlp(msg, H_EXEC);
122 if (pflags & P_CREAT)
123 addhlp(msg, H_CREAT);
124
125 if (pflags & P_BLK)
126 addhlp(msg, H_BLK);
127 else if (pflags & P_CHR)
128 addhlp(msg, H_CHR);
129 else if (pflags & P_DIR)
130 addhlp(msg, H_DIR);
131 else if (pflags & P_REG)
132 addhlp(msg, H_REG);
133
134 if (pflags & P_NONZERO)
135 addhlp(msg, H_NONZERO);
136
137 return (msg);
138 }
139
140 int
ckpath_stx(int pflags)141 ckpath_stx(int pflags)
142 {
143 if (((pflags & P_ABSOLUTE) && (pflags & P_RELATIVE)) ||
144 ((pflags & P_NEXIST) && (pflags &
145 (P_EXIST|P_NONZERO|P_READ|P_WRITE|P_EXEC))) ||
146 ((pflags & P_CREAT) && (pflags & (P_EXIST|P_NEXIST|P_BLK|P_CHR))) ||
147 ((pflags & P_BLK) && (pflags & (P_CHR|P_REG|P_DIR|P_NONZERO))) ||
148 ((pflags & P_CHR) && (pflags & (P_REG|P_DIR|P_NONZERO))) ||
149 ((pflags & P_DIR) && (pflags & P_REG))) {
150 return (1);
151 }
152 return (0);
153 }
154
155 int
ckpath_val(char * path,int pflags)156 ckpath_val(char *path, int pflags)
157 {
158 struct stat64 status;
159 int fd;
160 char *pt;
161
162 if ((pflags & P_RELATIVE) && (*path == '/')) {
163 errstr = E_RELATIVE;
164 return (1);
165 }
166 if ((pflags & P_ABSOLUTE) && (*path != '/')) {
167 errstr = E_ABSOLUTE;
168 return (1);
169 }
170 if (stat64(path, &status)) {
171 if (pflags & P_EXIST) {
172 errstr = E_EXIST;
173 return (1);
174 }
175 for (pt = path; *pt; pt++) {
176 if (!isprint((unsigned char)*pt) ||
177 strchr(badset, *pt)) {
178 errstr = E_SYNTAX;
179 return (1);
180 }
181 }
182 if (pflags & P_CREAT) {
183 if (pflags & P_DIR) {
184 if ((mkdir(path, 0755)) != 0) {
185 errstr = E_CREAT;
186 return (1);
187 }
188 } else {
189 if ((fd = creat(path, 0644)) < 0) {
190 errstr = E_CREAT;
191 return (1);
192 }
193 (void) close(fd);
194 }
195 }
196 return (0);
197 } else if (pflags & P_NEXIST) {
198 errstr = E_NEXIST;
199 return (1);
200 }
201 if ((status.st_mode & S_IFMT) == S_IFREG) {
202 /* check non zero status */
203 if ((pflags & P_NONZERO) && (status.st_size < 1)) {
204 errstr = E_NONZERO;
205 return (1);
206 }
207 }
208 if ((pflags & P_CHR) && ((status.st_mode & S_IFMT) != S_IFCHR)) {
209 errstr = E_CHR;
210 return (1);
211 }
212 if ((pflags & P_BLK) && ((status.st_mode & S_IFMT) != S_IFBLK)) {
213 errstr = E_BLK;
214 return (1);
215 }
216 if ((pflags & P_DIR) && ((status.st_mode & S_IFMT) != S_IFDIR)) {
217 errstr = E_DIR;
218 return (1);
219 }
220 if ((pflags & P_REG) && ((status.st_mode & S_IFMT) != S_IFREG)) {
221 errstr = E_REG;
222 return (1);
223 }
224 if ((pflags & P_READ) && !(status.st_mode & S_IREAD)) {
225 errstr = E_READ;
226 return (1);
227 }
228 if ((pflags & P_WRITE) && !(status.st_mode & S_IWRITE)) {
229 errstr = E_WRITE;
230 return (1);
231 }
232 if ((pflags & P_EXEC) && !(status.st_mode & S_IEXEC)) {
233 errstr = E_EXEC;
234 return (1);
235 }
236 return (0);
237 }
238
239 void
ckpath_err(int pflags,char * error,char * input)240 ckpath_err(int pflags, char *error, char *input)
241 {
242 char buffer[2048];
243 char *defhlp;
244
245 if (input) {
246 if (ckpath_val(input, pflags)) {
247 (void) sprintf(buffer, "Pathname %s.", errstr);
248 puterror(stdout, buffer, error);
249 return;
250 }
251 }
252 defhlp = sethlp(pflags);
253 puterror(stdout, defhlp, error);
254 free(defhlp);
255 }
256
257 void
ckpath_hlp(int pflags,char * help)258 ckpath_hlp(int pflags, char *help)
259 {
260 char *defhlp;
261
262 defhlp = sethlp(pflags);
263 puthelp(stdout, defhlp, help);
264 free(defhlp);
265 }
266
267 int
ckpath(char * pathval,int pflags,char * defstr,char * error,char * help,char * prompt)268 ckpath(char *pathval, int pflags, char *defstr, char *error, char *help,
269 char *prompt)
270 {
271 char *defhlp,
272 input[MAX_INPUT],
273 buffer[256];
274
275 if ((pathval == NULL) || ckpath_stx(pflags))
276 return (2); /* usage error */
277
278 if (!prompt) {
279 if (pflags & P_ABSOLUTE)
280 prompt = "Enter an absolute pathname";
281 else if (pflags & P_RELATIVE)
282 prompt = "Enter a relative pathname";
283 else
284 prompt = "Enter a pathname";
285 }
286 defhlp = sethlp(pflags);
287
288 start:
289 putprmpt(stderr, prompt, NULL, defstr);
290 if (getinput(input)) {
291 free(defhlp);
292 return (1);
293 }
294
295 if (strlen(input) == 0) {
296 if (defstr) {
297 (void) strcpy(pathval, defstr);
298 free(defhlp);
299 return (0);
300 }
301 puterror(stderr, NULL, "Input is required.");
302 goto start;
303 }
304 if (strcmp(input, "?") == 0) {
305 puthelp(stderr, defhlp, help);
306 goto start;
307 }
308 if (ckquit && (strcmp(input, "q") == 0)) {
309 free(defhlp);
310 return (3);
311 }
312
313 if (ckpath_val(input, pflags)) {
314 (void) sprintf(buffer, "Pathname %s.", errstr);
315 puterror(stderr, buffer, error);
316 goto start;
317 }
318 (void) strcpy(pathval, input);
319 free(defhlp);
320 return (0);
321 }
322