plptools
Loading...
Searching...
No Matches
rpcs.cc
Go to the documentation of this file.
1/*
2 * This file is part of plptools.
3 *
4 * Copyright (C) 1999-2001 Fritz Elfert <felfert@to.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * along with this program; if not, see <https://www.gnu.org/licenses/>.
18 *
19 */
20#include "config.h"
21
22#include "rpcs.h"
23
24#include <stdio.h>
25#include <stdlib.h>
26#include <time.h>
27
28#include "bufferarray.h"
29#include "bufferstore.h"
30#include "Enum.h"
31#include "ncpclient.h"
32#include "psiprocess.h"
33#include "rpcs16.h"
34#include "rpcs32.h"
35#include "tcpsocket.h"
36
37using namespace std;
38
40 stringRep.add(RPCS::PSI_MACH_UNKNOWN, N_("Unknown device"));
41 stringRep.add(RPCS::PSI_MACH_PC, N_("PC"));
42 stringRep.add(RPCS::PSI_MACH_MC, N_("MC"));
43 stringRep.add(RPCS::PSI_MACH_HC, N_("HC"));
44 stringRep.add(RPCS::PSI_MACH_S3, N_("Series 3"));
45 stringRep.add(RPCS::PSI_MACH_S3A, N_("Series 3a, 3c or 3mx"));
46 stringRep.add(RPCS::PSI_MACH_WORKABOUT, N_("Workabout"));
47 stringRep.add(RPCS::PSI_MACH_SIENA, N_("Siena"));
48 stringRep.add(RPCS::PSI_MACH_S3C, N_("Series 3c"));
49 stringRep.add(RPCS::PSI_MACH_S5, N_("Series 5"));
50 stringRep.add(RPCS::PSI_MACH_WINC, N_("WinC"));
52
53ENUM_DEFINITION_BEGIN(RPCS::batterystates, RPCS::PSI_BATT_DEAD)
54 stringRep.add(RPCS::PSI_BATT_DEAD, N_("Empty"));
55 stringRep.add(RPCS::PSI_BATT_VERYLOW, N_("Very Low"));
56 stringRep.add(RPCS::PSI_BATT_LOW, N_("Low"));
57 stringRep.add(RPCS::PSI_BATT_GOOD, N_("Good"));
58ENUM_DEFINITION_END(RPCS::batterystates)
59
60
61ENUM_DEFINITION_BEGIN(RPCS::languages, RPCS::PSI_LANG_TEST)
62 stringRep.add(RPCS::PSI_LANG_TEST, N_("Test"));
63 stringRep.add(RPCS::PSI_LANG_en_GB, N_("English"));
64 stringRep.add(RPCS::PSI_LANG_de_DE, N_("German"));
65 stringRep.add(RPCS::PSI_LANG_fr_FR, N_("French"));
66 stringRep.add(RPCS::PSI_LANG_es_ES, N_("Spanish"));
67 stringRep.add(RPCS::PSI_LANG_it_IT, N_("Italian"));
68 stringRep.add(RPCS::PSI_LANG_sv_SE, N_("Swedish"));
69 stringRep.add(RPCS::PSI_LANG_da_DK, N_("Danish"));
70 stringRep.add(RPCS::PSI_LANG_no_NO, N_("Norwegian"));
71 stringRep.add(RPCS::PSI_LANG_fi_FI, N_("Finnish"));
72 stringRep.add(RPCS::PSI_LANG_en_US, N_("American"));
73 stringRep.add(RPCS::PSI_LANG_fr_CH, N_("Swiss French"));
74 stringRep.add(RPCS::PSI_LANG_de_CH, N_("Swiss German"));
75 stringRep.add(RPCS::PSI_LANG_pt_PT, N_("Portugese"));
76 stringRep.add(RPCS::PSI_LANG_tr_TR, N_("Turkish"));
77 stringRep.add(RPCS::PSI_LANG_is_IS, N_("Icelandic"));
78 stringRep.add(RPCS::PSI_LANG_ru_RU, N_("Russian"));
79 stringRep.add(RPCS::PSI_LANG_hu_HU, N_("Hungarian"));
80 stringRep.add(RPCS::PSI_LANG_nl_NL, N_("Dutch"));
81 stringRep.add(RPCS::PSI_LANG_nl_BE, N_("Belgian Flemish"));
82 stringRep.add(RPCS::PSI_LANG_en_AU, N_("Australian"));
83 stringRep.add(RPCS::PSI_LANG_fr_BE, N_("Belgish French"));
84 stringRep.add(RPCS::PSI_LANG_de_AT, N_("Austrian"));
85 stringRep.add(RPCS::PSI_LANG_en_NZ, N_("New Zealand English"));
86 stringRep.add(RPCS::PSI_LANG_fr_CA, N_("Canadian French"));
87 stringRep.add(RPCS::PSI_LANG_cs_CZ, N_("Czech"));
88 stringRep.add(RPCS::PSI_LANG_sk_SK, N_("Slovak"));
89 stringRep.add(RPCS::PSI_LANG_pl_PL, N_("Polish"));
90 stringRep.add(RPCS::PSI_LANG_sl_SI, N_("Slovenian"));
91ENUM_DEFINITION_END(RPCS::languages)
92
93RPCS *RPCS::connect(const std::string &host, int port, Enum<ConnectionError> *error) {
94 return ncp_client::connect<RPCS, RPCS16, RPCS32>(host, port, false, error);
95}
96
98 socket_->closeSocket();
99}
100
101//
102// public common API
103//
104void RPCS::reconnect(void) {
105 socket_->reconnect();
106 reset();
107}
108
109void RPCS::reset(void) {
111 mtCacheS5mx = 0;
113 a.addStringT(getConnectName());
114 if (socket_->sendBufferStore(a)) {
115 if (socket_->getBufferStore(a) == 1) {
116 if (!strcmp(a.getString(0), "Ok")) {
118 }
119 }
120 }
121}
122
124 return status;
125}
126
127const char *RPCS::getConnectName(void) {
128 return "SYS$RPCS";
129}
130
131//
132// protected internals
133//
136 reconnect();
138 return false;
139 }
140 }
141 bool result;
143 a.addByte(cc);
144 a.addBuff(data);
145 result = socket_->sendBufferStore(a);
146 if (!result) {
147 reconnect();
148 result = socket_->sendBufferStore(a);
149 if (!result) {
151 }
152 }
153 return result;
154}
155
156Enum<RFSV::errs> RPCS::getResponse(BufferStore & data, bool statusIsFirstByte) {
158 if (socket_->getBufferStore(data) == 1) {
159 if (statusIsFirstByte) {
160 ret = (enum RFSV::errs)((char)data.getByte(0));
161 data.discardFirstBytes(1);
162 } else {
163 int l = data.getLen();
164 if (l > 0) {
165 ret = (enum RFSV::errs)((char)data.getByte(data.getLen() - 1));
166 data.init((const unsigned char *)data.getString(), l - 1);
167 } else {
169 }
170 }
171 return ret;
172 } else {
174 }
175 return status;
176}
177
178//
179// APIs, identical on SIBO and EPOC
180//
181Enum<RFSV::errs> RPCS::getNCPversion(int &major, int &minor) {
184
185 if (!sendCommand(QUERY_NCP, a)) {
187 }
188 if ((res = getResponse(a, true)) != RFSV::E_PSI_GEN_NONE) {
189 return res;
190 }
191 if (a.getLen() != 2) {
193 }
194 major = a.getByte(0);
195 minor = a.getByte(1);
196 return res;
197}
198
199Enum<RFSV::errs> RPCS::execProgram(const char *program, const char *args) {
201
202 a.addStringT(program);
203 int l = strlen(program);
204 for (int i = 127; i > l; i--) {
205 a.addByte(0);
206 }
207
214 a.addByte(strlen(args)+1);
215 a.addByte(' ');
216
217 a.addStringT(args);
218
219 if (!sendCommand(EXEC_PROG, a)) {
221 }
222 return getResponse(a, true);
223}
224
227
228 a.addStringT(program);
229 if (!sendCommand(STOP_PROG, a)) {
231 }
232 return getResponse(a, true);
233}
234
237
238 a.addStringT(program);
239 if (!sendCommand(QUERY_PROG, a)) {
241 }
242 return getResponse(a, true);
243}
244
247 const char *drives;
248 const char *dptr;
249 bool anySuccess = false;
251
252 // First, check how many drives we need to query
253 a.addStringT("M:"); // Drive M only exists on a SIBO
256 if (getResponse(a, false) == RFSV::E_PSI_GEN_NONE) {
257 // A SIBO; Must query all possible drives
258 drives = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
259 } else {
260 // A Series 5; Query of C is sufficient
261 drives = "C";
262 }
263
264 dptr = drives;
265 ret.clear();
266
267 if ((mtCacheS5mx & 4) == 0) {
268 Enum<machs> tmp;
271 }
272
273 }
274 if ((mtCacheS5mx & 9) == 1) {
275 machineInfo tmp;
278 }
279 }
280 bool s5mx = (mtCacheS5mx == 15);
281 while (*dptr) {
282 a.init();
283 a.addByte(*dptr);
286 }
287 if (getResponse(a, false) == RFSV::E_PSI_GEN_NONE) {
288 anySuccess = true;
289 int l = a.getLen();
290 while (l > 0) {
291 const char *s;
292 char *p;
293 int pid;
294 int sl;
295
296 s = a.getString(0);
297 sl = strlen(s) + 1;
298 l -= sl;
299 a.discardFirstBytes(sl);
300 if ((p = strstr((char *)s, ".$"))) {
301 *p = '\0'; p += 2;
302 sscanf(p, "%d", &pid);
303 } else {
304 pid = 0;
305 }
306 PsiProcess proc(pid, s, a.getString(0), s5mx);
307 ret.push_back(proc);
308 sl = strlen(a.getString(0)) + 1;
309 l -= sl;
310 a.discardFirstBytes(sl);
311 }
312 }
313 dptr++;
314 }
315 if (anySuccess && !ret.empty()) {
316 for (processList::iterator i = ret.begin(); i != ret.end(); i++) {
317 string cmdline;
318 if (getCmdLine(i->getProcId(), cmdline) == RFSV::E_PSI_GEN_NONE) {
319 i->setArgs(cmdline + " " + i->getArgs());
320 }
321 }
322 }
323 return anySuccess ? RFSV::E_PSI_GEN_NONE : RFSV::E_PSI_GEN_FAIL;
324}
325
326Enum<RFSV::errs> RPCS::formatOpen(const char drive, int &handle, int &count) {
329
330 a.addByte(toupper(drive));
331 a.addByte(':');
332 a.addByte(0);
333 if (!sendCommand(FORMAT_OPEN, a)) {
335 }
336 if ((res = getResponse(a, true)) != RFSV::E_PSI_GEN_NONE) {
337 return res;
338 }
339 if (a.getLen() != 4) {
341 }
342 handle = a.getWord(0);
343 count = a.getWord(2);
344 return res;
345}
346
349
350 a.addWord(handle);
351 if (!sendCommand(FORMAT_READ, a)) {
353 }
354 return getResponse(a, true);
355}
356
360
361 a.addStringT(device);
362 if (!sendCommand(GET_UNIQUEID, a)) {
364 }
365 if ((res = getResponse(a, true)) != RFSV::E_PSI_GEN_NONE) {
366 return res;
367 }
368 if (a.getLen() != 4) {
370 }
371 id = a.getDWord(0);
372 return res;
373}
374
378
381 }
382 if ((res = getResponse(a, true)) != RFSV::E_PSI_GEN_NONE) {
383 return res;
384 }
385 if (a.getLen() != 2) {
387 }
388 type = (enum machs)a.getWord(0);
389 mtCacheS5mx |= 4;
390 if (res == RFSV::E_PSI_GEN_NONE) {
391 if (type == RPCS::PSI_MACH_S5) {
392 mtCacheS5mx |= 1;
393 }
394 }
395 return res;
396}
397
398Enum<RFSV::errs> RPCS::fuser(const char *name, char *buf, int maxlen) {
401 char *p;
402
403 a.addStringT(name);
404 if (!sendCommand(FUSER, a)) {
406 }
407 if ((res = getResponse(a, true)) != RFSV::E_PSI_GEN_NONE) {
408 return res;
409 }
410 strncpy(buf, a.getString(0), maxlen - 1);
411 while ((p = strchr(buf, 6))) {
412 *p = '\0';
413 }
414 return res;
415}
416
419 if (!sendCommand(QUIT_SERVER, a)) {
421 }
422 return getResponse(a, true);
423}
#define ENUM_DEFINITION_END(EnumName)
Definition: Enum.h:303
#define ENUM_DEFINITION_BEGIN(EnumName, initWith)
Helper macro to construct an enumeration wrapper Enum<E> for a specific enum type.
Definition: Enum.h:298
A generic container for an array of bytes.
Definition: bufferstore.h:36
const char * getString(long pos=0) const
Retrieves the characters at index pos.
Definition: bufferstore.cc:118
unsigned long getLen() const
Retrieves the length of a BufferStore.
Definition: bufferstore.cc:92
unsigned char getByte(long pos=0) const
Retrieves the byte at index pos.
Definition: bufferstore.cc:96
void discardFirstBytes(int len=0)
Removes bytes from the start of the buffer.
Definition: bufferstore.cc:141
void init()
Initializes the BufferStore.
Definition: bufferstore.cc:74
Wrapper class featuring range-checking and string representation of enumerated values.
Definition: Enum.h:135
A class, describing a Process on the Psion.
Definition: psiprocess.h:34
errs
The known error codes.
Definition: rfsv.h:113
@ E_PSI_GEN_FAIL
Definition: rfsv.h:115
@ E_PSI_FILE_DISC
Definition: rfsv.h:156
@ E_PSI_GEN_NONE
Definition: rfsv.h:114
Remote procedure call services via PLP.
Definition: rpcs.h:52
Enum< RFSV::errs > queryPrograms(processList &ret)
Retrieves a list of all running Programs.
Definition: rpcs.cc:245
virtual Enum< RFSV::errs > getCmdLine(const char *process, std::string &ret)=0
Retrieves the command line of a running process.
Enum< RFSV::errs > quitServer(void)
Requests the remote server to terminate.
Definition: rpcs.cc:417
Enum< RFSV::errs > getUniqueID(const char *, long &)
Definition: rpcs.cc:357
const char * getConnectName()
Definition: rpcs.cc:127
Enum< RFSV::errs > formatRead(int handle)
Continues a running format.
Definition: rpcs.cc:347
virtual Enum< RFSV::errs > getMachineInfo(machineInfo &machineInfo)
Retrieve general Information about the connected machine.
Definition: rpcs.h:354
void reconnect()
Attempts to re-establish a remote connection by first closing the socket, then connecting again to th...
Definition: rpcs.cc:104
virtual ~RPCS()
Virtual destructor.
Definition: rpcs.cc:97
Enum< RFSV::errs > stopProgram(const char *program)
Requests termination of a program running on the remote machine.
Definition: rpcs.cc:225
Enum< RFSV::errs > getNCPversion(int &major, int &minor)
Retrieves the version of the NCP protocol on the remote side.
Definition: rpcs.cc:181
Enum< RFSV::errs > getMachineType(Enum< machs > &type)
Retrieves the type of machine on the remote side as defined in machs.
Definition: rpcs.cc:375
std::unique_ptr< TCPSocket > socket_
The socket, used for communication with ncpd.
Definition: rpcs.h:447
machs
The known machine types.
Definition: rpcs.h:57
@ PSI_MACH_S5
Definition: rpcs.h:67
@ PSI_MACH_UNKNOWN
Definition: rpcs.h:58
Enum< RFSV::errs > queryProgram(const char *)
Definition: rpcs.cc:235
Enum< RFSV::errs > execProgram(const char *program, const char *args)
Starts execution of a program on the remote machine.
Definition: rpcs.cc:199
Enum< RFSV::errs > getStatus()
Retrieves the current status of the connection.
Definition: rpcs.cc:123
int mtCacheS5mx
Flag: getMachineType and getMachineInfo have been called and the machine is an S5mx.
Definition: rpcs.h:490
Enum< RFSV::errs > fuser(const char *name, char *buf, int maxlen)
Retrieves the name of a process, having a given file opened on the remote side.
Definition: rpcs.cc:398
Enum< RFSV::errs > status
The current status of the connection.
Definition: rpcs.h:452
bool sendCommand(enum commands cc, BufferStore &data)
Sends a command to the remote side.
Definition: rpcs.cc:134
void reset()
Initializes a connection to the remote machine.
Definition: rpcs.cc:109
Enum< RFSV::errs > getResponse(BufferStore &data, bool statusIsFirstByte)
Definition: rpcs.cc:156
commands
The possible commands.
Definition: rpcs.h:457
@ EXEC_PROG
Definition: rpcs.h:459
@ QUIT_SERVER
Definition: rpcs.h:483
@ GET_UNIQUEID
Definition: rpcs.h:465
@ FORMAT_READ
Definition: rpcs.h:464
@ QUERY_DRIVE
Definition: rpcs.h:460
@ QUERY_PROG
Definition: rpcs.h:462
@ GET_MACHINETYPE
Definition: rpcs.h:467
@ FORMAT_OPEN
Definition: rpcs.h:463
@ QUERY_NCP
Definition: rpcs.h:458
@ FUSER
Definition: rpcs.h:469
@ STOP_PROG
Definition: rpcs.h:461
Enum< RFSV::errs > formatOpen(const char drive, int &handle, int &count)
Starts formatting a drive.
Definition: rpcs.cc:326
ConnectionError
Errors that can occur when connecting to a PLP server.
Definition: doctest.h:522
static RFSV * a
Definition: main.cc:55
#define N_(String)
Definition: plpintl.h:35
stringRep add(RPCS::PSI_MACH_UNKNOWN, N_("Unknown device"))
std::vector< PsiProcess > processList
Definition: rpcs.h:35
static void error(int line)
Definition: sismain.cpp:44
This struct holds the data returned by RPCS::getMachineInfo.
Definition: rpcs.h:121
Description of a Psion-Device.
Definition: plpfuse.h:33