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 * Copyright (c) 2001 by Sun Microsystems, Inc. 27 * All rights reserved. 28 */ 29 30 #ident "%Z%%M% %I% %E% SMI" /* from SVR4 bnu:expfile.c 2.10 */ 31 32 #include "uucp.h" 33 34 /* 35 * expand file name expansion is based on first characters 36 * / -> fully qualified pathname. no 37 * processing necessary 38 * ~ -> prepended with login directory 39 * ~/ -> prepended with Pubdir 40 * default -> prepended with current directory 41 * file -> filename to expand 42 * returns: 43 * 0 -> ok 44 * FAIL -> no Wrkdir name available 45 */ 46 int 47 expfile(file) 48 register char *file; 49 { 50 register char *fpart, *up; 51 uid_t uid; 52 char user[NAMESIZE], save[MAXFULLNAME]; 53 extern int gninfo(), canPath(); 54 55 if (strlcpy(save, file, sizeof (save)) >= sizeof (save)) 56 return(FAIL); 57 if (*file != '/') 58 if (*file == '~') { 59 /* find / and copy user part */ 60 for (fpart = save + 1, up = user; *fpart != '\0' 61 && *fpart != '/'; fpart++) 62 *up++ = *fpart; 63 *up = '\0'; 64 if ((user[0]=='\0') || (gninfo(user, &uid, file) != 0)){ 65 (void) strcpy(file, Pubdir); 66 } 67 if (strlen(file) + strlen(fpart) + 1 > (unsigned)MAXFULLNAME) 68 return(FAIL); 69 (void) strcat(file, fpart); 70 } else { 71 if (strlen(Wrkdir) + strlen(save) + 2 > (unsigned)MAXFULLNAME) 72 return(FAIL); 73 (void) sprintf(file, "%s/%s", Wrkdir, save); 74 if (Wrkdir[0] == '\0') 75 return(FAIL); 76 } 77 78 if (canPath(file) != 0) { /* I don't think this will ever fail */ 79 (void) strcpy(file, CORRUPTDIR); 80 return(FAIL); 81 } else 82 return(0); 83 } 84 85 86 /* 87 * make all necessary directories 88 * name -> directory to make 89 * mask -> mask to use during directory creation 90 * return: 91 * 0 -> success 92 * FAIL -> failure 93 */ 94 int 95 mkdirs(name, mask) 96 mode_t mask; 97 register char *name; 98 { 99 register char *p; 100 mode_t omask; 101 char dir[MAXFULLNAME]; 102 103 strcpy(dir, name); 104 if (*LASTCHAR(dir) != '/') 105 (void) strcat(dir, "/"); 106 p = dir + 1; 107 for (;;) { 108 if ((p = strchr(p, '/')) == NULL) 109 return(0); 110 *p = '\0'; 111 if (DIRECTORY(dir)) { 112 /* if directory exists and is owned by uucp, child's 113 permissions should be no more open than parent */ 114 if (__s_.st_uid == UUCPUID) 115 mask |= ((~__s_.st_mode) & PUB_DIRMODE); 116 } else { 117 DEBUG(4, "mkdir - %s\n", dir); 118 omask = umask(mask); 119 if (mkdir(dir, PUB_DIRMODE) == FAIL) { 120 umask(omask); 121 return (FAIL); 122 } 123 umask(omask); 124 } 125 *p++ = '/'; 126 } 127 /* NOTREACHED */ 128 } 129 130 /* 131 * expand file name and check return 132 * print error if it failed. 133 * file -> file name to check 134 * returns: 135 * 0 -> ok 136 * FAIL -> if expfile failed 137 */ 138 int 139 ckexpf(file) 140 char *file; 141 { 142 if (expfile(file) == 0) 143 return(0); 144 145 fprintf(stderr, gettext("Illegal filename (%s).\n"), file); 146 return(FAIL); 147 } 148 149 150 /* 151 * make canonical path out of path passed as argument. 152 * 153 * Eliminate redundant self-references like // or /./ 154 * (A single terminal / will be preserved, however.) 155 * Dispose of references to .. in the path names. 156 * In relative path names, this means that .. or a/../.. 157 * will be treated as an illegal reference. 158 * In full paths, .. is always allowed, with /.. treated as / 159 * 160 * returns: 161 * 0 -> path is now in canonical form 162 * FAIL -> relative path contained illegal .. reference 163 */ 164 165 int 166 canPath(path) 167 register char *path; /* path is modified in place */ 168 { 169 register char *to, *fr; 170 171 to = fr = path; 172 if (*fr == '/') *to++ = *fr++; 173 for (;;) { 174 /* skip past references to self and validate references to .. */ 175 for (;;) { 176 if (*fr == '/') { 177 fr++; 178 continue; 179 } 180 if ((strncmp(fr, "./", 2) == SAME) || EQUALS(fr, ".")) { 181 fr++; 182 continue; 183 } 184 if ((strncmp(fr, "../", 3) == SAME) || EQUALS(fr, "..")) { 185 fr += 2; 186 /* /.. is / */ 187 if (((to - 1) == path) && (*path == '/')) continue; 188 /* error if no previous component */ 189 if (to <= path) return (FAIL); 190 /* back past previous component */ 191 while ((--to > path) && (to[-1] != '/')); 192 continue; 193 } 194 break; 195 } 196 /* 197 * What follows is a legitimate component, 198 * terminated by a null or a / 199 */ 200 if (*fr == '\0') break; 201 while (((*to++ = *fr) != '\0') && (*fr++ != '/')); 202 } 203 /* null path is . */ 204 if (to == path) *to++ = '.'; 205 *to = '\0'; 206 return (0); 207 } 208