1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate 23*0Sstevel@tonic-gate /* 24*0Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 25*0Sstevel@tonic-gate * Use is subject to license terms. 26*0Sstevel@tonic-gate */ 27*0Sstevel@tonic-gate 28*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 29*0Sstevel@tonic-gate 30*0Sstevel@tonic-gate #include <stdio.h> 31*0Sstevel@tonic-gate #include <stdlib.h> 32*0Sstevel@tonic-gate #include <stdarg.h> 33*0Sstevel@tonic-gate #include <libintl.h> 34*0Sstevel@tonic-gate #include <signal.h> 35*0Sstevel@tonic-gate #include <errno.h> 36*0Sstevel@tonic-gate #include <fcntl.h> 37*0Sstevel@tonic-gate #include <unistd.h> 38*0Sstevel@tonic-gate #include <string.h> 39*0Sstevel@tonic-gate #include <strings.h> 40*0Sstevel@tonic-gate #include <syslog.h> 41*0Sstevel@tonic-gate #include <sys/types.h> 42*0Sstevel@tonic-gate #include <sys/socket.h> 43*0Sstevel@tonic-gate #include <sys/file.h> 44*0Sstevel@tonic-gate #include <netinet/in.h> 45*0Sstevel@tonic-gate #include "netpr.h" 46*0Sstevel@tonic-gate 47*0Sstevel@tonic-gate #define TIMEOUT 1 48*0Sstevel@tonic-gate 49*0Sstevel@tonic-gate static int netpr_send_message(int, char *, ...); 50*0Sstevel@tonic-gate static int xfer_cfAfile(int, char *, char *, uint); 51*0Sstevel@tonic-gate 52*0Sstevel@tonic-gate int 53*0Sstevel@tonic-gate bsd_print(int sockfd, caddr_t pa, np_bsdjob_t * bsdjob) 54*0Sstevel@tonic-gate { 55*0Sstevel@tonic-gate int filesize; 56*0Sstevel@tonic-gate int xfer; 57*0Sstevel@tonic-gate int net; 58*0Sstevel@tonic-gate 59*0Sstevel@tonic-gate syslog(LOG_DEBUG, "bsd_print"); 60*0Sstevel@tonic-gate 61*0Sstevel@tonic-gate filesize = bsdjob->np_data->np_data_size; 62*0Sstevel@tonic-gate syslog(LOG_DEBUG, "filesize is %d", filesize); 63*0Sstevel@tonic-gate 64*0Sstevel@tonic-gate 65*0Sstevel@tonic-gate if (netpr_send_message(sockfd, "%c%s\n", XFER_REQUEST, 66*0Sstevel@tonic-gate bsdjob->np_printer) != 0) { 67*0Sstevel@tonic-gate return (NETWORK_ERROR_SEND_RESPONSE); 68*0Sstevel@tonic-gate } 69*0Sstevel@tonic-gate 70*0Sstevel@tonic-gate /* 71*0Sstevel@tonic-gate * control file 72*0Sstevel@tonic-gate */ 73*0Sstevel@tonic-gate 74*0Sstevel@tonic-gate if (bsdjob->np_print_order == CONTROL_FIRST) { 75*0Sstevel@tonic-gate if ((xfer_cfAfile(sockfd, bsdjob->np_cfAfile, 76*0Sstevel@tonic-gate bsdjob->np_cfAfilename, 77*0Sstevel@tonic-gate bsdjob->np_cfAfilesize)) != 0) { 78*0Sstevel@tonic-gate (void) fprintf(stderr, 79*0Sstevel@tonic-gate gettext("Netpr: Error sending control file\n")); 80*0Sstevel@tonic-gate syslog(LOG_DEBUG, "Error sending control file"); 81*0Sstevel@tonic-gate return (NETWORK_ERROR_UNKNOWN); 82*0Sstevel@tonic-gate 83*0Sstevel@tonic-gate } 84*0Sstevel@tonic-gate } 85*0Sstevel@tonic-gate 86*0Sstevel@tonic-gate /* send msg - get ready for transfer */ 87*0Sstevel@tonic-gate 88*0Sstevel@tonic-gate if ((netpr_send_message(sockfd, "%c%d %s\n", XFER_DATA, filesize, 89*0Sstevel@tonic-gate bsdjob->np_data->np_dfAfilename)) != 0) { 90*0Sstevel@tonic-gate return (NETWORK_ERROR_SEND_RESPONSE); 91*0Sstevel@tonic-gate } 92*0Sstevel@tonic-gate 93*0Sstevel@tonic-gate /* 94*0Sstevel@tonic-gate * send the file 95*0Sstevel@tonic-gate */ 96*0Sstevel@tonic-gate 97*0Sstevel@tonic-gate if ((xfer = xfer_file(sockfd, pa, filesize, bsdjob->np_timeout)) != 0) { 98*0Sstevel@tonic-gate return (xfer); 99*0Sstevel@tonic-gate } 100*0Sstevel@tonic-gate 101*0Sstevel@tonic-gate /* send msg - done */ 102*0Sstevel@tonic-gate if ((net = netpr_send_message(sockfd, "", NULL)) != 0) { 103*0Sstevel@tonic-gate (void) fprintf(stderr, 104*0Sstevel@tonic-gate gettext("Netpr: network error transfering %s returns: %d\n"), 105*0Sstevel@tonic-gate bsdjob->np_filename, net); 106*0Sstevel@tonic-gate syslog(LOG_DEBUG, 107*0Sstevel@tonic-gate "network error transfering %s returns: %d", 108*0Sstevel@tonic-gate bsdjob->np_filename, net); 109*0Sstevel@tonic-gate return (NETWORK_ERROR_WRITE_FAILED); 110*0Sstevel@tonic-gate } 111*0Sstevel@tonic-gate 112*0Sstevel@tonic-gate /* 113*0Sstevel@tonic-gate * control file 114*0Sstevel@tonic-gate */ 115*0Sstevel@tonic-gate 116*0Sstevel@tonic-gate if (bsdjob->np_print_order == DATA_FIRST) { 117*0Sstevel@tonic-gate if ((xfer_cfAfile(sockfd, bsdjob->np_cfAfile, 118*0Sstevel@tonic-gate bsdjob->np_cfAfilename, 119*0Sstevel@tonic-gate bsdjob->np_cfAfilesize)) != 0) { 120*0Sstevel@tonic-gate 121*0Sstevel@tonic-gate (void) fprintf(stderr, 122*0Sstevel@tonic-gate gettext("Netpr: Error sending control file\n")); 123*0Sstevel@tonic-gate syslog(LOG_DEBUG, "Error sending control file"); 124*0Sstevel@tonic-gate return (NETWORK_ERROR_UNKNOWN); 125*0Sstevel@tonic-gate } 126*0Sstevel@tonic-gate } 127*0Sstevel@tonic-gate 128*0Sstevel@tonic-gate return (0); 129*0Sstevel@tonic-gate } 130*0Sstevel@tonic-gate 131*0Sstevel@tonic-gate int 132*0Sstevel@tonic-gate xfer_file(int sockfd, caddr_t pa, int filesize, int seed) 133*0Sstevel@tonic-gate { 134*0Sstevel@tonic-gate int ctr; 135*0Sstevel@tonic-gate int timeout; 136*0Sstevel@tonic-gate int nw; 137*0Sstevel@tonic-gate int error_msg = 0; 138*0Sstevel@tonic-gate int pause = 0; 139*0Sstevel@tonic-gate 140*0Sstevel@tonic-gate syslog(LOG_DEBUG, "xfer_file"); 141*0Sstevel@tonic-gate 142*0Sstevel@tonic-gate /* send file */ 143*0Sstevel@tonic-gate ctr = filesize; 144*0Sstevel@tonic-gate timeout = seed = seed ? seed : 10; 145*0Sstevel@tonic-gate 146*0Sstevel@tonic-gate while (ctr > 0) { 147*0Sstevel@tonic-gate 148*0Sstevel@tonic-gate syslog(LOG_DEBUG, "xfer_file: write while loop => ctr = %d", ctr); 149*0Sstevel@tonic-gate syslog(LOG_DEBUG, "xfer_file: timeout = %d", timeout); 150*0Sstevel@tonic-gate 151*0Sstevel@tonic-gate (void) signal(SIGALRM, null_sighandler); 152*0Sstevel@tonic-gate (void) alarm(2); 153*0Sstevel@tonic-gate nw = write(sockfd, pa, ctr); 154*0Sstevel@tonic-gate syslog(LOG_DEBUG, "xfer_file: write while loop => nw = %d", nw); 155*0Sstevel@tonic-gate (void) alarm(0); 156*0Sstevel@tonic-gate if ((nw == 0) || (nw < 0)) { 157*0Sstevel@tonic-gate if (timeout < (seed * 4)) { 158*0Sstevel@tonic-gate (void) sleep(timeout); 159*0Sstevel@tonic-gate timeout *= 2; 160*0Sstevel@tonic-gate } else if (timeout == (seed * 4)) { 161*0Sstevel@tonic-gate (void) sleep(timeout); 162*0Sstevel@tonic-gate timeout *= 2; 163*0Sstevel@tonic-gate 164*0Sstevel@tonic-gate /* 165*0Sstevel@tonic-gate * Send message to user once 166*0Sstevel@tonic-gate */ 167*0Sstevel@tonic-gate if (error_msg == 0) { 168*0Sstevel@tonic-gate error_msg++; 169*0Sstevel@tonic-gate tell_lptell(ERRORMSG, 170*0Sstevel@tonic-gate gettext("Printer not accepting input;" 171*0Sstevel@tonic-gate "possibly offline or out of paper.")); 172*0Sstevel@tonic-gate } 173*0Sstevel@tonic-gate 174*0Sstevel@tonic-gate } else if (timeout > (seed * 4)) { 175*0Sstevel@tonic-gate (void) sleep(timeout); 176*0Sstevel@tonic-gate if (pause++ > 3) 177*0Sstevel@tonic-gate timeout = (seed * 10); 178*0Sstevel@tonic-gate } 179*0Sstevel@tonic-gate 180*0Sstevel@tonic-gate } else { 181*0Sstevel@tonic-gate ctr -= nw; 182*0Sstevel@tonic-gate pa += nw; 183*0Sstevel@tonic-gate if (error_msg) { 184*0Sstevel@tonic-gate tell_lptell(OKMSG, "Current"); 185*0Sstevel@tonic-gate error_msg = 0; 186*0Sstevel@tonic-gate pause = 0; 187*0Sstevel@tonic-gate } 188*0Sstevel@tonic-gate timeout = seed; 189*0Sstevel@tonic-gate } 190*0Sstevel@tonic-gate } 191*0Sstevel@tonic-gate 192*0Sstevel@tonic-gate return (E_SUCCESS); 193*0Sstevel@tonic-gate } 194*0Sstevel@tonic-gate 195*0Sstevel@tonic-gate static int 196*0Sstevel@tonic-gate xfer_cfAfile(int sockfd, char * cfAfile, char * cfAname, uint size) 197*0Sstevel@tonic-gate { 198*0Sstevel@tonic-gate int ctr; 199*0Sstevel@tonic-gate caddr_t pa; 200*0Sstevel@tonic-gate int nw = 0; 201*0Sstevel@tonic-gate int timeout; 202*0Sstevel@tonic-gate int printererr; 203*0Sstevel@tonic-gate 204*0Sstevel@tonic-gate syslog(LOG_DEBUG, "xfer_cfAfile"); 205*0Sstevel@tonic-gate 206*0Sstevel@tonic-gate if ((netpr_send_message(sockfd, "%c%d %s\n", XFER_CONTROL, 207*0Sstevel@tonic-gate size, cfAname)) != 0) { 208*0Sstevel@tonic-gate return (NETWORK_ERROR_MSG_FAILED); 209*0Sstevel@tonic-gate } 210*0Sstevel@tonic-gate 211*0Sstevel@tonic-gate /* send the control file */ 212*0Sstevel@tonic-gate pa = cfAfile; 213*0Sstevel@tonic-gate ctr = size; 214*0Sstevel@tonic-gate syslog(LOG_DEBUG, "xfer_cfAfile : cfAfile %s", pa); 215*0Sstevel@tonic-gate syslog(LOG_DEBUG, "xfer_cfAfile : size %d", size); 216*0Sstevel@tonic-gate 217*0Sstevel@tonic-gate /* send control file */ 218*0Sstevel@tonic-gate timeout = TIMEOUT; 219*0Sstevel@tonic-gate printererr = 0; 220*0Sstevel@tonic-gate while (ctr > 0) { 221*0Sstevel@tonic-gate (void) signal(SIGALRM, null_sighandler); 222*0Sstevel@tonic-gate (void) alarm(2); 223*0Sstevel@tonic-gate nw = write(sockfd, pa, size); 224*0Sstevel@tonic-gate (void) alarm(0); 225*0Sstevel@tonic-gate if (nw <= 0) { 226*0Sstevel@tonic-gate if (timeout < 16) { 227*0Sstevel@tonic-gate (void) sleep(timeout); 228*0Sstevel@tonic-gate timeout *= 2; 229*0Sstevel@tonic-gate } else if (timeout == 16) { 230*0Sstevel@tonic-gate /* talk with the printer and see what's happening */ 231*0Sstevel@tonic-gate /* send message back to caller */ 232*0Sstevel@tonic-gate (void) sleep(timeout); 233*0Sstevel@tonic-gate timeout *= 2; 234*0Sstevel@tonic-gate printererr = 1; 235*0Sstevel@tonic-gate 236*0Sstevel@tonic-gate tell_lptell(ERRORMSG, 237*0Sstevel@tonic-gate gettext("Printer not accepting input;" 238*0Sstevel@tonic-gate "possibly offline or out of paper.")); 239*0Sstevel@tonic-gate 240*0Sstevel@tonic-gate } else if (timeout > 16) { 241*0Sstevel@tonic-gate (void) sleep(timeout); 242*0Sstevel@tonic-gate } 243*0Sstevel@tonic-gate } 244*0Sstevel@tonic-gate ctr -= nw; 245*0Sstevel@tonic-gate pa += nw; 246*0Sstevel@tonic-gate } 247*0Sstevel@tonic-gate 248*0Sstevel@tonic-gate if (printererr == 1) { 249*0Sstevel@tonic-gate (void) fprintf(stderr, gettext("Printer status ok\n")); 250*0Sstevel@tonic-gate tell_lptell(OKMSG, "Current"); 251*0Sstevel@tonic-gate } 252*0Sstevel@tonic-gate 253*0Sstevel@tonic-gate 254*0Sstevel@tonic-gate /* send msg - done */ 255*0Sstevel@tonic-gate if (netpr_send_message(sockfd, "", NULL) != 0) { 256*0Sstevel@tonic-gate return (NETWORK_ERROR_MSG_FAILED); 257*0Sstevel@tonic-gate } 258*0Sstevel@tonic-gate 259*0Sstevel@tonic-gate return (0); 260*0Sstevel@tonic-gate } 261*0Sstevel@tonic-gate 262*0Sstevel@tonic-gate /* 263*0Sstevel@tonic-gate * netpr_response() reads in a byte from the network printer 264*0Sstevel@tonic-gate */ 265*0Sstevel@tonic-gate static int 266*0Sstevel@tonic-gate netpr_response(int nd) 267*0Sstevel@tonic-gate { 268*0Sstevel@tonic-gate char c; 269*0Sstevel@tonic-gate int msg_given = 0; 270*0Sstevel@tonic-gate int firstloop = 0; 271*0Sstevel@tonic-gate 272*0Sstevel@tonic-gate syslog(LOG_DEBUG, "netpr_response"); 273*0Sstevel@tonic-gate 274*0Sstevel@tonic-gate (void) signal(SIGALRM, null_sighandler); 275*0Sstevel@tonic-gate (void) alarm(2); 276*0Sstevel@tonic-gate while (1) { 277*0Sstevel@tonic-gate errno = 0; 278*0Sstevel@tonic-gate if ((read(nd, &c, 1) != 1)) { 279*0Sstevel@tonic-gate 280*0Sstevel@tonic-gate if (firstloop == 0) { 281*0Sstevel@tonic-gate (void) alarm(0); 282*0Sstevel@tonic-gate firstloop++; 283*0Sstevel@tonic-gate } 284*0Sstevel@tonic-gate 285*0Sstevel@tonic-gate if (errno == EINTR) { 286*0Sstevel@tonic-gate if (msg_given == 0) { 287*0Sstevel@tonic-gate tell_lptell(ERRORMSG, 288*0Sstevel@tonic-gate gettext("Printer not responding;" 289*0Sstevel@tonic-gate "Either warming up or needs attention")); 290*0Sstevel@tonic-gate msg_given++; 291*0Sstevel@tonic-gate syslog(LOG_DEBUG, 292*0Sstevel@tonic-gate "read hanging in netpr_response: %m"); 293*0Sstevel@tonic-gate } 294*0Sstevel@tonic-gate 295*0Sstevel@tonic-gate } else { 296*0Sstevel@tonic-gate syslog(LOG_DEBUG, 297*0Sstevel@tonic-gate "read in netpr_response failed: %m"); 298*0Sstevel@tonic-gate return (NETWORK_READ_RESPONSE_FAILED); 299*0Sstevel@tonic-gate } 300*0Sstevel@tonic-gate 301*0Sstevel@tonic-gate } else { 302*0Sstevel@tonic-gate if (c) { 303*0Sstevel@tonic-gate syslog(LOG_DEBUG, 304*0Sstevel@tonic-gate "Printer returned error: %m"); 305*0Sstevel@tonic-gate return (NETWORK_PRINTER_REFUSED_CONN); 306*0Sstevel@tonic-gate } else { 307*0Sstevel@tonic-gate if (msg_given) 308*0Sstevel@tonic-gate tell_lptell(OKMSG, "Current"); 309*0Sstevel@tonic-gate return (0); 310*0Sstevel@tonic-gate } 311*0Sstevel@tonic-gate } 312*0Sstevel@tonic-gate } 313*0Sstevel@tonic-gate 314*0Sstevel@tonic-gate } 315*0Sstevel@tonic-gate 316*0Sstevel@tonic-gate static int 317*0Sstevel@tonic-gate netpr_send_message(int nd, char *fmt, ...) 318*0Sstevel@tonic-gate { 319*0Sstevel@tonic-gate char buf[BUFSIZ]; 320*0Sstevel@tonic-gate int ctr; 321*0Sstevel@tonic-gate char * pa; 322*0Sstevel@tonic-gate va_list ap; 323*0Sstevel@tonic-gate int timeout = 1; 324*0Sstevel@tonic-gate int nw; 325*0Sstevel@tonic-gate int err_msg = 0; 326*0Sstevel@tonic-gate 327*0Sstevel@tonic-gate syslog(LOG_DEBUG, "netpr_send_message"); 328*0Sstevel@tonic-gate va_start(ap, fmt); 329*0Sstevel@tonic-gate (void) vsnprintf(buf, sizeof (buf), fmt, ap); 330*0Sstevel@tonic-gate va_end(ap); 331*0Sstevel@tonic-gate 332*0Sstevel@tonic-gate pa = buf; 333*0Sstevel@tonic-gate ctr = (strlen(buf) != 0) ? strlen(buf) : 1; 334*0Sstevel@tonic-gate 335*0Sstevel@tonic-gate syslog(LOG_DEBUG, "netpr_send_message : ctr = %d", ctr); 336*0Sstevel@tonic-gate while (ctr > 0) { 337*0Sstevel@tonic-gate (void) signal(SIGALRM, null_sighandler); 338*0Sstevel@tonic-gate (void) alarm(2); 339*0Sstevel@tonic-gate nw = write(nd, pa, ctr); 340*0Sstevel@tonic-gate syslog(LOG_DEBUG, "netpr_send_message : nw = %d", nw); 341*0Sstevel@tonic-gate (void) alarm(0); 342*0Sstevel@tonic-gate 343*0Sstevel@tonic-gate if (nw <= 0) { 344*0Sstevel@tonic-gate if (timeout < 16) { 345*0Sstevel@tonic-gate (void) sleep(timeout); 346*0Sstevel@tonic-gate timeout *= 2; 347*0Sstevel@tonic-gate } else if (timeout == 16) { 348*0Sstevel@tonic-gate (void) sleep(timeout); 349*0Sstevel@tonic-gate timeout *= 2; 350*0Sstevel@tonic-gate if (err_msg == 0) { 351*0Sstevel@tonic-gate err_msg++; 352*0Sstevel@tonic-gate tell_lptell(ERRORMSG, 353*0Sstevel@tonic-gate gettext("Printer not accepting input;" 354*0Sstevel@tonic-gate "possibly offline or out of paper.")); 355*0Sstevel@tonic-gate } 356*0Sstevel@tonic-gate } else 357*0Sstevel@tonic-gate (void) sleep(timeout); 358*0Sstevel@tonic-gate } else { 359*0Sstevel@tonic-gate ctr -= nw; 360*0Sstevel@tonic-gate pa += nw; 361*0Sstevel@tonic-gate if (err_msg) 362*0Sstevel@tonic-gate tell_lptell(OKMSG, "Current"); 363*0Sstevel@tonic-gate } 364*0Sstevel@tonic-gate } 365*0Sstevel@tonic-gate 366*0Sstevel@tonic-gate return (netpr_response(nd)); 367*0Sstevel@tonic-gate } 368*0Sstevel@tonic-gate 369*0Sstevel@tonic-gate /* 370*0Sstevel@tonic-gate * null() is to be used as a signal handler that does nothing. It is used in 371*0Sstevel@tonic-gate * place of SIG_IGN, because we want the signal to be delivered and 372*0Sstevel@tonic-gate * interupt the current system call. 373*0Sstevel@tonic-gate */ 374*0Sstevel@tonic-gate /*ARGSUSED*/ 375*0Sstevel@tonic-gate void 376*0Sstevel@tonic-gate null_sighandler(int i) 377*0Sstevel@tonic-gate { 378*0Sstevel@tonic-gate } 379