/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright (c) 1999 by Sun Microsystems, Inc. * All rights reserved. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ #ident "%Z%%M% %I% %E% SMI" /* from SVR4 bnu:cpmv.c 2.13 */ #include "uucp.h" /* * copy f1 to f2 locally * f1 -> source file name * f2 -> destination file name * return: * 0 -> ok * FAIL -> failed */ static int xcp(f1, f2) char *f1, *f2; { register int fd1, fd2; register int nr, nw; char buf[BUFSIZ]; char *temp_p, temp[MAXFULLNAME]; if ((fd1 = open(f1, O_RDONLY)) == -1) return (FAIL); if (DIRECTORY(f2)) { (void) strcat(f2, "/"); (void) strcat(f2, BASENAME(f1, '/')); } DEBUG(4, "file name is %s\n", f2); (void) strcpy(temp, f2); if ((temp_p = strrchr(temp, '/')) == NULL) temp_p = temp; else temp_p++; (void) strcpy(temp_p, ".TM.XXXXXX"); temp_p = temp; DEBUG(4, "temp name is %s\n", temp_p); if ((fd2 = mkstemp(temp_p)) == -1) { /* open of temp may fail if called from uidxcp() */ /* in this case, try f2 since it is pre-created */ temp_p = f2; if ((fd2 = open(temp_p, O_CREAT | O_TRUNC | O_WRONLY, PUB_FILEMODE)) == -1) { DEBUG(5, "open of file returned errno %d\n", errno); (void) close(fd1); return (FAIL); } DEBUG(4, "using file name directly.%s\n", ""); } (void) chmod(temp_p, PUB_FILEMODE); /* copy, looking for read or write failures */ while ((nr = read(fd1, buf, sizeof (buf))) > 0 && (nw = write(fd2, buf, nr)) == nr) ; close(fd1); close(fd2); if (nr != 0 || nw == -1) { (void) unlink(temp_p); return (FAIL); } if (temp_p != f2) { if (rename(temp_p, f2) != 0) { DEBUG(5, "rename failed: errno %d\n", errno); (void) unlink(temp_p); return (FAIL); } } return (0); } /* * move f1 to f2 locally * returns: * 0 -> ok * FAIL -> failed */ int xmv(f1, f2) register char *f1, *f2; { register int do_unlink, ret; struct stat sbuf; if (stat(f2, &sbuf) == 0) do_unlink = ((sbuf.st_mode & S_IFMT) == S_IFREG); else do_unlink = 1; if (do_unlink) (void) unlink(f2); /* i'm convinced this is the right */ /* thing to do */ if ((ret = link(f1, f2)) < 0) { /* copy file */ ret = xcp(f1, f2); } if (ret == 0) (void) unlink(f1); return (ret); } /* * toCorrupt - move file to CORRUPTDIR * return - none */ void toCorrupt(file) char *file; { char corrupt[MAXFULLNAME]; (void) sprintf(corrupt, "%s/%s", CORRUPTDIR, BASENAME(file, '/')); (void) link(file, corrupt); ASSERT(unlink(file) == 0, Ct_UNLINK, file, errno); } /* * append f1 to f2 * f1 -> source FILE pointer * f2 -> destination FILE pointer * return: * SUCCESS -> ok * FAIL -> failed * * to avoid confusing mail, turn lines with just "." into "..". */ int xfappend(fp1, fp2) register FILE *fp1, *fp2; { char buf[BUFSIZ]; while (fgets(buf, sizeof (buf), fp1) != NULL) { if (buf[0] == '.' && buf[1] == '\n') strcpy(buf, "..\n"); fputs(buf, fp2); } return (ferror(fp1) || ferror(fp2) ? FAIL : SUCCESS); } /* * copy f1 to f2 locally under uid of uid argument * f1 -> source file name * f2 -> destination file name * Uid and Euid are global * return: * 0 -> ok * FAIL -> failed * NOTES: * for V7 systems, flip-flop between real and effective uid is * not allowed, so fork must be done. This code will not * work correctly when realuid is root on System 5 because of * a bug in setuid. */ int uidxcp(f1, f2) char *f1, *f2; { int status; char full[MAXFULLNAME]; (void) strcpy(full, f2); if (DIRECTORY(f2)) { (void) strcat(full, "/"); (void) strcat(full, BASENAME(f1, '/')); } /* create full owned by uucp */ (void) close(creat(full, PUB_FILEMODE)); (void) chmod(full, PUB_FILEMODE); /* do file copy as read uid */ #ifndef V7 (void) setuid(Uid); status = xcp(f1, full); (void) setuid(Euid); return (status); #else /* V7 */ if (vfork() == 0) { setuid(Uid); _exit(xcp(f1, full)); } wait(&status); return (status); #endif } /* * put file in public place * if successful, filename is modified * returns: * 0 -> success * FAIL -> failure */ int putinpub(file, tmp, user) char *file, *user, *tmp; { int status; char fullname[MAXFULLNAME]; (void) sprintf(fullname, "%s/%s/", Pubdir, user); if (mkdirs(fullname, PUBMASK) != 0) { /* cannot make directories */ return (FAIL); } (void) strcat(fullname, BASENAME(file, '/')); status = xmv(tmp, fullname); if (status == 0) { (void) strcpy(file, fullname); (void) chmod(fullname, PUB_FILEMODE); } return (status); }