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 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 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 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 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 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 * 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 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 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