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#include "bufferstore.h"
24#include "tcpsocket.h"
25#include "bufferarray.h"
26#include "psiprocess.h"
27#include "Enum.h"
28
29#include <stdio.h>
30#include <stdlib.h>
31#include <time.h>
32
33using namespace std;
34
36 stringRep.add(rpcs::PSI_MACH_UNKNOWN, N_("Unknown device"));
37 stringRep.add(rpcs::PSI_MACH_PC, N_("PC"));
38 stringRep.add(rpcs::PSI_MACH_MC, N_("MC"));
39 stringRep.add(rpcs::PSI_MACH_HC, N_("HC"));
40 stringRep.add(rpcs::PSI_MACH_S3, N_("Series 3"));
41 stringRep.add(rpcs::PSI_MACH_S3A, N_("Series 3a, 3c or 3mx"));
42 stringRep.add(rpcs::PSI_MACH_WORKABOUT, N_("Workabout"));
43 stringRep.add(rpcs::PSI_MACH_SIENA, N_("Siena"));
44 stringRep.add(rpcs::PSI_MACH_S3C, N_("Series 3c"));
45 stringRep.add(rpcs::PSI_MACH_S5, N_("Series 5"));
46 stringRep.add(rpcs::PSI_MACH_WINC, N_("WinC"));
48
49ENUM_DEFINITION_BEGIN(rpcs::batterystates, rpcs::PSI_BATT_DEAD)
50 stringRep.add(rpcs::PSI_BATT_DEAD, N_("Empty"));
51 stringRep.add(rpcs::PSI_BATT_VERYLOW, N_("Very Low"));
52 stringRep.add(rpcs::PSI_BATT_LOW, N_("Low"));
53 stringRep.add(rpcs::PSI_BATT_GOOD, N_("Good"));
54ENUM_DEFINITION_END(rpcs::batterystates)
55
56
57ENUM_DEFINITION_BEGIN(rpcs::languages, rpcs::PSI_LANG_TEST)
58 stringRep.add(rpcs::PSI_LANG_TEST, N_("Test"));
59 stringRep.add(rpcs::PSI_LANG_en_GB, N_("English"));
60 stringRep.add(rpcs::PSI_LANG_de_DE, N_("German"));
61 stringRep.add(rpcs::PSI_LANG_fr_FR, N_("French"));
62 stringRep.add(rpcs::PSI_LANG_es_ES, N_("Spanish"));
63 stringRep.add(rpcs::PSI_LANG_it_IT, N_("Italian"));
64 stringRep.add(rpcs::PSI_LANG_sv_SE, N_("Swedish"));
65 stringRep.add(rpcs::PSI_LANG_da_DK, N_("Danish"));
66 stringRep.add(rpcs::PSI_LANG_no_NO, N_("Norwegian"));
67 stringRep.add(rpcs::PSI_LANG_fi_FI, N_("Finnish"));
68 stringRep.add(rpcs::PSI_LANG_en_US, N_("American"));
69 stringRep.add(rpcs::PSI_LANG_fr_CH, N_("Swiss French"));
70 stringRep.add(rpcs::PSI_LANG_de_CH, N_("Swiss German"));
71 stringRep.add(rpcs::PSI_LANG_pt_PT, N_("Portugese"));
72 stringRep.add(rpcs::PSI_LANG_tr_TR, N_("Turkish"));
73 stringRep.add(rpcs::PSI_LANG_is_IS, N_("Icelandic"));
74 stringRep.add(rpcs::PSI_LANG_ru_RU, N_("Russian"));
75 stringRep.add(rpcs::PSI_LANG_hu_HU, N_("Hungarian"));
76 stringRep.add(rpcs::PSI_LANG_nl_NL, N_("Dutch"));
77 stringRep.add(rpcs::PSI_LANG_nl_BE, N_("Belgian Flemish"));
78 stringRep.add(rpcs::PSI_LANG_en_AU, N_("Australian"));
79 stringRep.add(rpcs::PSI_LANG_fr_BE, N_("Belgish French"));
80 stringRep.add(rpcs::PSI_LANG_de_AT, N_("Austrian"));
81 stringRep.add(rpcs::PSI_LANG_en_NZ, N_("New Zealand English"));
82 stringRep.add(rpcs::PSI_LANG_fr_CA, N_("Canadian French"));
83 stringRep.add(rpcs::PSI_LANG_cs_CZ, N_("Czech"));
84 stringRep.add(rpcs::PSI_LANG_sk_SK, N_("Slovak"));
85 stringRep.add(rpcs::PSI_LANG_pl_PL, N_("Polish"));
86 stringRep.add(rpcs::PSI_LANG_sl_SI, N_("Slovenian"));
87ENUM_DEFINITION_END(rpcs::languages)
88
90{
91 skt->closeSocket();
92}
93
94//
95// public common API
96//
98reconnect(void)
99{
100 skt->reconnect();
101 reset();
102}
103
105reset(void)
106{
108 mtCacheS5mx = 0;
110 a.addStringT(getConnectName());
111 if (skt->sendBufferStore(a)) {
112 if (skt->getBufferStore(a) == 1) {
113 if (!strcmp(a.getString(0), "Ok"))
115 }
116 }
117}
118
120getStatus(void)
121{
122 return status;
123}
124
125const char *rpcs::
126getConnectName(void)
127{
128 return "SYS$RPCS";
129}
130
131//
132// protected internals
133//
135sendCommand(enum commands cc, bufferStore & data)
136{
138 reconnect();
140 return false;
141 }
142 bool result;
144 a.addByte(cc);
145 a.addBuff(data);
146 result = skt->sendBufferStore(a);
147 if (!result) {
148 reconnect();
149 result = skt->sendBufferStore(a);
150 if (!result)
152 }
153 return result;
154}
155
157getResponse(bufferStore & data, bool statusIsFirstByte)
158{
160 if (skt->getBufferStore(data) == 1) {
161 if (statusIsFirstByte) {
162 ret = (enum rfsv::errs)((char)data.getByte(0));
163 data.discardFirstBytes(1);
164 } else {
165 int l = data.getLen();
166 if (l > 0) {
167 ret = (enum rfsv::errs)((char)data.getByte(data.getLen() - 1));
168 data.init((const unsigned char *)data.getString(), l - 1);
169 } else
171 }
172 return ret;
173 } else
175 return status;
176}
177
178//
179// APIs, identical on SIBO and EPOC
180//
182getNCPversion(int &major, int &minor)
183{
186
187 if (!sendCommand(QUERY_NCP, a))
189 if ((res = getResponse(a, true)) != rfsv::E_PSI_GEN_NONE)
190 return res;
191 if (a.getLen() != 2)
193 major = a.getByte(0);
194 minor = a.getByte(1);
195 return res;
196}
197
199execProgram(const char *program, const char *args)
200{
202
203 a.addStringT(program);
204 int l = strlen(program);
205 for (int i = 127; i > l; i--)
206 a.addByte(0);
207
214 a.addByte(strlen(args)+1);
215 a.addByte(' ');
216
217 a.addStringT(args);
218
219 if (!sendCommand(EXEC_PROG, a))
221 return getResponse(a, true);
222}
223
225stopProgram(const char *program)
226{
228
229 a.addStringT(program);
230 if (!sendCommand(STOP_PROG, a))
232 return getResponse(a, true);
233}
234
236queryProgram(const char *program)
237{
239
240 a.addStringT(program);
241 if (!sendCommand(QUERY_PROG, a))
243 return getResponse(a, true);
244}
245
248{
250 const char *drives;
251 const char *dptr;
252 bool anySuccess = false;
254
255 // First, check how many drives we need to query
256 a.addStringT("M:"); // Drive M only exists on a SIBO
259 if (getResponse(a, false) == rfsv::E_PSI_GEN_NONE)
260 // A SIBO; Must query all possible drives
261 drives = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
262 else
263 // A Series 5; Query of C is sufficient
264 drives = "C";
265
266 dptr = drives;
267 ret.clear();
268
269 if ((mtCacheS5mx & 4) == 0) {
270 Enum<machs> tmp;
273
274 }
275 if ((mtCacheS5mx & 9) == 1) {
276 machineInfo tmp;
279 }
280 bool s5mx = (mtCacheS5mx == 15);
281 while (*dptr) {
282 a.init();
283 a.addByte(*dptr);
286 if (getResponse(a, false) == rfsv::E_PSI_GEN_NONE) {
287 anySuccess = true;
288 int l = a.getLen();
289 while (l > 0) {
290 const char *s;
291 char *p;
292 int pid;
293 int sl;
294
295 s = a.getString(0);
296 sl = strlen(s) + 1;
297 l -= sl;
298 a.discardFirstBytes(sl);
299 if ((p = strstr((char *)s, ".$"))) {
300 *p = '\0'; p += 2;
301 sscanf(p, "%d", &pid);
302 } else
303 pid = 0;
304 PsiProcess proc(pid, s, a.getString(0), s5mx);
305 ret.push_back(proc);
306 sl = strlen(a.getString(0)) + 1;
307 l -= sl;
308 a.discardFirstBytes(sl);
309 }
310 }
311 dptr++;
312 }
313 if (anySuccess && !ret.empty())
314 for (processList::iterator i = ret.begin(); i != ret.end(); i++) {
315 string cmdline;
316 if (getCmdLine(i->getProcId(), cmdline) == rfsv::E_PSI_GEN_NONE)
317 i->setArgs(cmdline + " " + i->getArgs());
318 }
319 return anySuccess ? rfsv::E_PSI_GEN_NONE : rfsv::E_PSI_GEN_FAIL;
320}
321
323formatOpen(const char drive, int &handle, int &count)
324{
327
328 a.addByte(toupper(drive));
329 a.addByte(':');
330 a.addByte(0);
333 if ((res = getResponse(a, true)) != rfsv::E_PSI_GEN_NONE)
334 return res;
335 if (a.getLen() != 4)
337 handle = a.getWord(0);
338 count = a.getWord(2);
339 return res;
340}
341
343formatRead(int handle)
344{
346
347 a.addWord(handle);
350 return getResponse(a, true);
351}
352
354getUniqueID(const char *device, long &id)
355{
358
359 a.addStringT(device);
362 if ((res = getResponse(a, true)) != rfsv::E_PSI_GEN_NONE)
363 return res;
364 if (a.getLen() != 4)
366 id = a.getDWord(0);
367 return res;
368}
369
372{
375
378 if ((res = getResponse(a, true)) != rfsv::E_PSI_GEN_NONE)
379 return res;
380 if (a.getLen() != 2)
382 type = (enum machs)a.getWord(0);
383 mtCacheS5mx |= 4;
384 if (res == rfsv::E_PSI_GEN_NONE) {
385 if (type == rpcs::PSI_MACH_S5)
386 mtCacheS5mx |= 1;
387 }
388 return res;
389}
390
392fuser(const char *name, char *buf, int maxlen)
393{
396 char *p;
397
398 a.addStringT(name);
399 if (!sendCommand(FUSER, a))
401 if ((res = getResponse(a, true)) != rfsv::E_PSI_GEN_NONE)
402 return res;
403 strncpy(buf, a.getString(0), maxlen - 1);
404 while ((p = strchr(buf, 6)))
405 *p = '\0';
406 return res;
407}
408
410quitServer(void)
411{
415 return getResponse(a, true);
416}
#define ENUM_DEFINITION_END(EnumName)
Definition: Enum.h:304
#define ENUM_DEFINITION_BEGIN(EnumName, initWith)
Helper macro to construct an enumeration wrapper Enum<E> for a specific enum type.
Definition: Enum.h:299
Wrapper class featuring range-checking and string representation of enumerated values.
Definition: Enum.h:136
A class, describing a Process on the Psion.
Definition: psiprocess.h:35
virtual bool reconnect()
Reopens the connection after closing it.
Definition: tcpsocket.cc:100
int getBufferStore(bufferStore &a, bool wait=true)
Receive data into a bufferStore .
Definition: tcpsocket.cc:289
bool sendBufferStore(const bufferStore &a)
Sends data from a bufferStore .
Definition: tcpsocket.cc:325
A generic container for an array of bytes.
Definition: bufferstore.h:37
void discardFirstBytes(int len=0)
Removes bytes from the start of the buffer.
Definition: bufferstore.cc:143
void init()
Initializes the bufferStore.
Definition: bufferstore.cc:77
const char * getString(long pos=0) const
Retrieves the characters at index pos.
Definition: bufferstore.cc:120
unsigned long getLen() const
Retrieves the length of a bufferStore.
Definition: bufferstore.cc:94
unsigned char getByte(long pos=0) const
Retrieves the byte at index pos.
Definition: bufferstore.cc:98
errs
The known error codes.
Definition: rfsv.h:109
@ E_PSI_GEN_NONE
Definition: rfsv.h:110
@ E_PSI_GEN_FAIL
Definition: rfsv.h:111
@ E_PSI_FILE_DISC
Definition: rfsv.h:152
Remote procedure call services via PLP.
Definition: rpcs.h:51
Enum< rfsv::errs > getNCPversion(int &major, int &minor)
Retrieves the version of the NCP protocol on the remote side.
Definition: rpcs.cc:182
machs
The known machine types.
Definition: rpcs.h:56
@ PSI_MACH_UNKNOWN
Definition: rpcs.h:57
@ PSI_MACH_S5
Definition: rpcs.h:66
virtual Enum< rfsv::errs > getMachineInfo(machineInfo &machineInfo)
Retrieve general Information about the connected machine.
Definition: rpcs.h:351
Enum< rfsv::errs > formatRead(int handle)
Continues a running format.
Definition: rpcs.cc:343
Enum< rfsv::errs > status
The current status of the connection.
Definition: rpcs.h:425
Enum< rfsv::errs > stopProgram(const char *program)
Requests termination of a program running on the remote machine.
Definition: rpcs.cc:225
virtual Enum< rfsv::errs > getCmdLine(const char *process, std::string &ret)=0
Retrieves the command line of a running process.
TCPSocket * skt
The socket, used for communication with ncpd.
Definition: rpcs.h:420
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:392
bool sendCommand(enum commands cc, bufferStore &data)
Sends a command to the remote side.
Definition: rpcs.cc:135
Enum< rfsv::errs > queryProgram(const char *)
Definition: rpcs.cc:236
const char * getConnectName()
Definition: rpcs.cc:126
Enum< rfsv::errs > queryPrograms(processList &ret)
Retrieves a list of all running Programs.
Definition: rpcs.cc:247
commands
The possible commands.
Definition: rpcs.h:430
@ QUIT_SERVER
Definition: rpcs.h:456
@ QUERY_NCP
Definition: rpcs.h:431
@ QUERY_PROG
Definition: rpcs.h:435
@ EXEC_PROG
Definition: rpcs.h:432
@ QUERY_DRIVE
Definition: rpcs.h:433
@ FORMAT_OPEN
Definition: rpcs.h:436
@ GET_UNIQUEID
Definition: rpcs.h:438
@ FUSER
Definition: rpcs.h:442
@ GET_MACHINETYPE
Definition: rpcs.h:440
@ STOP_PROG
Definition: rpcs.h:434
@ FORMAT_READ
Definition: rpcs.h:437
Enum< rfsv::errs > getMachineType(Enum< machs > &type)
Retrieves the type of machine on the remote side as defined in machs.
Definition: rpcs.cc:371
Enum< rfsv::errs > getStatus()
Retrieves the current status of the connection.
Definition: rpcs.cc:120
Enum< rfsv::errs > formatOpen(const char drive, int &handle, int &count)
Starts formatting a drive.
Definition: rpcs.cc:323
Enum< rfsv::errs > getUniqueID(const char *, long &)
Definition: rpcs.cc:354
Enum< rfsv::errs > getResponse(bufferStore &data, bool statusIsFirstByte)
Definition: rpcs.cc:157
void reset()
Initializes a connection to the remote machine.
Definition: rpcs.cc:105
Enum< rfsv::errs > execProgram(const char *program, const char *args)
Starts execution of a program on the remote machine.
Definition: rpcs.cc:199
int mtCacheS5mx
Flag: getMachineType and getMachineInfo have been called and the machine is an S5mx.
Definition: rpcs.h:463
void reconnect()
Attempts to re-establish a remote connection by first closing the socket, then connecting again to th...
Definition: rpcs.cc:98
Enum< rfsv::errs > quitServer(void)
Requests the remote server to terminate.
Definition: rpcs.cc:410
Definition: doctest.h:522
static rfsv * a
Definition: main.cc:53
#define N_(String)
Definition: plpintl.h:36
stringRep add(rpcs::PSI_MACH_UNKNOWN, N_("Unknown device"))
std::vector< PsiProcess > processList
Definition: rpcs.h:34
Description of a Psion-Device.
Definition: plpfuse.h:34
This struct holds the data returned by rpcs::getMachineInfo.
Definition: rpcs.h:120