1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241
|
//
// LPD.pmod: an implementation of the BSD lpd protocol (RFC 1179).
// This is a module for pike.
// 3 July 1998 <hww3@riverweb.com> Bill Welliver
//
// $Id: LPD.pmod,v 1.10 2008/01/13 17:02:43 nilsson Exp $
//
#pike __REAL_VERSION__
//! A client for communicating with printers and print spoolers that
//! support the BSD lpd protocol (RFC 1179).
class client {
string host;
int port;
private object conn;
int jobnum;
string jobtype;
string jobname;
private int connect(string host, int port)
{
int a=random(10);
// try to open one of the "official" local socket ports.
// not having one doesn't seem to be a problem with most LPD
// servers, but we should at least try. will probably fail
// if two try to open the same local port at once. ymmv.
int res=conn->open_socket(721 + a);
return conn->connect(host, port);
}
//! @decl int set_job_type(string type)
//! Set the type of job to be sent to the printer to @i{type@}.
//! Valid types are: text, postscript and raw.
int set_job_type(string type)
{
type=lower_case(type);
switch (type) {
case "f":
case "text":
jobtype="f";
break;
case "o":
case "postscript":
case "ps":
jobtype="o";
break;
default:
case "l":
case "raw":
jobtype="l";
break;
}
return 1;
}
//! @decl int set_job_name(string name)
//! Sets the name of the print job to @i{name@}.
int set_job_name(string name)
{
jobname=name;
return 1;
}
//! @decl int start_queue(string queue)
//! Start the queue @i{queue@} if not already printing.
//! @returns
//! Returns 0 if unable to connect, 1 otherwise.
int start_queue(string queue)
{
if(!queue) return 0;
if(!connect(host, port))
return 0;
conn->write(sprintf("%c%s\n", 01, queue));
string resp= conn->read();
conn->close();
return 1;
}
//! @decl string|int send_job(string queue, string job)
//! Send print job consisting of data @i{job@} to printer @i{queue@}.
//! @returns
//! Returns 1 if success, 0 otherwise.
int send_job(string queue, string job)
{
string resp;
if(!queue) return 0;
if(!connect(host, port))
return 0;
// werror("connected to " + host + "\n");
string control="";
control+="H"+gethostname()+"\n";
#if constant(getuid) && constant(getpwuid)
control+="P"+(getpwuid(getuid())[0]||"nobody")+"\n";
#else
control+="P-1\n";
#endif
control+=(jobtype||"l")+"dfA"+ sprintf("%03d%s", jobnum, gethostname())+"\n";
if(jobname)
{
control+="J" + jobname + "\n";
control+="N" + jobname + "\n";
}
else
{
control+="JPike LPD Client Job " + jobnum + "\n";
control+="NPike LPD Client Job " + jobnum + "\n";
}
jobnum++;
werror("job file:\n\n" + control + "\n\n");
conn->write(sprintf("%c%s\n", 02, queue));
resp=conn->read(1);
if((int)resp !=0)
{
werror("receive job failed.\n");
return 0;
}
conn->write(sprintf("%c%s cfA%03d%s\n", 02, (string)sizeof(control),
jobnum,gethostname()));
resp=conn->read(1);
if((int)resp !=0)
{
werror("request receive control failed.\n");
return 0;
}
conn->write(sprintf("%s%c", control, 0));
resp=conn->read(1);
if((int)resp !=0)
{
werror("send receive control failed.\n");
return 0;
}
conn->write(sprintf("%c%s dfA%03d%s\n", 03, (string)sizeof(job), jobnum,
gethostname()));
resp=conn->read(1);
if((int)resp !=0)
{
werror("request receive job failed.\n");
return 0;
}
conn->write(sprintf("%s%c", job, 0));
resp=conn->read(1);
if((int)resp !=0)
{
werror("send receive job failed.\n");
return 0;
}
// read the response.
// resp=conn->read();
if((int)(resp)!=0)
{
conn->close();
return 0;
}
conn->close();
// start_queue(queue);
return 1;
}
//! @decl int delete_job(string queue, int|void job)
//! Delete job @i{job@} from printer @i{queue@}.
//! @returns
//! Returns 1 on success, 0 otherwise.
int delete_job(string queue, int|void job)
{
if(!queue) return 0;
if(!connect(host, port))
return 0;
#if constant(getpwuid) && constant(getuid)
string agent=(getpwuid(getuid())[0]||"nobody");
#else
string agent="nobody";
#endif
if(job)
conn->write(sprintf("%c%s %s %d\n", 05, queue, agent, job));
else
conn->write(sprintf("%c%s %s\n", 05, queue, agent));
string resp= conn->read();
conn->close();
return 1;
}
//! @decl string|int status(string queue)
//! Check the status of queue @i{queue@}.
//! @returns
//! Returns 0 on failure, otherwise returns the status response from the printer.
string|int status(string queue)
{
if(!queue) return 0;
if(!connect(host, port))
return 0;
conn->write(sprintf("%c%s\n", 04, queue));
string resp= conn->read();
conn->close();
return resp;
}
//! Create a new LPD client connection.
//! @param hostname
//! Contains the hostname or ipaddress of the print host.
//! if not provided, defaults to @i{localhost@}.
//! @param portnum
//! Contains the port the print host is listening on.
//! if not provided, defaults to port @i{515@}, the RFC 1179 standard.
void create(string|void hostname, int|void portnum)
{
host=hostname || "localhost";
port=portnum || 515;
conn=Stdio.File();
jobnum=1;
}
}
|