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
is_printer_uri(char * value)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
chownmod(char * path,uid_t owner,gid_t group,mode_t mode)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
fdprintf(int fd,char * fmt,...)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 *
fdgets(char * buf,int len,int fd)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
fdputs(char * buf,int fd)109 fdputs(char *buf, int fd)
110 {
111 return (fdprintf(fd, "%s", buf));
112 }
113
114 int
fdputc(char c,int fd)115 fdputc(char c, int fd)
116 {
117 if (fd == 1)
118 fflush(stdout);
119 return (write(fd, &c, 1));
120 }
121
122 int
open_locked(char * path,char * type,mode_t mode)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 *
open_lpfile(char * path,char * type,mode_t mode)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
close_lpfile(FILE * fp)218 close_lpfile(FILE *fp)
219 {
220 return (fclose(fp));
221 }
222
223 /*
224 * chown_lppath()
225 */
226
227 int
chown_lppath(char * path)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
rmfile(char * path)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 *
loadline(char * path)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 *
loadstring(char * path)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
dumpstring(char * path,char * str)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