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