/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #include #include #include #include #include #include #include #include #include #include #include "s5sysmacros.h" #include "compat.h" #define PRINTER_DIR "/etc/lp/printers/" #define PRINTER_CONFIG_FILE "/configuration" #define MNT_LINE_MAX 1024 #define GETTOK(xx, ll) \ if ((xx = strtok(ll, sepstr)) == NULL) \ return (-1); \ if (strcmp(xx, dash) == 0) \ xx = NULL char *mktemp(); static void getPrinterInfo(char *, FILE *); static char sepstr[] = " \t\n"; static char dash[] = "-"; static int open_printcap(void); /* SVR4/SunOS 5.0 equivalent modes */ #define N_O_NDELAY 0x04 #define N_O_SYNC 0x10 #define N_O_NONBLOCK 0x80 #define N_O_CREAT 0x100 #define N_O_TRUNC 0x200 #define N_O_EXCL 0x400 /* Mask corresponding to the bits above in SunOS 4.x */ #define FLAGS_MASK (O_SYNC|O_NONBLOCK|O_CREAT|O_TRUNC|O_EXCL \ |_FNDELAY|_FNBIO) int open_com(char *path, int flags, int mode) { int fd, fd2, pathl, inspt, ret = 0; int nflags = flags; char loc[] = "/lib/locale"; char *loct = NULL; if (flags & FLAGS_MASK) { nflags = flags & ~FLAGS_MASK; if (flags & O_SYNC) nflags |= N_O_SYNC; if (flags & (_FNDELAY|O_NONBLOCK)) { nflags |= N_O_NONBLOCK; } if (flags & O_CREAT) nflags |= N_O_CREAT; if (flags & O_TRUNC) nflags |= N_O_TRUNC; if (flags & O_EXCL) nflags |= N_O_EXCL; if (flags & _FNBIO) nflags |= N_O_NDELAY; } /* change path from ..../lib/locale/.... to ..../lib/oldlocale/.... XXX */ if ((loct = (char *)_strstr(path, loc)) != NULL) { /* /lib/locale ? */ char locbuf[MAXPATHLEN+100]; /* to hold new locale path */ pathl = strlen(path); inspt = pathl - strlen(loct) + 5; /* pos to add "old" */ (void) strncpy(locbuf, path, inspt); /* copy path upto lib */ locbuf[inspt] = '\0'; /* make it a string */ strcat(locbuf, "old"); /* add "old" */ strcat(locbuf, loct+5); /* add remainer of path */ return (_syscall(SYS_openat, AT_FDCWD, locbuf, nflags, mode)); } if (strcmp(path, "/etc/mtab") == 0) return (open_mnt("/etc/mnttab", "mtab", nflags, mode)); if (strcmp(path, "/etc/fstab") == 0) return (open_mnt("/etc/vfstab", "fstab", nflags, mode)); if (strcmp(path, "/etc/printcap") == 0) { if ((fd = _syscall(SYS_openat, AT_FDCWD, path, nflags, mode)) >= 0) return (fd); return (open_printcap()); } if (strcmp(path, "/etc/utmp") == 0 || strcmp(path, "/var/adm/utmp") == 0) { fd = _syscall(SYS_openat, AT_FDCWD, "/var/adm/utmpx", nflags, mode); if (fd >= 0) fd_add(fd, UTMPX_MAGIC_FLAG); return (fd); } if (strcmp(path, "/var/adm/wtmp") == 0) { fd = _syscall(SYS_openat, AT_FDCWD, "/var/adm/wtmpx", nflags, mode); if (fd >= 0) fd_add(fd, UTMPX_MAGIC_FLAG); return (fd); } return (_syscall(SYS_openat, AT_FDCWD, path, nflags, mode)); } int open_mnt(char *fname, char *tname, int flags, int mode) { FILE *fd_in, *fd_out; FILE *_fopen(); char tmp_name[64]; char line[MNT_LINE_MAX]; int fd; if ((fd_in = _fopen(fname, "r")) == NULL) return (-1); sprintf(tmp_name, "%s%s%s", "/tmp/", tname, "XXXXXX"); mktemp(tmp_name); if ((fd_out = _fopen(tmp_name, "a+")) == NULL) { fclose(fd_in); return (-1); } while (getmntline(line, fd_in) != -1) { if (strcmp(fname, "/etc/mnttab") == 0) { if (putmline(line, fd_out) == -1) { fclose(fd_in); fclose(fd_out); return (-1); } } else { /* processing vfstab */ if (putfline(line, fd_out) == -1) { fclose(fd_in); fclose(fd_out); return (-1); } } } if (feof(fd_in)) { fclose(fd_in); fclose(fd_out); fd = _syscall(SYS_openat, AT_FDCWD, tmp_name, O_RDONLY); if (fd == -1 || unlink(tmp_name) == -1) return (-1); return (fd); } else { fclose(fd_in); fclose(fd_out); return (-1); } } int getmntline(char *lp, FILE *fp) { int ret; char *cp; while ((lp = fgets(lp, MNT_LINE_MAX, fp)) != NULL) { if (strlen(lp) == MNT_LINE_MAX-1 && lp[MNT_LINE_MAX-2] != '\n') return (-1); for (cp = lp; *cp == ' ' || *cp == '\t'; cp++) ; if (*cp != '#' && *cp != '\n') return (0); } return (-1); } int putmline(char *line, FILE *fp) { struct mntent mnt; char *buf; char *devnumstr = 0; /* the device number, in (hex) ascii */ char *remainder; /* remainder of mnt_opts string, after devnum */ unsigned long devnum; GETTOK(mnt.mnt_fsname, line); GETTOK(mnt.mnt_dir, NULL); GETTOK(mnt.mnt_type, NULL); GETTOK(mnt.mnt_opts, NULL); GETTOK(buf, NULL); mnt.mnt_freq = 0; mnt.mnt_passno = 0; if (strtok(NULL, sepstr) != NULL) return (-1); if (strcmp(mnt.mnt_type, "ufs") == 0) { mnt.mnt_type = "4.2"; } /* * the device number, if present, follows the '=' * in the mnt_opts string. */ if (mnt.mnt_opts != NULL) devnumstr = (char *)strchr(mnt.mnt_opts, '='); if (!devnumstr) { /* no device number on this line */ fprintf(fp, "%s %s %s %s %d %d\n", mnt.mnt_fsname, mnt.mnt_dir, mnt.mnt_type, mnt.mnt_opts, mnt.mnt_freq, mnt.mnt_passno); } else { /* found the device number, convert it to 4.x format */ devnum = strtol(&devnumstr[1], (char **)NULL, 16); remainder = (char *)strchr(&devnumstr[1], ' '); devnumstr[1] = 0; /* null terminate mnt_opts after '=' */ devnum = cmpdev(devnum); fprintf(fp, "%s %s %s %s%4x%s %d %d\n", mnt.mnt_fsname, mnt.mnt_dir, mnt.mnt_type, mnt.mnt_opts, devnum, remainder ? remainder : "", mnt.mnt_freq, mnt.mnt_passno); } return (0); } int putfline(char *line, FILE *fp) { struct mntent mnt; char *buf; GETTOK(mnt.mnt_fsname, line); GETTOK(buf, NULL); GETTOK(mnt.mnt_dir, NULL); if (mnt.mnt_dir == NULL && strcmp(mnt.mnt_fsname, "/dev/root") == 0) mnt.mnt_dir = "/"; GETTOK(mnt.mnt_type, NULL); GETTOK(buf, NULL); GETTOK(buf, NULL); GETTOK(mnt.mnt_opts, NULL); if (mnt.mnt_opts == NULL) mnt.mnt_opts = "rw"; mnt.mnt_freq = 0; mnt.mnt_passno = 0; if (strtok(NULL, sepstr) != NULL) return (-1); if (strcmp(mnt.mnt_type, "ufs") == 0) { mnt.mnt_type = "4.2"; } fprintf(fp, "%s %s %s %s %d %d\n", mnt.mnt_fsname, mnt.mnt_dir, mnt.mnt_type, mnt.mnt_opts, mnt.mnt_freq, mnt.mnt_passno); return (0); } FILE * _fopen(char *file, char *mode) { extern FILE *_findiop(); FILE *iop; int plus, oflag, fd; iop = _findiop(); if (iop == NULL || file == NULL || file[0] == '\0') return (NULL); plus = (mode[1] == '+'); switch (mode[0]) { case 'w': oflag = (plus ? O_RDWR : O_WRONLY) | N_O_TRUNC | N_O_CREAT; break; case 'a': oflag = (plus ? O_RDWR : O_WRONLY) | N_O_CREAT; break; case 'r': oflag = plus ? O_RDWR : O_RDONLY; break; default: return (NULL); } if ((fd = _syscall(SYS_openat, AT_FDCWD, file, oflag, 0666)) < 0) return (NULL); iop->_cnt = 0; iop->_file = fd; iop->_flag = plus ? _IORW : (mode[0] == 'r') ? _IOREAD : _IOWRT; if (mode[0] == 'a') { if ((lseek(fd, 0L, 2)) < 0) { (void) close(fd); return (NULL); } } iop->_base = iop->_ptr = NULL; iop->_bufsiz = 0; return (iop); } static int open_printcap(void) { FILE *fd; FILE *_fopen(); char tmp_name[] = "/tmp/printcap.XXXXXX"; int tmp_file; DIR *printerDir; struct dirent *entry; mktemp(tmp_name); if ((fd = _fopen(tmp_name, "a+")) == NULL) return (-1); fprintf(fd, "# Derived from lp(1) configuration information for BCP\n"); if ((printerDir = opendir(PRINTER_DIR)) != NULL) { while ((entry = readdir(printerDir)) != NULL) if (entry->d_name[0] != '.') getPrinterInfo(entry->d_name, fd); closedir(printerDir); } fclose(fd); tmp_file = _syscall(SYS_openat, AT_FDCWD, tmp_name, O_RDONLY); if (tmp_file == -1 || unlink(tmp_name) == -1) return (-1); return (tmp_file); } static void getPrinterInfo(char *printerName, FILE *fd) { char *fullPath; char *str; char *p; char *c; struct stat buf; int config_fd; fullPath = (char *)malloc(strlen(PRINTER_DIR) + strlen(printerName) + strlen(PRINTER_CONFIG_FILE) + 1); strcpy(fullPath, PRINTER_DIR); strcat(fullPath, printerName); strcat(fullPath, PRINTER_CONFIG_FILE); if ((config_fd = _syscall(SYS_openat, AT_FDCWD, fullPath, O_RDONLY)) == -1) { free(fullPath); return; } if ((fstat(config_fd, &buf)) != 0 || (str = (char *)malloc(buf.st_size + 2)) == NULL) { free(fullPath); close(config_fd); return; } if ((read(config_fd, str, buf.st_size)) != buf.st_size) { free(fullPath); free(str); close(config_fd); return; } p = &str[buf.st_size]; p[0] = '\n'; p[1] = '\0'; fprintf(fd, "%s:", printerName); if ((p = (char *)_strstr(str, "Remote")) != NULL) { /* remote printer */ p = (char *)strchr(p, ' ') + 1; c = (char *)strchr(p, '\n'); *c = '\0'; fprintf(fd, "lp=:rm=%s:rp=%s:\n", p, printerName); } else if ((p = (char *)_strstr(str, "Device")) != NULL) { /* local printer */ p = (char *)strchr(p, ' ') + 1; c = (char *)strchr(p, '\n'); *c = '\0'; fprintf(fd, "lp=%s:\n", p); } free(fullPath); free(str); close(config_fd); }