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