1 // Sun, 18 Jun 2000
2 // Y.Takagi
3
4 #include <sys/socket.h>
5 #include <netdb.h>
6
7 #include <errno.h>
8 #include <string.h>
9
10 #include <iomanip>
11 #include <algorithm>
12 #include "LpsClient.h"
13 #include "Socket.h"
14
15
16 using namespace std;
17
18
19 #define LPS_SERVER_PORT 515
20 #define LPS_CLIENT_PORT_S 721
21 #define LPS_CLIENT_PORT_E 731
22
23 #define LPS_CHECK_QUEUE '\001'
24 #define LPS_PRINT_JOB '\002'
25 #define LPS_DISPLAY_SHORT_QUEUE '\003'
26 #define LPS_DISPLAY_LONG_QUEUE '\004'
27 #define LPS_REMOVE_JOB '\005'
28 #define LPS_END_TRANSFER '\000'
29 #define LPS_ABORT '\001'
30 #define LPS_RECEIVE_CONTROL_FILE '\002'
31 #define LPS_RECEIVE_DATA_FILE '\003'
32
33 #define LPS_OK '\0'
34 #define LPS_ERROR '\1'
35 #define LPS_NO_SPOOL_SPACE '\2'
36
37 #ifndef INADDR_NONE
38 #define INADDR_NONE 0xffffffff
39 #endif
40
41 #define ERRNO errno
42
43
LpsClient(const char * host)44 LpsClient::LpsClient(const char *host)
45 :
46 fConnected(false),
47 fHost(host),
48 fSock(NULL)
49 {
50 }
51
52
~LpsClient()53 LpsClient::~LpsClient()
54 {
55 close();
56 }
57
58
59 void
connect()60 LpsClient::connect()
61 {
62 for (int localPort = LPS_CLIENT_PORT_S; localPort <= LPS_CLIENT_PORT_E;
63 localPort++) {
64
65 if (fSock) {
66 delete fSock;
67 }
68 fSock = new Socket(fHost.c_str(), LPS_SERVER_PORT, localPort);
69 if (fSock->good()) {
70 fInput = &fSock->getInputStream();
71 fOutput = &fSock->getOutputStream();
72 fConnected = true;
73 return;
74 }
75 }
76
77 throw(LPSException(fSock->getLastError()));
78 }
79
80
81 void
close()82 LpsClient::close()
83 {
84 fConnected = false;
85 if (fSock) {
86 delete fSock;
87 fSock = NULL;
88 }
89 }
90
91
92 void
receiveJob(const char * printer)93 LpsClient::receiveJob(const char *printer)
94 {
95 if (fConnected) {
96 *fOutput << LPS_PRINT_JOB << printer << '\n' << flush;
97 checkAck();
98 }
99 }
100
101
102 void
receiveControlFile(int size,const char * name)103 LpsClient::receiveControlFile(int size, const char *name)
104 {
105 if (fConnected) {
106
107 char cfname[32];
108 strncpy(cfname, name, sizeof(cfname));
109 cfname[sizeof(cfname) - 1] = '\0';
110
111 *fOutput << LPS_RECEIVE_CONTROL_FILE << size << ' ' << cfname << '\n' << flush;
112
113 checkAck();
114 }
115 }
116
117 void
receiveDataFile(int size,const char * name)118 LpsClient::receiveDataFile(int size, const char *name)
119 {
120 if (fConnected) {
121
122 char dfname[32];
123 strncpy(dfname, name, sizeof(dfname));
124 dfname[sizeof(dfname) - 1] = '\0';
125
126 *fOutput << LPS_RECEIVE_DATA_FILE << size << ' ' << dfname << '\n' << flush;
127
128 checkAck();
129 }
130 }
131
132
133 void
transferData(const char * buffer,int size)134 LpsClient::transferData(const char *buffer, int size)
135 {
136 if (fConnected) {
137
138 if (size < 0) {
139 size = strlen(buffer);
140 }
141
142 if (!fOutput->write(buffer, size)) {
143 close();
144 throw(LPSException("error talking to lpd server"));
145 }
146 }
147 }
148
149
150 void
transferData(istream & is,int size)151 LpsClient::transferData(istream &is, int size)
152 {
153 if (fConnected) {
154
155 if (size < 0) {
156 is.seekg(0, ios::end);
157 size = is.tellg();
158 is.seekg(0, ios::beg);
159 }
160
161 char c;
162 while (is.get(c)) {
163 if (!fOutput->put(c)) {
164 close();
165 throw(LPSException("error reading file."));
166 return;
167 }
168 }
169 }
170 }
171
172
173 void
endTransfer()174 LpsClient::endTransfer()
175 {
176 if (fConnected) {
177 *fOutput << LPS_END_TRANSFER << flush;
178 checkAck();
179 }
180 }
181
182
183 void
checkAck()184 LpsClient::checkAck()
185 {
186 if (fConnected) {
187
188 char c;
189
190 if (!fInput->get(c)) {
191 close();
192 throw(LPSException("server not responding."));
193 return;
194 }
195
196 switch (c) {
197 case LPS_OK:
198 break;
199 case LPS_ERROR:
200 close();
201 throw(LPSException("server error."));
202 break;
203 case LPS_NO_SPOOL_SPACE:
204 close();
205 throw(LPSException("not enough spool space on server."));
206 break;
207 }
208 }
209 }
210