17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5de81e71eSTim Marsland * Common Development and Distribution License (the "License").
6de81e71eSTim Marsland * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
217c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
227c478bd9Sstevel@tonic-gate /* All Rights Reserved */
237c478bd9Sstevel@tonic-gate
247c478bd9Sstevel@tonic-gate
257c478bd9Sstevel@tonic-gate /*
26de81e71eSTim Marsland * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
277c478bd9Sstevel@tonic-gate * Use is subject to license terms.
2848bbca81SDaniel Hoffman * Copyright (c) 2016 by Delphix. All rights reserved.
297c478bd9Sstevel@tonic-gate */
307c478bd9Sstevel@tonic-gate
317c478bd9Sstevel@tonic-gate #include "termio.h"
327c478bd9Sstevel@tonic-gate #include "dial.h"
337c478bd9Sstevel@tonic-gate #include "unistd.h"
347c478bd9Sstevel@tonic-gate
357c478bd9Sstevel@tonic-gate #include "lpsched.h"
367c478bd9Sstevel@tonic-gate
377c478bd9Sstevel@tonic-gate #include <sys/ioccom.h>
387c478bd9Sstevel@tonic-gate #include <sys/ecppsys.h>
397c478bd9Sstevel@tonic-gate
40de81e71eSTim Marsland static void sigalrm(int);
41de81e71eSTim Marsland static int push_module(int, char *, char *);
427c478bd9Sstevel@tonic-gate
437c478bd9Sstevel@tonic-gate static int SigAlrm;
447c478bd9Sstevel@tonic-gate
45de81e71eSTim Marsland /*
46de81e71eSTim Marsland * open_dialup() - OPEN A PORT TO A ``DIAL-UP'' PRINTER
47de81e71eSTim Marsland */
487c478bd9Sstevel@tonic-gate
497c478bd9Sstevel@tonic-gate int
open_dialup(char * ptype,PRINTER * pp)50de81e71eSTim Marsland open_dialup(char *ptype, PRINTER *pp)
517c478bd9Sstevel@tonic-gate {
527c478bd9Sstevel@tonic-gate static char *baud_table[] = {
53de81e71eSTim Marsland 0,
54de81e71eSTim Marsland "50",
55de81e71eSTim Marsland "75",
56de81e71eSTim Marsland "110",
57de81e71eSTim Marsland "134",
58de81e71eSTim Marsland "150",
59de81e71eSTim Marsland "200",
60de81e71eSTim Marsland "300",
61de81e71eSTim Marsland "600",
62de81e71eSTim Marsland "1200",
63de81e71eSTim Marsland "1800",
64de81e71eSTim Marsland "2400",
65de81e71eSTim Marsland "4800",
66de81e71eSTim Marsland "9600",
677c478bd9Sstevel@tonic-gate "19200",
687c478bd9Sstevel@tonic-gate "38400",
697c478bd9Sstevel@tonic-gate "57600",
707c478bd9Sstevel@tonic-gate "76800",
717c478bd9Sstevel@tonic-gate "115200",
727c478bd9Sstevel@tonic-gate "153600",
737c478bd9Sstevel@tonic-gate "230400",
747c478bd9Sstevel@tonic-gate "307200",
75de81e71eSTim Marsland "460800",
76*d9c3e05cSJoshua M. Clulow "921600",
77*d9c3e05cSJoshua M. Clulow "1000000",
78*d9c3e05cSJoshua M. Clulow "1152000",
79*d9c3e05cSJoshua M. Clulow "1500000",
80*d9c3e05cSJoshua M. Clulow "2000000",
81*d9c3e05cSJoshua M. Clulow "2500000",
82*d9c3e05cSJoshua M. Clulow "3000000",
83*d9c3e05cSJoshua M. Clulow "3500000",
84*d9c3e05cSJoshua M. Clulow "4000000"
857c478bd9Sstevel@tonic-gate };
867c478bd9Sstevel@tonic-gate
877c478bd9Sstevel@tonic-gate struct termio tio;
887c478bd9Sstevel@tonic-gate struct termios tios;
897c478bd9Sstevel@tonic-gate
907c478bd9Sstevel@tonic-gate CALL call;
917c478bd9Sstevel@tonic-gate
92de81e71eSTim Marsland int speed, fd;
937c478bd9Sstevel@tonic-gate
947c478bd9Sstevel@tonic-gate char *sspeed;
957c478bd9Sstevel@tonic-gate
967c478bd9Sstevel@tonic-gate
977c478bd9Sstevel@tonic-gate if (pp->speed == NULL || (speed = atoi(pp->speed)) <= 0)
987c478bd9Sstevel@tonic-gate speed = -1;
997c478bd9Sstevel@tonic-gate
1007c478bd9Sstevel@tonic-gate call.attr = 0;
1017c478bd9Sstevel@tonic-gate call.speed = speed;
1027c478bd9Sstevel@tonic-gate call.line = 0;
1037c478bd9Sstevel@tonic-gate call.telno = pp->dial_info;
1047c478bd9Sstevel@tonic-gate
1057c478bd9Sstevel@tonic-gate if ((fd = dial(call)) < 0)
1067c478bd9Sstevel@tonic-gate return (EXEC_EXIT_NDIAL | (~EXEC_EXIT_NMASK & abs(fd)));
1077c478bd9Sstevel@tonic-gate
1087c478bd9Sstevel@tonic-gate /*
1097c478bd9Sstevel@tonic-gate * "dial()" doesn't guarantee which file descriptor
1107c478bd9Sstevel@tonic-gate * it uses when it opens the port, so we probably have to
1117c478bd9Sstevel@tonic-gate * move it.
1127c478bd9Sstevel@tonic-gate */
1137c478bd9Sstevel@tonic-gate if (fd != 1) {
114de81e71eSTim Marsland dup2(fd, 1);
115de81e71eSTim Marsland Close(fd);
1167c478bd9Sstevel@tonic-gate }
1177c478bd9Sstevel@tonic-gate
1187c478bd9Sstevel@tonic-gate /*
1197c478bd9Sstevel@tonic-gate * The "printermgmt()" routines move out of ".stty"
1207c478bd9Sstevel@tonic-gate * anything that looks like a baud rate, and puts it
1217c478bd9Sstevel@tonic-gate * in ".speed", if the printer port is dialed. Thus
1227c478bd9Sstevel@tonic-gate * we are saved the task of cleaning out spurious
1237c478bd9Sstevel@tonic-gate * baud rates from ".stty".
1247c478bd9Sstevel@tonic-gate *
1257c478bd9Sstevel@tonic-gate * However, we must determine the baud rate and
1267c478bd9Sstevel@tonic-gate * concatenate it onto ".stty" so that that we can
1277c478bd9Sstevel@tonic-gate * override the default in the interface progam.
1287c478bd9Sstevel@tonic-gate * Putting the override in ".stty" allows the user
1297c478bd9Sstevel@tonic-gate * to override us (although it would be probably be
13048bbca81SDaniel Hoffman * silly for them to do so.)
1317c478bd9Sstevel@tonic-gate */
132de81e71eSTim Marsland if (ioctl(1, TCGETS, &tios) < 0) {
133de81e71eSTim Marsland ioctl(1, TCGETA, &tio);
1347c478bd9Sstevel@tonic-gate tios.c_cflag = tio.c_cflag;
1357c478bd9Sstevel@tonic-gate }
1367c478bd9Sstevel@tonic-gate if ((sspeed = baud_table[cfgetospeed(&tios)]) != NULL) {
1377c478bd9Sstevel@tonic-gate
1387c478bd9Sstevel@tonic-gate if (pp->stty == NULL)
1397c478bd9Sstevel@tonic-gate pp->stty = "";
140de81e71eSTim Marsland
1417c478bd9Sstevel@tonic-gate {
142de81e71eSTim Marsland char *new_stty = Malloc(
143de81e71eSTim Marsland strlen(pp->stty) + 1 + strlen(sspeed) + 1);
1447c478bd9Sstevel@tonic-gate
145de81e71eSTim Marsland sprintf(new_stty, "%s %s", pp->stty, sspeed);
1467c478bd9Sstevel@tonic-gate
147de81e71eSTim Marsland /*
148de81e71eSTim Marsland * We can trash "pp->stty" because
149de81e71eSTim Marsland * the parent process has the good copy.
150de81e71eSTim Marsland */
151de81e71eSTim Marsland pp->stty = new_stty;
1527c478bd9Sstevel@tonic-gate }
1537c478bd9Sstevel@tonic-gate }
1547c478bd9Sstevel@tonic-gate
1557c478bd9Sstevel@tonic-gate return (0);
1567c478bd9Sstevel@tonic-gate }
1577c478bd9Sstevel@tonic-gate
158de81e71eSTim Marsland /*
159de81e71eSTim Marsland * open_direct() - OPEN A PORT TO A DIRECTLY CONNECTED PRINTER
160de81e71eSTim Marsland */
1617c478bd9Sstevel@tonic-gate
1627c478bd9Sstevel@tonic-gate int
open_direct(char * ptype,PRINTER * pp)1637c478bd9Sstevel@tonic-gate open_direct(char *ptype, PRINTER *pp)
1647c478bd9Sstevel@tonic-gate {
165de81e71eSTim Marsland short bufsz = -1, cps = -1;
166de81e71eSTim Marsland int open_mode, fd;
167de81e71eSTim Marsland register unsigned int oldalarm, newalarm = 0;
1687c478bd9Sstevel@tonic-gate char *device;
1697c478bd9Sstevel@tonic-gate
1707c478bd9Sstevel@tonic-gate struct ecpp_transfer_parms ecpp_params; /* for ECPP port checking */
171de81e71eSTim Marsland char **modules = NULL;
1727c478bd9Sstevel@tonic-gate
1737c478bd9Sstevel@tonic-gate struct flock lck;
1747c478bd9Sstevel@tonic-gate struct stat buf;
1757c478bd9Sstevel@tonic-gate
1767c478bd9Sstevel@tonic-gate register void (*oldsig)() = signal(SIGALRM, sigalrm);
1777c478bd9Sstevel@tonic-gate
1787c478bd9Sstevel@tonic-gate
1797c478bd9Sstevel@tonic-gate /*
1807c478bd9Sstevel@tonic-gate * Set an alarm to wake us from trying to open the port.
1817c478bd9Sstevel@tonic-gate * We'll try at least 60 seconds, or more if the printer
1827c478bd9Sstevel@tonic-gate * has a huge buffer that, in the worst case, would take
1837c478bd9Sstevel@tonic-gate * a long time to drain.
1847c478bd9Sstevel@tonic-gate */
185de81e71eSTim Marsland tidbit(ptype, "bufsz", &bufsz);
186de81e71eSTim Marsland tidbit(ptype, "cps", &cps);
1877c478bd9Sstevel@tonic-gate if (bufsz > 0 && cps > 0)
1887c478bd9Sstevel@tonic-gate newalarm = (((long)bufsz * 1100) / cps) / 1000;
1897c478bd9Sstevel@tonic-gate if (newalarm < 60)
1907c478bd9Sstevel@tonic-gate newalarm = 60;
1917c478bd9Sstevel@tonic-gate oldalarm = alarm(newalarm);
1927c478bd9Sstevel@tonic-gate
1937c478bd9Sstevel@tonic-gate device = pp->device;
1947c478bd9Sstevel@tonic-gate if (is_printer_uri(device) == 0) {
1957c478bd9Sstevel@tonic-gate /*
1967c478bd9Sstevel@tonic-gate * if it's a device uri and the endpoint contains a valid
1977c478bd9Sstevel@tonic-gate * path, that path should be opened/locked by lpsched for
1987c478bd9Sstevel@tonic-gate * the backend. If not, the uri isn't associated with a
1997c478bd9Sstevel@tonic-gate * local device, so use /dev/null.
2007c478bd9Sstevel@tonic-gate */
2017c478bd9Sstevel@tonic-gate device = strstr(device, "://");
2027c478bd9Sstevel@tonic-gate if (device != NULL)
2037c478bd9Sstevel@tonic-gate device = strchr(device + 3, '/');
2047c478bd9Sstevel@tonic-gate
2057c478bd9Sstevel@tonic-gate if ((device == NULL) || (access(device, F_OK) < 0))
2067c478bd9Sstevel@tonic-gate device = "/dev/null";
2077c478bd9Sstevel@tonic-gate }
2087c478bd9Sstevel@tonic-gate
2097c478bd9Sstevel@tonic-gate /*
2107c478bd9Sstevel@tonic-gate * The following open must be interruptable.
2117c478bd9Sstevel@tonic-gate * O_APPEND is set in case the ``port'' is a file.
2127c478bd9Sstevel@tonic-gate * O_RDWR is set in case the interface program wants
2137c478bd9Sstevel@tonic-gate * to get input from the printer. Don't fail, though,
2147c478bd9Sstevel@tonic-gate * just because we can't get read access.
2157c478bd9Sstevel@tonic-gate */
2167c478bd9Sstevel@tonic-gate
2177c478bd9Sstevel@tonic-gate open_mode = O_WRONLY;
2187c478bd9Sstevel@tonic-gate if (access(device, R_OK) == 0)
2197c478bd9Sstevel@tonic-gate open_mode = O_RDWR;
2207c478bd9Sstevel@tonic-gate open_mode |= O_APPEND;
2217c478bd9Sstevel@tonic-gate
2227c478bd9Sstevel@tonic-gate SigAlrm = 0;
2237c478bd9Sstevel@tonic-gate
2247c478bd9Sstevel@tonic-gate while ((fd = open(device, open_mode, 0)) == -1) {
2257c478bd9Sstevel@tonic-gate if (errno != EINTR)
2267c478bd9Sstevel@tonic-gate return (EXEC_EXIT_NPORT);
2277c478bd9Sstevel@tonic-gate else if (SigAlrm)
2287c478bd9Sstevel@tonic-gate return (EXEC_EXIT_TMOUT);
2297c478bd9Sstevel@tonic-gate }
2307c478bd9Sstevel@tonic-gate
231de81e71eSTim Marsland alarm(oldalarm);
232de81e71eSTim Marsland signal(SIGALRM, oldsig);
2337c478bd9Sstevel@tonic-gate
2347c478bd9Sstevel@tonic-gate /*
2357c478bd9Sstevel@tonic-gate * Lock the file in case two "printers" are defined on the
2367c478bd9Sstevel@tonic-gate * same port. Don't lock /dev/null.
2377c478bd9Sstevel@tonic-gate */
2387c478bd9Sstevel@tonic-gate
2397c478bd9Sstevel@tonic-gate lck.l_type = F_WRLCK;
240de81e71eSTim Marsland lck.l_whence = 0;
2417c478bd9Sstevel@tonic-gate lck.l_start = 0L;
2427c478bd9Sstevel@tonic-gate lck.l_len = 0L;
2437c478bd9Sstevel@tonic-gate
2447c478bd9Sstevel@tonic-gate if (strcmp(device, "/dev/null") && Fcntl(fd, F_SETLKW, &lck) < 0) {
2457c478bd9Sstevel@tonic-gate execlog("lock error: %s\n", pp->device);
2467c478bd9Sstevel@tonic-gate return (EXEC_EXIT_NPORT);
2477c478bd9Sstevel@tonic-gate }
2487c478bd9Sstevel@tonic-gate
2497c478bd9Sstevel@tonic-gate /*
2507c478bd9Sstevel@tonic-gate * We should get the correct channel number (1), but just
2517c478bd9Sstevel@tonic-gate * in case....
2527c478bd9Sstevel@tonic-gate */
2537c478bd9Sstevel@tonic-gate if (fd != 1) {
254de81e71eSTim Marsland dup2(fd, 1);
255de81e71eSTim Marsland Close(fd);
2567c478bd9Sstevel@tonic-gate }
2577c478bd9Sstevel@tonic-gate
2587c478bd9Sstevel@tonic-gate /*
2597c478bd9Sstevel@tonic-gate * Handle streams modules:
2607c478bd9Sstevel@tonic-gate */
2617c478bd9Sstevel@tonic-gate if (fstat(1, &buf))
2627c478bd9Sstevel@tonic-gate buf.st_mode = 0;
2637c478bd9Sstevel@tonic-gate
2647c478bd9Sstevel@tonic-gate /*
2657c478bd9Sstevel@tonic-gate * for some unknown reason, lpsched appears to pop the streams
2667c478bd9Sstevel@tonic-gate * modules off the device and push back some "default" ones,
2677c478bd9Sstevel@tonic-gate * unless a specific set were specified with the printer configuration.
2687c478bd9Sstevel@tonic-gate * This behaviour causes problems with the ECPP port, so if we have
2697c478bd9Sstevel@tonic-gate * an ECPP port, and nobody specified a set of modules to use, we
2707c478bd9Sstevel@tonic-gate * should leave it alone. Normally, we would not bother to play with
2717c478bd9Sstevel@tonic-gate * the streams modules, but it is possible that someone has come
2727c478bd9Sstevel@tonic-gate * to rely on this behaviour for other devices.
2737c478bd9Sstevel@tonic-gate */
2747c478bd9Sstevel@tonic-gate if ((pp->modules != NULL) && (pp->modules[0] != NULL) &&
2757c478bd9Sstevel@tonic-gate (strcmp(pp->modules[0], "default") != 0))
2767c478bd9Sstevel@tonic-gate modules = pp->modules;
2777c478bd9Sstevel@tonic-gate
2787c478bd9Sstevel@tonic-gate if ((modules == NULL) && (ioctl(1, ECPPIOC_GETPARMS, &ecpp_params) < 0))
2797c478bd9Sstevel@tonic-gate modules = getlist(DEFMODULES, LP_WS, LP_SEP);
2807c478bd9Sstevel@tonic-gate
2817c478bd9Sstevel@tonic-gate /* if "nopush" is supplied, leave the modules alone */
2827c478bd9Sstevel@tonic-gate if ((modules != NULL) && (modules[0] != NULL) &&
2837c478bd9Sstevel@tonic-gate (strcasecmp(modules[0], "nopush") == 0))
2847c478bd9Sstevel@tonic-gate modules = NULL;
2857c478bd9Sstevel@tonic-gate
2867c478bd9Sstevel@tonic-gate /*
2877c478bd9Sstevel@tonic-gate * If we have a stream and a list of modules to use, then pop the old
2887c478bd9Sstevel@tonic-gate * modules and push the new ones.
2897c478bd9Sstevel@tonic-gate */
2904bc0a2efScasper if ((modules != NULL) && !S_ISFIFO(buf.st_mode) && isastream(1)) {
2917c478bd9Sstevel@tonic-gate /*
2927c478bd9Sstevel@tonic-gate * First, pop all current modules off, unless
2937c478bd9Sstevel@tonic-gate * instructed not to.
2947c478bd9Sstevel@tonic-gate */
2957c478bd9Sstevel@tonic-gate while (ioctl(1, I_POP, 0) == 0)
296de81e71eSTim Marsland ;
2977c478bd9Sstevel@tonic-gate
2987c478bd9Sstevel@tonic-gate /*
2997c478bd9Sstevel@tonic-gate * Now push either the administrator specified modules
3007c478bd9Sstevel@tonic-gate * or the standard modules, unless instructed to push
3017c478bd9Sstevel@tonic-gate * nothing.
3027c478bd9Sstevel@tonic-gate */
3037c478bd9Sstevel@tonic-gate
3047c478bd9Sstevel@tonic-gate if ((modules[1] == NULL) &&
3057c478bd9Sstevel@tonic-gate (strcasecmp(modules[0], "none") == 0))
3067c478bd9Sstevel@tonic-gate return (0);
3077c478bd9Sstevel@tonic-gate
3087c478bd9Sstevel@tonic-gate while (*modules)
3097c478bd9Sstevel@tonic-gate if (push_module(1, device, *modules++) == -1)
3107c478bd9Sstevel@tonic-gate return (EXEC_EXIT_NPUSH);
3117c478bd9Sstevel@tonic-gate }
3127c478bd9Sstevel@tonic-gate
3137c478bd9Sstevel@tonic-gate return (0);
3147c478bd9Sstevel@tonic-gate }
3157c478bd9Sstevel@tonic-gate
316de81e71eSTim Marsland /*
317de81e71eSTim Marsland * sigalrm()
318de81e71eSTim Marsland */
3197c478bd9Sstevel@tonic-gate static void
sigalrm(int ignore)3207c478bd9Sstevel@tonic-gate sigalrm(int ignore)
3217c478bd9Sstevel@tonic-gate {
322de81e71eSTim Marsland signal(SIGALRM, SIG_IGN);
3237c478bd9Sstevel@tonic-gate SigAlrm = 1;
3247c478bd9Sstevel@tonic-gate }
3257c478bd9Sstevel@tonic-gate
3267c478bd9Sstevel@tonic-gate
327de81e71eSTim Marsland /*
328de81e71eSTim Marsland * push_module()
329de81e71eSTim Marsland */
3307c478bd9Sstevel@tonic-gate
3317c478bd9Sstevel@tonic-gate static int
push_module(int fd,char * device,char * module)3327c478bd9Sstevel@tonic-gate push_module(int fd, char *device, char *module)
3337c478bd9Sstevel@tonic-gate {
334de81e71eSTim Marsland int ret = ioctl(fd, I_PUSH, module);
3357c478bd9Sstevel@tonic-gate
3367c478bd9Sstevel@tonic-gate if (ret == -1)
337de81e71eSTim Marsland note("push (%s) on %s failed (%s)\n", module, device, PERROR);
3387c478bd9Sstevel@tonic-gate return (ret);
3397c478bd9Sstevel@tonic-gate }
340