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
xcp(f1,f2)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
xmv(f1,f2)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
toCorrupt(file)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
xfappend(fp1,fp2)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
uidxcp(f1,f2)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
putinpub(file,tmp,user)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