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 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 * 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 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 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 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 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 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