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