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 (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 #include <stdio.h>
28 #include <fcntl.h>
29 #include <string.h>
30 #include <mntent.h>
31 #include <sys/syscall.h>
32 #include <sys/param.h>
33 #include <sys/sysmacros.h>
34 #include <sys/types.h>
35 #include <sys/stat.h>
36 #include <dirent.h>
37 #include "s5sysmacros.h"
38 #include "compat.h"
39
40 #define PRINTER_DIR "/etc/lp/printers/"
41 #define PRINTER_CONFIG_FILE "/configuration"
42 #define MNT_LINE_MAX 1024
43
44 #define GETTOK(xx, ll) \
45 if ((xx = strtok(ll, sepstr)) == NULL) \
46 return (-1); \
47 if (strcmp(xx, dash) == 0) \
48 xx = NULL
49
50 char *mktemp();
51
52 static void getPrinterInfo(char *, FILE *);
53 static char sepstr[] = " \t\n";
54 static char dash[] = "-";
55 static int open_printcap(void);
56
57 /* SVR4/SunOS 5.0 equivalent modes */
58 #define N_O_NDELAY 0x04
59 #define N_O_SYNC 0x10
60 #define N_O_NONBLOCK 0x80
61 #define N_O_CREAT 0x100
62 #define N_O_TRUNC 0x200
63 #define N_O_EXCL 0x400
64
65 /* Mask corresponding to the bits above in SunOS 4.x */
66 #define FLAGS_MASK (O_SYNC|O_NONBLOCK|O_CREAT|O_TRUNC|O_EXCL \
67 |_FNDELAY|_FNBIO)
68
69 int
open_com(char * path,int flags,int mode)70 open_com(char *path, int flags, int mode)
71 {
72 int fd, fd2, pathl, inspt, ret = 0;
73 int nflags = flags;
74 char loc[] = "/lib/locale";
75 char *loct = NULL;
76
77 if (flags & FLAGS_MASK) {
78 nflags = flags & ~FLAGS_MASK;
79 if (flags & O_SYNC)
80 nflags |= N_O_SYNC;
81 if (flags & (_FNDELAY|O_NONBLOCK)) {
82 nflags |= N_O_NONBLOCK;
83 }
84 if (flags & O_CREAT)
85 nflags |= N_O_CREAT;
86 if (flags & O_TRUNC)
87 nflags |= N_O_TRUNC;
88 if (flags & O_EXCL)
89 nflags |= N_O_EXCL;
90 if (flags & _FNBIO)
91 nflags |= N_O_NDELAY;
92 }
93
94 /* change path from ..../lib/locale/.... to ..../lib/oldlocale/.... XXX */
95
96 if ((loct = (char *)_strstr(path, loc)) != NULL) { /* /lib/locale ? */
97 char locbuf[MAXPATHLEN+100]; /* to hold new locale path */
98
99 pathl = strlen(path);
100 inspt = pathl - strlen(loct) + 5; /* pos to add "old" */
101 (void) strncpy(locbuf, path, inspt); /* copy path upto lib */
102 locbuf[inspt] = '\0'; /* make it a string */
103 strcat(locbuf, "old"); /* add "old" */
104 strcat(locbuf, loct+5); /* add remainer of path */
105 return (_syscall(SYS_openat, AT_FDCWD, locbuf, nflags, mode));
106 }
107
108 if (strcmp(path, "/etc/mtab") == 0)
109 return (open_mnt("/etc/mnttab", "mtab", nflags, mode));
110
111 if (strcmp(path, "/etc/fstab") == 0)
112 return (open_mnt("/etc/vfstab", "fstab", nflags, mode));
113
114 if (strcmp(path, "/etc/printcap") == 0) {
115 if ((fd = _syscall(SYS_openat, AT_FDCWD, path, nflags, mode))
116 >= 0)
117 return (fd);
118 return (open_printcap());
119 }
120
121 if (strcmp(path, "/etc/utmp") == 0 ||
122 strcmp(path, "/var/adm/utmp") == 0) {
123 fd = _syscall(SYS_openat,
124 AT_FDCWD, "/var/adm/utmpx", nflags, mode);
125 if (fd >= 0)
126 fd_add(fd, UTMPX_MAGIC_FLAG);
127 return (fd);
128 }
129
130 if (strcmp(path, "/var/adm/wtmp") == 0) {
131 fd = _syscall(SYS_openat,
132 AT_FDCWD, "/var/adm/wtmpx", nflags, mode);
133 if (fd >= 0)
134 fd_add(fd, UTMPX_MAGIC_FLAG);
135 return (fd);
136 }
137
138 return (_syscall(SYS_openat, AT_FDCWD, path, nflags, mode));
139 }
140
141 int
open_mnt(char * fname,char * tname,int flags,int mode)142 open_mnt(char *fname, char *tname, int flags, int mode)
143 {
144 FILE *fd_in, *fd_out;
145 FILE *_fopen();
146 char tmp_name[64];
147 char line[MNT_LINE_MAX];
148 int fd;
149
150 if ((fd_in = _fopen(fname, "r")) == NULL)
151 return (-1);
152
153 sprintf(tmp_name, "%s%s%s", "/tmp/", tname, "XXXXXX");
154 mktemp(tmp_name);
155
156 if ((fd_out = _fopen(tmp_name, "a+")) == NULL) {
157 fclose(fd_in);
158 return (-1);
159 }
160
161 while (getmntline(line, fd_in) != -1) {
162 if (strcmp(fname, "/etc/mnttab") == 0) {
163 if (putmline(line, fd_out) == -1) {
164 fclose(fd_in);
165 fclose(fd_out);
166 return (-1);
167 }
168 } else { /* processing vfstab */
169 if (putfline(line, fd_out) == -1) {
170 fclose(fd_in);
171 fclose(fd_out);
172 return (-1);
173 }
174 }
175 }
176
177 if (feof(fd_in)) {
178 fclose(fd_in);
179 fclose(fd_out);
180
181 fd = _syscall(SYS_openat, AT_FDCWD, tmp_name, O_RDONLY);
182
183 if (fd == -1 || unlink(tmp_name) == -1)
184 return (-1);
185
186 return (fd);
187 } else {
188 fclose(fd_in);
189 fclose(fd_out);
190 return (-1);
191 }
192 }
193
194 int
getmntline(char * lp,FILE * fp)195 getmntline(char *lp, FILE *fp)
196 {
197 int ret;
198 char *cp;
199
200 while ((lp = fgets(lp, MNT_LINE_MAX, fp)) != NULL) {
201 if (strlen(lp) == MNT_LINE_MAX-1 && lp[MNT_LINE_MAX-2] != '\n')
202 return (-1);
203 for (cp = lp; *cp == ' ' || *cp == '\t'; cp++)
204 ;
205 if (*cp != '#' && *cp != '\n')
206 return (0);
207 }
208 return (-1);
209 }
210
211 int
putmline(char * line,FILE * fp)212 putmline(char *line, FILE *fp)
213 {
214 struct mntent mnt;
215 char *buf;
216 char *devnumstr = 0; /* the device number, in (hex) ascii */
217 char *remainder; /* remainder of mnt_opts string, after devnum */
218 unsigned long devnum;
219
220 GETTOK(mnt.mnt_fsname, line);
221 GETTOK(mnt.mnt_dir, NULL);
222 GETTOK(mnt.mnt_type, NULL);
223 GETTOK(mnt.mnt_opts, NULL);
224 GETTOK(buf, NULL);
225 mnt.mnt_freq = 0;
226 mnt.mnt_passno = 0;
227
228 if (strtok(NULL, sepstr) != NULL)
229 return (-1);
230 if (strcmp(mnt.mnt_type, "ufs") == 0) {
231 mnt.mnt_type = "4.2";
232 }
233
234 /*
235 * the device number, if present, follows the '='
236 * in the mnt_opts string.
237 */
238
239 if (mnt.mnt_opts != NULL)
240 devnumstr = (char *)strchr(mnt.mnt_opts, '=');
241
242 if (!devnumstr) {
243 /* no device number on this line */
244 fprintf(fp, "%s %s %s %s %d %d\n",
245 mnt.mnt_fsname, mnt.mnt_dir, mnt.mnt_type,
246 mnt.mnt_opts, mnt.mnt_freq, mnt.mnt_passno);
247 } else {
248 /* found the device number, convert it to 4.x format */
249 devnum = strtol(&devnumstr[1], (char **)NULL, 16);
250 remainder = (char *)strchr(&devnumstr[1], ' ');
251 devnumstr[1] = 0; /* null terminate mnt_opts after '=' */
252 devnum = cmpdev(devnum);
253
254 fprintf(fp, "%s %s %s %s%4x%s %d %d\n",
255 mnt.mnt_fsname, mnt.mnt_dir, mnt.mnt_type,
256 mnt.mnt_opts, devnum, remainder ? remainder : "",
257 mnt.mnt_freq, mnt.mnt_passno);
258 }
259
260 return (0);
261 }
262
263 int
putfline(char * line,FILE * fp)264 putfline(char *line, FILE *fp)
265 {
266 struct mntent mnt;
267 char *buf;
268
269 GETTOK(mnt.mnt_fsname, line);
270 GETTOK(buf, NULL);
271 GETTOK(mnt.mnt_dir, NULL);
272 if (mnt.mnt_dir == NULL && strcmp(mnt.mnt_fsname, "/dev/root") == 0)
273 mnt.mnt_dir = "/";
274 GETTOK(mnt.mnt_type, NULL);
275 GETTOK(buf, NULL);
276 GETTOK(buf, NULL);
277 GETTOK(mnt.mnt_opts, NULL);
278 if (mnt.mnt_opts == NULL)
279 mnt.mnt_opts = "rw";
280 mnt.mnt_freq = 0;
281 mnt.mnt_passno = 0;
282
283 if (strtok(NULL, sepstr) != NULL)
284 return (-1);
285 if (strcmp(mnt.mnt_type, "ufs") == 0) {
286 mnt.mnt_type = "4.2";
287 }
288
289 fprintf(fp, "%s %s %s %s %d %d\n",
290 mnt.mnt_fsname, mnt.mnt_dir, mnt.mnt_type,
291 mnt.mnt_opts, mnt.mnt_freq, mnt.mnt_passno);
292
293 return (0);
294 }
295
296 FILE *
_fopen(char * file,char * mode)297 _fopen(char *file, char *mode)
298 {
299 extern FILE *_findiop();
300 FILE *iop;
301
302 int plus, oflag, fd;
303
304 iop = _findiop();
305
306 if (iop == NULL || file == NULL || file[0] == '\0')
307 return (NULL);
308 plus = (mode[1] == '+');
309 switch (mode[0]) {
310 case 'w':
311 oflag = (plus ? O_RDWR : O_WRONLY) | N_O_TRUNC | N_O_CREAT;
312 break;
313 case 'a':
314 oflag = (plus ? O_RDWR : O_WRONLY) | N_O_CREAT;
315 break;
316 case 'r':
317 oflag = plus ? O_RDWR : O_RDONLY;
318 break;
319 default:
320 return (NULL);
321 }
322 if ((fd = _syscall(SYS_openat, AT_FDCWD, file, oflag, 0666)) < 0)
323 return (NULL);
324 iop->_cnt = 0;
325 iop->_file = fd;
326 iop->_flag = plus ? _IORW : (mode[0] == 'r') ? _IOREAD : _IOWRT;
327 if (mode[0] == 'a') {
328 if ((lseek(fd, 0L, 2)) < 0) {
329 (void) close(fd);
330 return (NULL);
331 }
332 }
333 iop->_base = iop->_ptr = NULL;
334 iop->_bufsiz = 0;
335 return (iop);
336 }
337
338 static int
open_printcap(void)339 open_printcap(void)
340 {
341 FILE *fd;
342 FILE *_fopen();
343 char tmp_name[] = "/tmp/printcap.XXXXXX";
344 int tmp_file;
345 DIR *printerDir;
346 struct dirent *entry;
347
348 mktemp(tmp_name);
349 if ((fd = _fopen(tmp_name, "a+")) == NULL)
350 return (-1);
351 fprintf(fd, "# Derived from lp(1) configuration information for BCP\n");
352
353 if ((printerDir = opendir(PRINTER_DIR)) != NULL) {
354 while ((entry = readdir(printerDir)) != NULL)
355 if (entry->d_name[0] != '.')
356 getPrinterInfo(entry->d_name, fd);
357 closedir(printerDir);
358 }
359 fclose(fd);
360
361 tmp_file = _syscall(SYS_openat, AT_FDCWD, tmp_name, O_RDONLY);
362 if (tmp_file == -1 || unlink(tmp_name) == -1)
363 return (-1);
364
365 return (tmp_file);
366 }
367
368 static void
getPrinterInfo(char * printerName,FILE * fd)369 getPrinterInfo(char *printerName, FILE *fd)
370 {
371 char *fullPath;
372 char *str;
373 char *p;
374 char *c;
375 struct stat buf;
376 int config_fd;
377
378 fullPath = (char *)malloc(strlen(PRINTER_DIR) + strlen(printerName) +
379 strlen(PRINTER_CONFIG_FILE) + 1);
380 strcpy(fullPath, PRINTER_DIR);
381 strcat(fullPath, printerName);
382 strcat(fullPath, PRINTER_CONFIG_FILE);
383
384 if ((config_fd = _syscall(SYS_openat, AT_FDCWD, fullPath, O_RDONLY))
385 == -1) {
386 free(fullPath);
387 return;
388 }
389 if ((fstat(config_fd, &buf)) != 0 ||
390 (str = (char *)malloc(buf.st_size + 2)) == NULL) {
391 free(fullPath);
392 close(config_fd);
393 return;
394 }
395 if ((read(config_fd, str, buf.st_size)) != buf.st_size) {
396 free(fullPath);
397 free(str);
398 close(config_fd);
399 return;
400 }
401 p = &str[buf.st_size];
402 p[0] = '\n';
403 p[1] = '\0';
404
405 fprintf(fd, "%s:", printerName);
406 if ((p = (char *)_strstr(str, "Remote")) != NULL) {
407 /* remote printer */
408 p = (char *)strchr(p, ' ') + 1;
409 c = (char *)strchr(p, '\n');
410 *c = '\0';
411 fprintf(fd, "lp=:rm=%s:rp=%s:\n", p, printerName);
412 } else if ((p = (char *)_strstr(str, "Device")) != NULL) {
413 /* local printer */
414 p = (char *)strchr(p, ' ') + 1;
415 c = (char *)strchr(p, '\n');
416 *c = '\0';
417 fprintf(fd, "lp=%s:\n", p);
418 }
419 free(fullPath);
420 free(str);
421 close(config_fd);
422 }
423