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 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 22 /* All Rights Reserved */ 23 24 25 /* 26 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 27 * Use is subject to license terms. 28 */ 29 30 #include "termio.h" 31 #include "dial.h" 32 #include "unistd.h" 33 34 #include "lpsched.h" 35 36 #include <sys/ioccom.h> 37 #include <sys/ecppsys.h> 38 39 static void sigalrm(int); 40 static int push_module(int, char *, char *); 41 42 static int SigAlrm; 43 44 /* 45 * open_dialup() - OPEN A PORT TO A ``DIAL-UP'' PRINTER 46 */ 47 48 int 49 open_dialup(char *ptype, PRINTER *pp) 50 { 51 static char *baud_table[] = { 52 0, 53 "50", 54 "75", 55 "110", 56 "134", 57 "150", 58 "200", 59 "300", 60 "600", 61 "1200", 62 "1800", 63 "2400", 64 "4800", 65 "9600", 66 "19200", 67 "38400", 68 "57600", 69 "76800", 70 "115200", 71 "153600", 72 "230400", 73 "307200", 74 "460800", 75 "921600" 76 }; 77 78 struct termio tio; 79 struct termios tios; 80 81 CALL call; 82 83 int speed, fd; 84 85 char *sspeed; 86 87 88 if (pp->speed == NULL || (speed = atoi(pp->speed)) <= 0) 89 speed = -1; 90 91 call.attr = 0; 92 call.speed = speed; 93 call.line = 0; 94 call.telno = pp->dial_info; 95 96 if ((fd = dial(call)) < 0) 97 return (EXEC_EXIT_NDIAL | (~EXEC_EXIT_NMASK & abs(fd))); 98 99 /* 100 * "dial()" doesn't guarantee which file descriptor 101 * it uses when it opens the port, so we probably have to 102 * move it. 103 */ 104 if (fd != 1) { 105 dup2(fd, 1); 106 Close(fd); 107 } 108 109 /* 110 * The "printermgmt()" routines move out of ".stty" 111 * anything that looks like a baud rate, and puts it 112 * in ".speed", if the printer port is dialed. Thus 113 * we are saved the task of cleaning out spurious 114 * baud rates from ".stty". 115 * 116 * However, we must determine the baud rate and 117 * concatenate it onto ".stty" so that that we can 118 * override the default in the interface progam. 119 * Putting the override in ".stty" allows the user 120 * to override us (although it would be probably be 121 * silly for him or her to do so.) 122 */ 123 if (ioctl(1, TCGETS, &tios) < 0) { 124 ioctl(1, TCGETA, &tio); 125 tios.c_cflag = tio.c_cflag; 126 } 127 if ((sspeed = baud_table[cfgetospeed(&tios)]) != NULL) { 128 129 if (pp->stty == NULL) 130 pp->stty = ""; 131 132 { 133 char *new_stty = Malloc( 134 strlen(pp->stty) + 1 + strlen(sspeed) + 1); 135 136 sprintf(new_stty, "%s %s", pp->stty, sspeed); 137 138 /* 139 * We can trash "pp->stty" because 140 * the parent process has the good copy. 141 */ 142 pp->stty = new_stty; 143 } 144 } 145 146 return (0); 147 } 148 149 /* 150 * open_direct() - OPEN A PORT TO A DIRECTLY CONNECTED PRINTER 151 */ 152 153 int 154 open_direct(char *ptype, PRINTER *pp) 155 { 156 short bufsz = -1, cps = -1; 157 int open_mode, fd; 158 register unsigned int oldalarm, newalarm = 0; 159 char *device; 160 161 struct ecpp_transfer_parms ecpp_params; /* for ECPP port checking */ 162 char **modules = NULL; 163 164 struct flock lck; 165 struct stat buf; 166 167 register void (*oldsig)() = signal(SIGALRM, sigalrm); 168 169 170 /* 171 * Set an alarm to wake us from trying to open the port. 172 * We'll try at least 60 seconds, or more if the printer 173 * has a huge buffer that, in the worst case, would take 174 * a long time to drain. 175 */ 176 tidbit(ptype, "bufsz", &bufsz); 177 tidbit(ptype, "cps", &cps); 178 if (bufsz > 0 && cps > 0) 179 newalarm = (((long)bufsz * 1100) / cps) / 1000; 180 if (newalarm < 60) 181 newalarm = 60; 182 oldalarm = alarm(newalarm); 183 184 device = pp->device; 185 if (is_printer_uri(device) == 0) { 186 /* 187 * if it's a device uri and the endpoint contains a valid 188 * path, that path should be opened/locked by lpsched for 189 * the backend. If not, the uri isn't associated with a 190 * local device, so use /dev/null. 191 */ 192 device = strstr(device, "://"); 193 if (device != NULL) 194 device = strchr(device + 3, '/'); 195 196 if ((device == NULL) || (access(device, F_OK) < 0)) 197 device = "/dev/null"; 198 } 199 200 /* 201 * The following open must be interruptable. 202 * O_APPEND is set in case the ``port'' is a file. 203 * O_RDWR is set in case the interface program wants 204 * to get input from the printer. Don't fail, though, 205 * just because we can't get read access. 206 */ 207 208 open_mode = O_WRONLY; 209 if (access(device, R_OK) == 0) 210 open_mode = O_RDWR; 211 open_mode |= O_APPEND; 212 213 SigAlrm = 0; 214 215 while ((fd = open(device, open_mode, 0)) == -1) { 216 if (errno != EINTR) 217 return (EXEC_EXIT_NPORT); 218 else if (SigAlrm) 219 return (EXEC_EXIT_TMOUT); 220 } 221 222 alarm(oldalarm); 223 signal(SIGALRM, oldsig); 224 225 /* 226 * Lock the file in case two "printers" are defined on the 227 * same port. Don't lock /dev/null. 228 */ 229 230 lck.l_type = F_WRLCK; 231 lck.l_whence = 0; 232 lck.l_start = 0L; 233 lck.l_len = 0L; 234 235 if (strcmp(device, "/dev/null") && Fcntl(fd, F_SETLKW, &lck) < 0) { 236 execlog("lock error: %s\n", pp->device); 237 return (EXEC_EXIT_NPORT); 238 } 239 240 /* 241 * We should get the correct channel number (1), but just 242 * in case.... 243 */ 244 if (fd != 1) { 245 dup2(fd, 1); 246 Close(fd); 247 } 248 249 /* 250 * Handle streams modules: 251 */ 252 if (fstat(1, &buf)) 253 buf.st_mode = 0; 254 255 /* 256 * for some unknown reason, lpsched appears to pop the streams 257 * modules off the device and push back some "default" ones, 258 * unless a specific set were specified with the printer configuration. 259 * This behaviour causes problems with the ECPP port, so if we have 260 * an ECPP port, and nobody specified a set of modules to use, we 261 * should leave it alone. Normally, we would not bother to play with 262 * the streams modules, but it is possible that someone has come 263 * to rely on this behaviour for other devices. 264 */ 265 if ((pp->modules != NULL) && (pp->modules[0] != NULL) && 266 (strcmp(pp->modules[0], "default") != 0)) 267 modules = pp->modules; 268 269 if ((modules == NULL) && (ioctl(1, ECPPIOC_GETPARMS, &ecpp_params) < 0)) 270 modules = getlist(DEFMODULES, LP_WS, LP_SEP); 271 272 /* if "nopush" is supplied, leave the modules alone */ 273 if ((modules != NULL) && (modules[0] != NULL) && 274 (strcasecmp(modules[0], "nopush") == 0)) 275 modules = NULL; 276 277 /* 278 * If we have a stream and a list of modules to use, then pop the old 279 * modules and push the new ones. 280 */ 281 if ((modules != NULL) && !S_ISFIFO(buf.st_mode) && isastream(1)) { 282 /* 283 * First, pop all current modules off, unless 284 * instructed not to. 285 */ 286 while (ioctl(1, I_POP, 0) == 0) 287 ; 288 289 /* 290 * Now push either the administrator specified modules 291 * or the standard modules, unless instructed to push 292 * nothing. 293 */ 294 295 if ((modules[1] == NULL) && 296 (strcasecmp(modules[0], "none") == 0)) 297 return (0); 298 299 while (*modules) 300 if (push_module(1, device, *modules++) == -1) 301 return (EXEC_EXIT_NPUSH); 302 } 303 304 return (0); 305 } 306 307 /* 308 * sigalrm() 309 */ 310 static void 311 sigalrm(int ignore) 312 { 313 signal(SIGALRM, SIG_IGN); 314 SigAlrm = 1; 315 } 316 317 318 /* 319 * push_module() 320 */ 321 322 static int 323 push_module(int fd, char *device, char *module) 324 { 325 int ret = ioctl(fd, I_PUSH, module); 326 327 if (ret == -1) 328 note("push (%s) on %s failed (%s)\n", module, device, PERROR); 329 return (ret); 330 } 331