1/* 2 * This program is free software; you can redistribute it and/or 3 * modify it under the terms of the GNU General Public License as 4 * published by the Free Software Foundation; either version 2 of 5 * the License, or (at your option) any later version. 6 * 7 * This program is distributed in the hope that it will be useful, 8 * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 * GNU General Public License for more details. 11 * 12 * You should have received a copy of the GNU General Public License 13 * along with this program; if not, write to the Free Software 14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 15 * MA 02111-1307 USA 16 */ 17/*************************************************************************** 18 * LPRng - An Extended Print Spooler System 19 * 20 * Copyright 1988-2003, Patrick Powell, San Diego, CA 21 * papowell@lprng.com 22 * See LICENSE for conditions of use. 23 * 24 ***************************************************************************/ 25 26 static char *const _id = 27"$Id: sendreq.c,v 1.1.1.1 2008/10/15 03:28:27 james26_jang Exp $"; 28 29 30#include "lp.h" 31 32#include "child.h" 33#include "fileopen.h" 34#include "getqueue.h" 35#include "linksupport.h" 36#include "readstatus.h" 37#include "user_auth.h" 38#include "sendreq.h" 39#include "sendauth.h" 40 41/**** ENDINCLUDE ****/ 42 43 44/*************************************************************************** 45 * Commentary: 46 * The protocol used to send requests to a remote host consists of the 47 * following: 48 * 49 * Client Server 50 * - short format 51 * \Xprintername option option\n - request 52 * status\n 53 * .... 54 * status\n 55 * <close connection> 56 * 57 * The requestor: 58 * 1. makes a connection (connection timeout) 59 * 2. sends the \3printername options line 60 * 3. reads from the connection until nothing left 61 * 62 * int Send_request( char *printer, * name of printer * 63 * char *host, * name of remote host * 64 * int class, * 'Q'= LPQ, 'C'= LPC, M = lprm * 65 * int format, * X value for request * 66 * char **options, * options to send * 67 * int connnect_timeout, * timeout on connection * 68 * int transfer_timeout, * timeout on transfer * 69 * int output ) * output fd 70 * 71 **************************************************************************/ 72 73 74/*************************************************************************** 75 * Send_request 76 * 1. Open connection to remote host 77 * 2. Send a line of the form: 78 * \Xprinter <options> 79 * 3. Read from the connection until closed and echo on fd 1 80 ***************************************************************************/ 81 82int Send_request( 83 int class, /* 'Q'= LPQ, 'C'= LPC, M = lprm */ 84 int format, /* X for option */ 85 char **options, /* options to send */ 86 int connnect_timeout, /* timeout on connection */ 87 int transfer_timeout, /* timeout on transfer */ 88 int output /* output on this FD */ 89 ) 90{ 91 char errormsg[LARGEBUFFER]; 92 char *cmd = 0; 93 int status = -1, sock = -1, err; 94 char *real_host = 0; 95 char *save_host = 0; 96 struct security *security = 0; 97 struct line_list info; 98 99 Init_line_list(&info); 100 errormsg[0] = 0; 101 102 DEBUG1("Send_request: printer '%s', host '%s', format %d", 103 RemotePrinter_DYN, RemoteHost_DYN, format ); 104 DEBUG1("Send_request: connnect_timeout %d, transfer_timeout %d", 105 connnect_timeout, transfer_timeout ); 106 107#ifdef ORIGINAL_DEBUG//JY@1020 108 security = Fix_send_auth(0,&info, 0, errormsg, sizeof(errormsg) ); 109#endif 110 111 DEBUG1("Send_request: security %s", security?security->name:0 ); 112 if( security ){ 113 DEBUG1("Send_request: security name '%s', tag '%s'", 114 security->name, security->config_tag ); 115 } 116 if( errormsg[0] ){ 117 goto error; 118 } 119 120 if( islower( class ) ) class = toupper(class); 121 122 if( Remote_support_DYN ) uppercase( Remote_support_DYN ); 123 if( islower(class) ) class = toupper(class); 124 if( safestrchr( Remote_support_DYN, class ) == 0 ){ 125 char *m = "unknown"; 126 switch( class ){ 127 case 'R': m = "lpr"; break; 128 case 'M': m = "lprm"; break; 129 case 'Q': m = "lpq"; break; 130 case 'V': m = "lpq -v"; break; 131 case 'C': m = "lpc"; break; 132 } 133 DEBUG1("Send_request: no remote support for %c - '%s' operation", class, m ); 134 if( !Is_server ){ 135 SNPRINTF(errormsg,sizeof(errormsg)) 136 _("no network support for '%s' operation"), m); 137 } 138 status = 0; 139 goto error; 140 } 141 142 cmd = safestrdup2(" ",RemotePrinter_DYN,__FILE__,__LINE__); 143 cmd[0] = format; 144 if( options ){ 145 for( ; options && *options; ++options ){ 146 cmd = safeextend3(cmd," ",*options, __FILE__,__LINE__ ); 147 } 148 } 149 DEBUG1("Send_request: command '%s'", cmd ); 150 cmd = safeextend2(cmd,"\n", __FILE__,__LINE__ ); 151 errno = 0; 152 153#ifdef ORIGINAL_DEBUG//JY@1020 154 sock = Link_open_list( RemoteHost_DYN, 155 &real_host, connnect_timeout, 0, Unix_socket_path_DYN ); 156#endif 157 err = errno; 158 if( sock < 0 ){ 159 char *msg = ""; 160 SNPRINTF( errormsg, sizeof(errormsg)-2) 161 "cannot open connection - %s", 162 err?Errormsg(err):"bad or missing hostname" ); 163 if( !Is_server ){ 164 int v = safestrlen(errormsg); 165 SNPRINTF( errormsg+v, sizeof(errormsg)-v) 166 "\nMake sure the remote host supports the LPD protocol"); 167 if( geteuid() && getuid() ){ 168 v = safestrlen(errormsg); 169 SNPRINTF( errormsg+v, sizeof(errormsg)-v) 170 "\nand accepts connections from this host and from non-privileged (>1023) ports"); 171 } 172 } 173 goto error; 174 } 175 176 DEBUG1("Send_request: socket %d, real host '%s'", sock, real_host ); 177 save_host = safestrdup(RemoteHost_DYN,__FILE__,__LINE__); 178 Set_DYN(&RemoteHost_DYN, real_host ); 179 if( real_host ) free( real_host ); real_host = 0; 180 181 if( security && security->client_connect ){ 182 DEBUG1("Send_request: security '%s', using connect", security->name ); 183 status = security->client_connect( 0, &sock, 184 transfer_timeout, 185 errormsg, sizeof(errormsg), 186 security, &info ); 187 DEBUG1("Send_request: connect status %d, error '%s'", status, errormsg ); 188 if( status ) goto error; 189 } 190 /* now send the command line */ 191 if( security && security->client_send ){ 192#ifdef ORIGINAL_DEBUG//JY@1020 193 status = Send_auth_transfer( &sock, transfer_timeout, 0, 0, 194 errormsg, sizeof(errormsg), cmd, security, &info ); 195#endif 196 } else { 197 status = Link_send( RemoteHost_DYN, &sock, transfer_timeout, 198 cmd, safestrlen(cmd), 0 ); 199 if( status ){ 200 SNPRINTF(errormsg,sizeof(errormsg))"%s",Link_err_str(status)); 201 close(sock); sock = -1; 202 goto error; 203 } 204 } 205 206 error: 207 if( status || errormsg[0] ){ 208 char line[SMALLBUFFER]; 209 SNPRINTF( line,sizeof(line)) "Printer '%s@%s' - ", 210 RemotePrinter_DYN, RemoteHost_DYN ); 211 if( Write_fd_str( output, line ) < 0 212 || Write_fd_str( output, errormsg ) < 0 213 || Write_fd_str( output, "\n" ) < 0 ) cleanup(0); 214 } 215 if( save_host ){ 216 Set_DYN(&RemoteHost_DYN,save_host); 217 free(save_host); save_host = 0; 218 } 219 if( cmd ) free(cmd); cmd = 0; 220 Free_line_list(&info); 221 return( sock ); 222} 223