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