xref: /illumos-gate/usr/src/cmd/lp/lib/lp/files.c (revision 581cede61ac9c14d8d4ea452562a567189eead78)
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 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
28 /*	  All Rights Reserved  	*/
29 
30 
31 #pragma ident	"%Z%%M%	%I%	%E% SMI"
32 /* EMACS_MODES: !fill, lnumb, !overwrite, !nodelete, !picture */
33 
34 #include "stdio.h"
35 #include "fcntl.h"
36 #include "string.h"
37 #include "errno.h"
38 #include "pwd.h"
39 #include "sys/types.h"
40 #include "sys/stat.h"
41 #include "stdlib.h"
42 #include <stdarg.h>
43 #include <unistd.h>
44 #include "pwd.h"
45 
46 #include "lp.h"
47 
48 int
49 is_printer_uri(char *value)
50 {
51 	if (value == NULL)
52 		return (-1);
53 
54 	if ((value[0] == '/') && (access(value, F_OK) == 0))
55 		return (-1); /* a valid path */
56 
57 	if (strstr(value, "://") == NULL)
58 		return (-1); /* not in uri form */
59 
60 	return (0);
61 }
62 
63 /*
64  * To avoid a race condition, chown() should always be called before
65  * chmod().
66  */
67 int
68 chownmod(char *path, uid_t owner, gid_t group, mode_t mode)
69 {
70 	int rc;
71 
72 	if ((rc = Chown(path, owner, group)) == 0)
73 		rc = Chmod(path, mode);
74 
75 	return (rc);
76 }
77 
78 
79 int
80 fdprintf(int fd, char *fmt, ...)
81 {
82 	char    buf[BUFSIZ];
83 	va_list ap;
84 
85 	if (fd == 1)
86 		fflush(stdout);
87 	va_start(ap, fmt);
88 	vsnprintf(buf, sizeof (buf), fmt, ap);
89 	va_end(ap);
90 	return (Write(fd, buf, (int)strlen(buf)));
91 }
92 
93 char *
94 fdgets(char *buf, int len, int fd)
95 {
96 	char    tmp;
97 	int	count = 0;
98 
99 	memset(buf, NULL, len);
100 	while ((count < len) && (Read(fd, &tmp, 1) > 0))
101 		if ((buf[count++] = tmp) == '\n') break;
102 
103 	if (count != 0)
104 		return (buf);
105 	return (NULL);
106 }
107 
108 int
109 fdputs(char *buf, int fd)
110 {
111 	return (fdprintf(fd, "%s", buf));
112 }
113 
114 int
115 fdputc(char c, int fd)
116 {
117 	if (fd == 1)
118 		fflush(stdout);
119 	return (write(fd, &c, 1));
120 }
121 
122 int
123 open_locked(char *path, char *type, mode_t mode)
124 {
125 	struct flock		l;
126 	int			fd,
127 				oflag,
128 				create,
129 				truncate = 0;
130 
131 	if (!path || !type) {
132 		errno = EINVAL;
133 		return (-1);
134 	}
135 
136 #define	plus (type[1] == '+')
137 	switch (type[0]) {
138 	case 'w':
139 		oflag = plus? O_RDWR : O_WRONLY;
140 		create = 1;
141 		truncate = 1;
142 		break;
143 	case 'a':
144 		oflag = (plus? O_RDWR : O_WRONLY) | O_APPEND;
145 		create = 1;
146 		break;
147 	case 'r':
148 		oflag = plus? O_RDWR : O_RDONLY;
149 		create = 0;
150 		break;
151 	default:
152 		errno = EINVAL;
153 		return (-1);
154 	}
155 	if ((fd = Open(path, oflag, mode)) == -1)
156 		if (errno == ENOENT && create) {
157 			int		old_umask = umask(0);
158 			int		save_errno;
159 
160 			if ((fd = Open(path, oflag|O_CREAT, mode)) != -1)
161 				chown_lppath(path);
162 			save_errno = errno;
163 			if (old_umask)
164 				umask(old_umask);
165 			errno = save_errno;
166 		}
167 
168 	if (fd == -1)
169 	switch (errno) {
170 	case ENOTDIR:
171 		errno = EACCES;
172 		/* FALLTHROUGH */
173 	default:
174 		return (-1);
175 	}
176 
177 	l.l_type = (oflag & (O_WRONLY|O_RDWR)? F_WRLCK : F_RDLCK);
178 	l.l_whence = 1;
179 	l.l_start = 0;
180 	l.l_len = 0;
181 	if (Fcntl(fd, F_SETLK, &l) == -1) {
182 		/*
183 		 * Early UNIX op. sys. have wrong errno.
184 		 */
185 		if (errno == EACCES)
186 			errno = EAGAIN;
187 		Close(fd);
188 		return (-1);
189 	}
190 
191 	if (truncate) {
192 		if ((lseek(fd, 0, SEEK_SET) == (off_t)-1) ||
193 		    (ftruncate(fd, 0) == -1)) {
194 			Close(fd);
195 			return (-1);
196 		}
197 	}
198 
199 	return (fd);
200 }
201 
202 
203 FILE *
204 open_lpfile(char *path, char *type, mode_t mode)
205 {
206 	FILE		*fp = NULL;
207 	int		fd;
208 
209 	if ((fd = open_locked(path, type, mode)) >= 0) {
210 		errno = 0;	/* fdopen() may fail and not set errno */
211 		if (!(fp = fdopen(fd, type))) {
212 			Close(fd);
213 		}
214 	}
215 	return (fp);
216 }
217 int
218 close_lpfile(FILE *fp)
219 {
220 	return (fclose(fp));
221 }
222 
223 /*
224  * chown_lppath()
225  */
226 
227 int
228 chown_lppath(char *path)
229 {
230 	static uid_t	lp_uid;
231 
232 	static gid_t	lp_gid;
233 
234 	static int	gotids = 0;
235 
236 	struct passwd	*ppw;
237 
238 
239 	if (!gotids) {
240 		if (!(ppw = getpwnam(LPUSER)))
241 			ppw = getpwnam(ROOTUSER);
242 		endpwent();
243 		if (!ppw)
244 			return (-1);
245 		lp_uid = ppw->pw_uid;
246 		lp_gid = ppw->pw_gid;
247 		gotids = 1;
248 	}
249 	return (Chown(path, lp_uid, lp_gid));
250 }
251 
252 /*
253  * rmfile() - UNLINK FILE BUT NO COMPLAINT IF NOT THERE
254  */
255 
256 int
257 rmfile(char *path)
258 {
259 	return (Unlink(path) == 0 || errno == ENOENT);
260 }
261 
262 /*
263  * loadline() - LOAD A ONE-LINE CHARACTER STRING FROM FILE
264  */
265 
266 char *
267 loadline(char *path)
268 {
269 	int fd;
270 	register char		*ret;
271 	register int		len;
272 	char			buf[BUFSIZ];
273 
274 	if ((fd = open_locked(path, "r", MODE_READ)) < 0)
275 		return (0);
276 
277 	if (fdgets(buf, BUFSIZ, fd)) {
278 		if ((len = strlen(buf)) && buf[len - 1] == '\n')
279 			buf[--len] = 0;
280 		if ((ret = Malloc(len + 1)))
281 			strcpy(ret, buf);
282 	} else {
283 		errno = 0;
284 		ret = 0;
285 	}
286 
287 	close(fd);
288 	return (ret);
289 }
290 
291 /*
292  * loadstring() - LOAD A CHARACTER STRING FROM FILE
293  */
294 
295 char *
296 loadstring(char *path)
297 {
298 	int fd;
299 	register char		*ret;
300 	register int		len;
301 
302 	if ((fd = open_locked(path, "r", MODE_READ)) < 0)
303 		return (0);
304 
305 	if ((ret = sop_up_rest(fd, (char *)0))) {
306 		if ((len = strlen(ret)) && ret[len - 1] == '\n')
307 			ret[len - 1] = 0;
308 	} else
309 		errno = 0;
310 
311 	close(fd);
312 	return (ret);
313 }
314 
315 /*
316  * dumpstring() - DUMP CHARACTER STRING TO FILE
317  */
318 
319 int
320 dumpstring(char *path, char *str)
321 {
322 	int fd;
323 
324 	if (!str)
325 		return (rmfile(path));
326 
327 	if ((fd = open_locked(path, "w", MODE_READ)) < 0)
328 		return (-1);
329 	fdprintf(fd, "%s\n", str);
330 	close(fd);
331 	return (0);
332 }
333