xref: /titanic_50/usr/src/lib/libbc/libc/sys/common/_open.c (revision 8fd04b8338ed5093ec2d1e668fa620b7de44c177)
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