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 /* 23 * Copyright (c) 1999 by Sun Microsystems, Inc. 24 * All rights reserved. 25 */ 26 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 27 /* All Rights Reserved */ 28 29 30 #ident "%Z%%M% %I% %E% SMI" /* from SVR4 bnu:cpmv.c 2.13 */ 31 32 #include "uucp.h" 33 34 /* 35 * copy f1 to f2 locally 36 * f1 -> source file name 37 * f2 -> destination file name 38 * return: 39 * 0 -> ok 40 * FAIL -> failed 41 */ 42 43 static int 44 xcp(f1, f2) 45 char *f1, *f2; 46 { 47 register int fd1, fd2; 48 register int nr, nw; 49 char buf[BUFSIZ]; 50 char *temp_p, temp[MAXFULLNAME]; 51 52 if ((fd1 = open(f1, O_RDONLY)) == -1) 53 return (FAIL); 54 55 if (DIRECTORY(f2)) { 56 (void) strcat(f2, "/"); 57 (void) strcat(f2, BASENAME(f1, '/')); 58 } 59 DEBUG(4, "file name is %s\n", f2); 60 61 (void) strcpy(temp, f2); 62 if ((temp_p = strrchr(temp, '/')) == NULL) 63 temp_p = temp; 64 else 65 temp_p++; 66 (void) strcpy(temp_p, ".TM.XXXXXX"); 67 temp_p = temp; 68 DEBUG(4, "temp name is %s\n", temp_p); 69 70 if ((fd2 = mkstemp(temp_p)) == -1) { 71 /* open of temp may fail if called from uidxcp() */ 72 /* in this case, try f2 since it is pre-created */ 73 temp_p = f2; 74 if ((fd2 = open(temp_p, O_CREAT | O_TRUNC | O_WRONLY, 75 PUB_FILEMODE)) == -1) { 76 DEBUG(5, "open of file returned errno %d\n", errno); 77 (void) close(fd1); 78 return (FAIL); 79 } 80 DEBUG(4, "using file name directly.%s\n", ""); 81 } 82 (void) chmod(temp_p, PUB_FILEMODE); 83 84 /* copy, looking for read or write failures */ 85 while ((nr = read(fd1, buf, sizeof (buf))) > 0 && 86 (nw = write(fd2, buf, nr)) == nr) 87 ; 88 89 close(fd1); 90 close(fd2); 91 92 if (nr != 0 || nw == -1) { 93 (void) unlink(temp_p); 94 return (FAIL); 95 } 96 if (temp_p != f2) { 97 if (rename(temp_p, f2) != 0) { 98 DEBUG(5, "rename failed: errno %d\n", errno); 99 (void) unlink(temp_p); 100 return (FAIL); 101 } 102 } 103 return (0); 104 } 105 106 107 /* 108 * move f1 to f2 locally 109 * returns: 110 * 0 -> ok 111 * FAIL -> failed 112 */ 113 114 int 115 xmv(f1, f2) 116 register char *f1, *f2; 117 { 118 register int do_unlink, ret; 119 struct stat sbuf; 120 121 if (stat(f2, &sbuf) == 0) 122 do_unlink = ((sbuf.st_mode & S_IFMT) == S_IFREG); 123 else 124 do_unlink = 1; 125 126 if (do_unlink) 127 (void) unlink(f2); /* i'm convinced this is the right */ 128 /* thing to do */ 129 if ((ret = link(f1, f2)) < 0) { 130 /* copy file */ 131 ret = xcp(f1, f2); 132 } 133 134 if (ret == 0) 135 (void) unlink(f1); 136 return (ret); 137 } 138 139 /* 140 * toCorrupt - move file to CORRUPTDIR 141 * return - none 142 */ 143 144 void 145 toCorrupt(file) 146 char *file; 147 { 148 char corrupt[MAXFULLNAME]; 149 150 (void) sprintf(corrupt, "%s/%s", CORRUPTDIR, BASENAME(file, '/')); 151 (void) link(file, corrupt); 152 ASSERT(unlink(file) == 0, Ct_UNLINK, file, errno); 153 } 154 155 /* 156 * append f1 to f2 157 * f1 -> source FILE pointer 158 * f2 -> destination FILE pointer 159 * return: 160 * SUCCESS -> ok 161 * FAIL -> failed 162 * 163 * to avoid confusing mail, turn lines with just "." into "..". 164 */ 165 int 166 xfappend(fp1, fp2) 167 register FILE *fp1, *fp2; 168 { 169 char buf[BUFSIZ]; 170 171 while (fgets(buf, sizeof (buf), fp1) != NULL) { 172 if (buf[0] == '.' && buf[1] == '\n') 173 strcpy(buf, "..\n"); 174 fputs(buf, fp2); 175 } 176 177 return (ferror(fp1) || ferror(fp2) ? FAIL : SUCCESS); 178 } 179 180 181 /* 182 * copy f1 to f2 locally under uid of uid argument 183 * f1 -> source file name 184 * f2 -> destination file name 185 * Uid and Euid are global 186 * return: 187 * 0 -> ok 188 * FAIL -> failed 189 * NOTES: 190 * for V7 systems, flip-flop between real and effective uid is 191 * not allowed, so fork must be done. This code will not 192 * work correctly when realuid is root on System 5 because of 193 * a bug in setuid. 194 */ 195 196 int 197 uidxcp(f1, f2) 198 char *f1, *f2; 199 { 200 int status; 201 char full[MAXFULLNAME]; 202 203 (void) strcpy(full, f2); 204 if (DIRECTORY(f2)) { 205 (void) strcat(full, "/"); 206 (void) strcat(full, BASENAME(f1, '/')); 207 } 208 209 /* create full owned by uucp */ 210 (void) close(creat(full, PUB_FILEMODE)); 211 (void) chmod(full, PUB_FILEMODE); 212 213 /* do file copy as read uid */ 214 #ifndef V7 215 (void) setuid(Uid); 216 status = xcp(f1, full); 217 (void) setuid(Euid); 218 return (status); 219 220 #else /* V7 */ 221 222 if (vfork() == 0) { 223 setuid(Uid); 224 _exit(xcp(f1, full)); 225 } 226 wait(&status); 227 return (status); 228 #endif 229 } 230 231 /* 232 * put file in public place 233 * if successful, filename is modified 234 * returns: 235 * 0 -> success 236 * FAIL -> failure 237 */ 238 int 239 putinpub(file, tmp, user) 240 char *file, *user, *tmp; 241 { 242 int status; 243 char fullname[MAXFULLNAME]; 244 245 (void) sprintf(fullname, "%s/%s/", Pubdir, user); 246 if (mkdirs(fullname, PUBMASK) != 0) { 247 /* cannot make directories */ 248 return (FAIL); 249 } 250 (void) strcat(fullname, BASENAME(file, '/')); 251 status = xmv(tmp, fullname); 252 if (status == 0) { 253 (void) strcpy(file, fullname); 254 (void) chmod(fullname, PUB_FILEMODE); 255 } 256 return (status); 257 } 258