aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFritz Elfert <felfert@to.com>2000-01-17 11:49:41 +0000
committerFritz Elfert <felfert@to.com>2000-01-17 11:49:41 +0000
commitab18114bfd38d4632c66401b5bc079241e27fab3 (patch)
tree14f9c1d5f020cf8ed2f205094ca9e2fc907bb969
parent6eceb82662300bf306e70bd943200665bc3c9bc3 (diff)
downloadplptools-ab18114bfd38d4632c66401b5bc079241e27fab3.tar.gz
plptools-ab18114bfd38d4632c66401b5bc079241e27fab3.tar.bz2
plptools-ab18114bfd38d4632c66401b5bc079241e27fab3.zip
Release of plptools-0.5
-rw-r--r--.cvsignore1
-rw-r--r--CHANGES13
-rw-r--r--INSTALL2
-rw-r--r--Makefile.am2
-rw-r--r--Makefile.cvs4
-rw-r--r--README25
-rw-r--r--README.mjg120
-rw-r--r--configure.in24
-rw-r--r--include/.cvsignore1
-rw-r--r--include/config.h.in11
-rw-r--r--include/defs.h.in2
-rw-r--r--include/mp.h2
-rw-r--r--lib/Makefile.am8
-rw-r--r--lib/bufferarray.cc97
-rw-r--r--lib/bufferarray.h21
-rw-r--r--lib/bufferstore.cc13
-rw-r--r--lib/bufferstore.h25
-rw-r--r--lib/ppsocket.cc21
-rw-r--r--lib/rfsv.cc158
-rw-r--r--lib/rfsv.h151
-rw-r--r--lib/rfsv16.cc836
-rw-r--r--lib/rfsv16.h127
-rw-r--r--lib/rfsv32.cc368
-rw-r--r--lib/rfsv32.h199
-rw-r--r--lib/rfsvfactory.cc86
-rw-r--r--lib/rfsvfactory.h20
-rw-r--r--lib/rpcs.cc283
-rw-r--r--lib/rpcs.h103
-rw-r--r--lib/rpcs16.cc63
-rw-r--r--lib/rpcs16.h18
-rw-r--r--lib/rpcs32.cc114
-rw-r--r--lib/rpcs32.h36
-rw-r--r--lib/rpcsfactory.cc85
-rw-r--r--lib/rpcsfactory.h20
-rw-r--r--ncpd/channel.cc25
-rw-r--r--ncpd/channel.h11
-rw-r--r--ncpd/linkchan.cc61
-rw-r--r--ncpd/linkchan.h9
-rw-r--r--ncpd/main.cc12
-rw-r--r--ncpd/ncp.cc101
-rw-r--r--ncpd/ncp.h15
-rw-r--r--ncpd/packet.cc11
-rw-r--r--ncpd/packet.h3
-rw-r--r--ncpd/socketchan.cc107
-rw-r--r--ncpd/socketchan.h8
-rw-r--r--plpftp/ftp.cc568
-rw-r--r--plpftp/ftp.h22
-rw-r--r--plpftp/main.cc36
-rw-r--r--plpnfsd/main.cc163
-rw-r--r--plpnfsd/mp_main.c5
-rw-r--r--plpnfsd/mp_mount.c1
-rw-r--r--plpnfsd/mp_pfs_ops.c45
-rw-r--r--plpnfsd/rfsv_api.h5
53 files changed, 3722 insertions, 545 deletions
diff --git a/.cvsignore b/.cvsignore
index 364e9f2..e36cc10 100644
--- a/.cvsignore
+++ b/.cvsignore
@@ -3,7 +3,6 @@ Makefile
aclocal.m4
configure
libtool
-stamp-h.in
config.status
config.cache
config.log
diff --git a/CHANGES b/CHANGES
new file mode 100644
index 0000000..d1b0459
--- /dev/null
+++ b/CHANGES
@@ -0,0 +1,13 @@
+Changes from Version 0.4 to 0.5:
+
+ - merged all stuff from Matt Gumbley's plptools-0.4-mjg5
+ see his README.mjg
+ - Added a speedup-patch for plpnfsd from Rudol Koenig. This
+ should also solve Olaf Flebbe's problems as a side effect.
+ - Added command- and filename-completion to plpftp
+ - Changed plpftp's default-drive to "AUTO". This triggers
+ auto-detection of available drives and selecting the first one.
+ - fixed various bugs in plpftp
+ - added hash printing in plpftp.
+ - Added new commands "ps", "kill" and "run" to plpftp (these should
+ work at least for Series5. For Series3: INCOMPLETE)
diff --git a/INSTALL b/INSTALL
index ca5d962..cb328dd 100644
--- a/INSTALL
+++ b/INSTALL
@@ -2,7 +2,7 @@ Basic Installation
==================
These are generic installation instructions.
- For package-specific stuff, look into README.
+ >>>> For package-specific stuff, look into README. <<<<
The `configure' shell script attempts to guess correct values for
various system-dependent variables used during compilation. It uses
diff --git a/Makefile.am b/Makefile.am
index 94ecd0f..fc7f1fc 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,7 +1,7 @@
# $Id$
#
SUBDIRS = lib ncpd plpnfsd plpftp
-EXTRA_DIST = COPYING README TODO INSTALL include/*.h* etc/*magic etc/*.in
+EXTRA_DIST = COPYING README TODO INSTALL README.mjg include/*.h* etc/*magic etc/*.in
DISTCLEANFILES = etc/psion
AUTOMAKE_OPTIONS = foreign
diff --git a/Makefile.cvs b/Makefile.cvs
index b7e3170..72d73e0 100644
--- a/Makefile.cvs
+++ b/Makefile.cvs
@@ -6,14 +6,14 @@ devel:
autoheader
automake
autoconf
- touch stamp-h.in
+ touch include/stamp-h.in
dist:
aclocal
autoheader
automake --include-deps
autoconf
- touch stamp-h.in
+ touch include/stamp-h.in
./configure
$(MAKE) dist
diff --git a/README b/README
index 91a1f59..2fd2b77 100644
--- a/README
+++ b/README
@@ -4,8 +4,7 @@
- p3nfsd-5.4 by Rudolf Koenig (rfkoenig@immd4.informatik.uni-erlangen.de)
an nfs daemon for Psion series 3 and 5
- - plp_1_7 by Philip Proudman
- (former email, current address unknown proudman@btinternet.com)
+ - plp_1_7 by Philip Proudman (phil@proudman51.freeserve.co.uk)
I want to thank both authors for their nice packages and for making
these available under GPL which makes it possible for me to
@@ -25,6 +24,14 @@
because a) i can't test it and b) Sibo support is dropped by
Psion.
+ Since version 0.5, there is also starting support for RPC-service
+ on the Psion. Note the new commands "ps", "kill" and "run" in
+ plpftp. This support was only possible because of Alexander Thoukydides'
+ excellent documentation at
+ http://www.btinternet.com/~thouky/software/psifs/plp.html
+ Thanks a lot for that. Also Psion-3 support is now added by Matt Gumbley
+ (matt@gumbley.demon.co.uk)
+
How to install:
./configure
@@ -54,6 +61,20 @@
overrides the default port number, where ncpd listens
and plpftp resp. plpnfsd connects to.
+ --with-drive=drivespec
+
+ overrides the default drive for plpftp. The default "AUTO"
+ triggers a drive-scan on the psion and sets the drive to
+ the first drive found. If you don't want that, specify
+ C: for example.
+
+ --with-basedir=dirspec
+
+ overrides the default directory for plpftp. The default is \\
+ which means the root-dir. Note: directory-separators have to
+ be specified as C-like backslashes and if you consider shell's
+ escape-mechanism, these in turn have to be escaped with backslashes ;-)
+
You will get 3 programs and a shared and static library.
By default, the install-prefix is /usr/local, so you probably
should add /usr/local/lib to your /etc/ld.so.conf and then run
diff --git a/README.mjg b/README.mjg
new file mode 100644
index 0000000..a557988
--- /dev/null
+++ b/README.mjg
@@ -0,0 +1,120 @@
+Retrofitting RFSV 16 to Fritz Elfert's plptools
+===============================================
+
+These notes updated 21/10/99
+
+
+I started modifying Fritz' plptools-0.3 with the intention of adding back the
+RFSV16 support. Fritz then released 0.4, and so I re-patched 0.4, and did lots
+more work, and merged in some patches from Pete Bentley.
+
+The result is this, plptools-0.4-mjg<x>.
+
+When it's finished, hopefully Fritz will merge it into the next official
+release.
+
+Release Dates:
+plptools-0.4-mjg1 on 23/09/99
+plptools-0.4-mjg2 on 04/10/99
+plptools-0.4-mjg3 on 07/10/99
+plptools-0.4-mjg4 on 10/10/99
+plptools-0.4-mjg5 on 21/10/99 (+ patch against 0.4 original)
+
+The changes to plptools-0.4 are:
+* Now detects which version of the NCP protocol is in use, and records this:
+ this is how we detect whether the Psion is a Series 3 or Series 5.
+* Makefiles updated to include the rfsv16 stuff, the rfsv base class, and the
+ rfsvfactory object.
+* Instantiates either an RFSV32 or RFSV16 object to handle the file server
+ requests, based on the protocol version returned by the INFO command above.
+ There is an rfsvfactory object to make this easier in client programs.
+ This is used in plpftp and plpnfsd. This will obtain the NCP version number
+ over the socket, by announcing itself as "NCP$INFO.*". The correct RFSV class
+ will further announce itself as SYS$RFSV.* - this is stored in connectName.
+ RFSV objects have an opAttr method to output a correct attributes flag for each
+ protocol.
+* Added --with-drive and --with-basedir to the configure.in script, and
+ include/defs.h.in. These are used in RFSV16, and plpftp now uses these,
+ instead of the DEFAULT_DRIVE AND DEFAULT_BASE_DIRECTORY of ftp.h
+* ncpd/packet.h: verbose is now a short int, to allow packet debugging.
+* Pete Bentley's changes. Fixes bogus definition of usleep(); plpftp compiles in
+ the absence of libreadline and libhistory; accept 3rd parameter in ppsocket is
+ signed not unsigned; -v all debugging option; (sun) link detection changes;
+ new PKT_DEBUG_HANDSHAKE debug level added; correct termios.h include for
+ Solaris; Solaris non-blocking fixes; move the fcntl for O_NONBLOCK; remove
+ O_NONBLOCK where needed; set SO_REUSEADDR for ncpd.
+* Peter Cherriman's "1 hour out" fix (doesn't work for me though... could be my
+ PC clock)
+
+Some things to do:
+* Finish rfsv16.cc:
+ fread, fwrite, fseek, copyFromPsion, copyToPsion, fsetsize, mktemp,
+ fcreatefile, freplacefile, fopendir, fsetmtime
+
+* Test everything with plpftp and plpnfsd.
+* Remove read, write fully?
+* Remove unused convertName method in plpftp/ftp.cc,h
+
+Adding RFSV16 back is still a work in progress.... stay tuned!
+
+
+Building plptools for use with a Psion 3
+========================================
+./configure --with-speed=19200 --with-serial=/dev/ttyS1 --with-drive=M:
+# Or whatever port you use. I use ttyS1, since ttyS0 is my mouse.
+# The default speed is 115200 bps, which is only for the Lucky S5 owners.
+# The S3c can take speeds up to 57600, but my RS232 protocol analyser can't -
+# your mileage may vary.
+make
+make install
+plpftp
+# NFS access not finished yet
+
+
+Tip for use with a Psion 3
+==========================
+Turn the Psion's remote link on first, THEN run ncpd.
+
+Why this seems to help matters
+------------------------------
+This seems to ensure that the Psion will send a request for the LINK.* process,
+which is what we must detect to allow other connections to the NCP daemon. It
+seems there may be a strange bug when you start ncpd, THEN start the Psion link
+- the link request/acknowledge messages are exchanged correctly, followed by
+valid INFO/NCP Protocol Version messages - and then the Psion attempts to
+connect to the PC's SYS$RFSV.* - IMHO, it should start by attempting to connect
+to LINK.*
+
+Philip Proudman's plp_1.7 always receives the LINK.* connect request, as do
+other protocol implementations.
+
+I haven't managed to work out why the Psion starts by sending a SYS$RFSV.*
+connect request with plptools, and not with other implementations, but the above
+work-around gets round it.
+
+
+Troubleshooting
+===============
+Q. I can't build it on SuSE Linux.
+A. You need the gppshare and libgpp packages. (Thanks to der.hans)
+
+
+Acknowledgements
+================
+This couldn't have been written without pioneering investigations into the link
+protocol by Olaf Flebbe, Michael Pieper, and others. Philip Proudman beat me to
+producing a decent, working PLP stack (Thanks, Philip ;-) and Fritz Elfert did
+some excellent merging of Rudolf Koenig's p3nfs. Also thanks to the Majordomo
+maintainers @geekstuff.co.uk, who host the linux-psion list.
+
+Finally, the RFSV16 re-merge would still be in my In-tray if my wife Angela
+hadn't been away for the week, leaving me to code, and fend for myself.
+
+Thanks to Pete Bentley for ideas on proxying, his patches, suggestions for
+improvement, and a loan Series 5 for testing against.
+
+
+Viola!
+--
+Matt Gumbley
+matt@gumbley.demon.co.uk
diff --git a/configure.in b/configure.in
index a5fd29b..03e631b 100644
--- a/configure.in
+++ b/configure.in
@@ -2,10 +2,12 @@ AC_REVISION($ Revision: 0.1 $)dnl revision of this configure.in script
AC_INIT(acinclude.m4)
AM_CONFIG_HEADER(include/config.h)
-AM_INIT_AUTOMAKE(plptools, 0.4)
+AM_INIT_AUTOMAKE(plptools, 0.5)
AM_PROG_LIBTOOL
dnl Enable Mainatiner stuff
+dnl **** NOTE **** Matt had to comment the following line out to get it to
+dnl ************** build, and doesn't know why - YMMV.
AM_MAINTAINER_MODE
dnl checks for programs
@@ -86,6 +88,26 @@ AC_ARG_WITH(port,
)
AC_SUBST(DPORT)
+AC_ARG_WITH(drive,
+ [ --with-drive=DRIVE override default Psion drive [AUTO]],
+ [ DDRIVE="$withval"
+ AC_MSG_RESULT(Overriding drive: $DDRIVE) ],
+ [ DDRIVE='AUTO'
+ AC_MSG_RESULT(Using default Psion drive: $DDRIVE)
+ ]
+)
+AC_SUBST(DDRIVE)
+
+AC_ARG_WITH(basedir,
+ [ --with-basedir=DIR override default Psion directory [\\\\]],
+ [ DBASEDIR="$withval"
+ AC_MSG_RESULT(Overriding directory: $DBASEDIR) ],
+ [ DBASEDIR="\\\\"
+ AC_MSG_RESULT(Using default Psion directory: $DBASEDIR)
+ ]
+)
+AC_SUBST(DBASEDIR)
+
AC_OUTPUT(
Makefile
lib/Makefile
diff --git a/include/.cvsignore b/include/.cvsignore
index 123a642..bd3c1d5 100644
--- a/include/.cvsignore
+++ b/include/.cvsignore
@@ -1,3 +1,4 @@
+stamp-h.in
stamp-h
config.h
defs.h
diff --git a/include/config.h.in b/include/config.h.in
index 4932d0a..a9d3daa 100644
--- a/include/config.h.in
+++ b/include/config.h.in
@@ -1,9 +1,5 @@
/* include/config.h.in. Generated automatically from configure.in by autoheader. */
-#undef VERSION
-
-#undef PACKAGE
-
/* Define if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
@@ -33,3 +29,10 @@
/* Define if you have the socket library (-lsocket). */
#undef HAVE_LIBSOCKET
+
+/* Name of package */
+#undef PACKAGE
+
+/* Version number of package */
+#undef VERSION
+
diff --git a/include/defs.h.in b/include/defs.h.in
index 3c6fbce..ce5f68d 100644
--- a/include/defs.h.in
+++ b/include/defs.h.in
@@ -36,6 +36,8 @@
#define DDEV "@DDEV@"
#define DSPEED @DSPEED@
#define DPORT @DPORT@
+#define DDRIVE "@DDRIVE@"
+#define DBASEDIR "@DBASEDIR@"
/* Debugging */
diff --git a/include/mp.h b/include/mp.h
index ae2fe19..125ad80 100644
--- a/include/mp.h
+++ b/include/mp.h
@@ -122,7 +122,7 @@ extern char *index(), *rindex(), *strdup();
#endif
/* mp_main.c */
-#if defined(hpux) || defined(__SVR4)
+#if defined(hpux) || defined(__SVR4) && !defined(sun)
/* HPUX 10.20 declares int usleep( useconds_t useconds); */
# ifndef HPUX10
extern void usleep __P((int usec));
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 27d5ea4..08df502 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -1,5 +1,9 @@
lib_LTLIBRARIES = libplp.la
libplp_la_LDFLAGS = --debug -version-info 1:0:0
-libplp_la_SOURCES = bufferarray.cc bufferstore.cc iowatch.cc ppsocket.cc rfsv32.cc log.cc
-EXTRA_DIST = bool.h bufferarray.h bufferstore.h iowatch.h ppsocket.h rfsv32.h log.h
+libplp_la_SOURCES = bufferarray.cc bufferstore.cc iowatch.cc ppsocket.cc \
+ rfsv16.cc rfsv32.cc rfsvfactory.cc log.cc rfsv.cc rpcs32.cc rpcs16.cc \
+ rpcs.cc rpcsfactory.cc
+EXTRA_DIST = bool.h bufferarray.h bufferstore.h iowatch.h ppsocket.h \
+ rfsv.h rfsv16.h rfsv32.h rfsvfactory.h log.h rpcs32.h rpcs16.h rpcs.h \
+ rpcsfactory.h
diff --git a/lib/bufferarray.cc b/lib/bufferarray.cc
index 99b1811..4e922ed 100644
--- a/lib/bufferarray.cc
+++ b/lib/bufferarray.cc
@@ -2,6 +2,7 @@
// PLP - An implementation of the PSION link protocol
//
// Copyright (C) 1999 Philip Proudman
+// extensions Copyright (C) 2000 Fritz Elfert <felfert@to.com>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -20,7 +21,8 @@
// e-mail philip.proudman@btinternet.com
-#include <stdio.h>
+#include <stream.h>
+#include <iomanip.h>
#include "bufferstore.h"
#include "bufferarray.h"
@@ -28,7 +30,7 @@
bufferArray::bufferArray()
{
len = 0;
- lenAllocd = 5;
+ lenAllocd = ALLOC_MIN;
buff = new bufferStore[lenAllocd];
}
@@ -64,7 +66,7 @@ void bufferArray::
pushBuffer(const bufferStore & b)
{
if (len == lenAllocd) {
- lenAllocd += 5;
+ lenAllocd += ALLOC_MIN;
bufferStore *nb = new bufferStore[lenAllocd];
for (long i = 0; i < len; i++) {
nb[i] = buff[i];
@@ -74,3 +76,92 @@ pushBuffer(const bufferStore & b)
}
buff[len++] = b;
}
+
+void bufferArray::
+push(const bufferStore & b)
+{
+ if (len == lenAllocd)
+ lenAllocd += ALLOC_MIN;
+ bufferStore *nb = new bufferStore[lenAllocd];
+ for (long i = len; i > 0; i--) {
+ nb[i] = buff[i-1];
+ }
+ nb[0] = b;
+ delete[]buff;
+ buff = nb;
+ len++;
+}
+
+bufferStore bufferArray::
+pop()
+{
+ return popBuffer();
+}
+
+void bufferArray::
+append(const bufferStore & b)
+{
+ pushBuffer(b);
+}
+
+long bufferArray::
+length(void)
+{
+ return len;
+}
+
+void bufferArray::
+clear(void)
+{
+ len = 0;
+ lenAllocd = ALLOC_MIN;
+ delete []buff;
+ buff = new bufferStore[lenAllocd];
+}
+
+bufferArray &bufferArray::
+operator =(const bufferArray & a)
+{
+ delete []buff;
+ len = a.len;
+ lenAllocd = a.lenAllocd;
+ buff = new bufferStore[lenAllocd];
+ for (int i = 0; i < len; i++)
+ buff[i] = a.buff[i];
+ return *this;
+}
+
+bufferStore &bufferArray::
+operator [](const unsigned long index)
+{
+ return buff[index];
+}
+
+bufferArray &bufferArray::
+operator +(const bufferStore &a)
+{
+ append(a);
+ return *this;
+}
+
+bufferArray &bufferArray::
+operator +(const bufferArray &a)
+{
+ lenAllocd += a.lenAllocd;
+ bufferStore *nb = new bufferStore[lenAllocd];
+ for (int i = 0; i < len; i++)
+ nb[len + i] = buff[i];
+ for (int i = 0; i < a.len; i++)
+ nb[len + i] = a.buff[i];
+ len += a.len;
+ delete []buff;
+ buff = nb;
+ return *this;
+}
+
+bufferArray &bufferArray::
+operator +=(const bufferStore &a)
+{
+ append(a);
+ return *this;
+}
diff --git a/lib/bufferarray.h b/lib/bufferarray.h
index 4cb948e..fbf26f1 100644
--- a/lib/bufferarray.h
+++ b/lib/bufferarray.h
@@ -9,12 +9,27 @@ class bufferArray {
bufferArray();
bufferArray(const bufferArray &a);
~bufferArray();
- void operator =(const bufferArray &a);
-
+ bufferArray &operator =(const bufferArray &a);
bool empty() const;
- bufferStore popBuffer();
+
+ // this is NOT a real push as with a FIFO but
+ // appends the bufferStore.
void pushBuffer(const bufferStore& b);
+ bufferStore popBuffer(void);
+
+ // new API (push() now behaves like a FIFO, more operators
+ bufferStore &operator [](const unsigned long index);
+ bufferArray &operator +(const bufferStore &); // append
+ bufferArray &operator +(const bufferArray &); // append
+ bufferArray &operator +=(const bufferStore &b); // append
+ bufferStore pop(void);
+ void push(const bufferStore& b);
+ void append(const bufferStore& b);
+ long length(void);
+ void clear(void);
+
private:
+ static const long ALLOC_MIN = 5;
long len;
long lenAllocd;
bufferStore* buff;
diff --git a/lib/bufferstore.cc b/lib/bufferstore.cc
index 886b952..842e666 100644
--- a/lib/bufferstore.cc
+++ b/lib/bufferstore.cc
@@ -19,7 +19,8 @@
//
// e-mail philip.proudman@btinternet.com
-#include <stream.h>
+#include <stream.h>
+// That should be iostream.h, but it won't build on Sun WorkShop C++ 5.0
#include <iomanip.h>
#include <string.h>
@@ -48,7 +49,7 @@ bufferStore::bufferStore(const unsigned char*_buff, long _len) {
start = 0;
}
-void bufferStore::operator =(const bufferStore &a) {
+bufferStore &bufferStore::operator =(const bufferStore &a) {
checkAllocd(a.getLen());
len = a.getLen();
memcpy(buff, a.getString(0), len);
@@ -106,7 +107,7 @@ ostream &operator<<(ostream &s, const bufferStore &m) {
if (c>=' ' && c <= 'z') s << c;
}
}
- s<< ")";
+ s<< ")" << dec << setw(0);
return s;
}
@@ -144,6 +145,12 @@ void bufferStore::addStringT(const char* s) {
addByte(0);
}
+void bufferStore::addBytes(const unsigned char* s, int l) {
+ checkAllocd(len + l);
+ memcpy(&buff[len], s, l);
+ len += l;
+}
+
void bufferStore::addBuff(const bufferStore &s, long maxLen) {
long l = s.getLen();
checkAllocd(len + l);
diff --git a/lib/bufferstore.h b/lib/bufferstore.h
index 4840689..df216c0 100644
--- a/lib/bufferstore.h
+++ b/lib/bufferstore.h
@@ -7,10 +7,10 @@ class ostream;
class bufferStore {
public:
bufferStore();
- bufferStore(const unsigned char*buff, long len);
+ bufferStore(const unsigned char *, long);
~bufferStore();
- bufferStore(const bufferStore &a);
- void operator =(const bufferStore &a);
+ bufferStore(const bufferStore &);
+ bufferStore &operator =(const bufferStore &);
// Reading Utils
unsigned long getLen() const;
@@ -18,19 +18,20 @@ public:
unsigned int getWord(long pos) const;
unsigned int getDWord(long pos) const;
const char* getString(long pos=0) const;
- void discardFirstBytes(int n);
- friend ostream &operator<<(ostream &s, const bufferStore &m);
+ void discardFirstBytes(int);
+ friend ostream &operator<<(ostream &, const bufferStore &);
bool empty() const;
// Writing utils
void init();
- void init(const unsigned char*buff, long len);
- void addByte(unsigned char c);
- void addWord(int a);
- void addDWord(long a);
- void addString(const char* s);
- void addStringT(const char* s);
- void addBuff(const bufferStore &s, long maxLen=-1);
+ void init(const unsigned char*, long);
+ void addByte(unsigned char);
+ void addWord(int);
+ void addDWord(long);
+ void addString(const char*);
+ void addStringT(const char*);
+ void addBytes(const unsigned char*, int);
+ void addBuff(const bufferStore &, long maxLen=-1);
private:
void checkAllocd(long newLen);
diff --git a/lib/ppsocket.cc b/lib/ppsocket.cc
index c51c557..cb04919 100644
--- a/lib/ppsocket.cc
+++ b/lib/ppsocket.cc
@@ -30,6 +30,7 @@
#include <sys/time.h>
#include <sys/types.h>
#include <netinet/in.h>
+#include <arpa/inet.h>
#include "defs.h"
#include "bool.h"
@@ -126,7 +127,6 @@ printPeer()
bool ppsocket::
connect(char *Peer, int PeerPort, char *Host, int HostPort)
{
-
//****************************************************
//* If we aren't already bound set the host and bind *
//****************************************************
@@ -172,13 +172,16 @@ listen(char *Host, int Port)
m_LastError = lastErrorCode();
return (false);
}
+ // Our accept member function relies on non-blocking accepts,
+ // so set the flag here (rather than every time around the loop)
+ fcntl(m_Socket, F_SETFL, O_NONBLOCK);
return (true);
}
ppsocket *ppsocket::
accept(char *Peer, int MaxLen)
{
- unsigned int len;
+ socklen_t len;
ppsocket *accepted;
char *peer;
@@ -197,7 +200,6 @@ accept(char *Peer, int MaxLen)
//***********************
len = sizeof(struct sockaddr);
- fcntl(m_Socket, F_SETFL, O_NONBLOCK);
accepted->m_Socket =::accept(m_Socket, &accepted->m_PeerAddr, &len);
if (accepted->m_Socket == INVALID_SOCKET) {
@@ -209,6 +211,14 @@ accept(char *Peer, int MaxLen)
//* Got a connection so fill in the other attributes *
//****************************************************
+ // Make sure the new socket hasn't inherited O_NONBLOCK
+ // from the accept socket
+ int flags = fcntl( accepted->m_Socket, F_GETFL, 0 );
+ if( flags >= 0 ) {
+ flags &= ~O_NONBLOCK;
+ fcntl( accepted->m_Socket, F_SETFL, flags);
+ }
+
accepted->m_HostAddr = m_HostAddr;
accepted->m_Bound = true;
@@ -503,6 +513,11 @@ bindSocket(char *Host, int Port)
return (false);
}
}
+ // Set SO_REUSEADDR
+ int one = 1;
+ if (setsockopt( m_Socket, SOL_SOCKET, SO_REUSEADDR,
+ (const char *) &one, sizeof(int)) < 0 )
+ cerr << "Warning: Unable to set SO_REUSEADDR option\n";
// If a host name was supplied then use it
if (!setHost(Host, Port)) {
return (false);
diff --git a/lib/rfsv.cc b/lib/rfsv.cc
new file mode 100644
index 0000000..3b9dc6a
--- /dev/null
+++ b/lib/rfsv.cc
@@ -0,0 +1,158 @@
+#include "rfsv.h"
+
+char *rfsv::
+opErr(long status)
+{
+ enum errs e = (enum errs) status;
+ switch (e) {
+ case E_PSI_GEN_NONE:
+ return "no error";
+ case E_PSI_GEN_FAIL:
+ return "general";
+ case E_PSI_GEN_ARG:
+ return "bad argument";
+ case E_PSI_GEN_OS:
+ return "OS error";
+ case E_PSI_GEN_NSUP:
+ return "not supported";
+ case E_PSI_GEN_UNDER:
+ return "numeric underflow";
+ case E_PSI_GEN_OVER:
+ return "numeric overflow";
+ case E_PSI_GEN_RANGE:
+ return "numeric exception";
+ case E_PSI_GEN_INUSE:
+ return "in use";
+ case E_PSI_GEN_NOMEMORY:
+ return "out of memory";
+ case E_PSI_GEN_NOSEGMENTS:
+ return "out of segments";
+ case E_PSI_GEN_NOSEM:
+ return "out of semaphores";
+ case E_PSI_GEN_NOPROC:
+ return "out of processes";
+ case E_PSI_GEN_OPEN:
+ return "already open";
+ case E_PSI_GEN_NOTOPEN:
+ return "not open";
+ case E_PSI_GEN_IMAGE:
+ return "bad image";
+ case E_PSI_GEN_RECEIVER:
+ return "receiver error";
+ case E_PSI_GEN_DEVICE:
+ return "device error";
+ case E_PSI_GEN_FSYS:
+ return "no filesystem";
+ case E_PSI_GEN_START:
+ return "not ready";
+ case E_PSI_GEN_NOFONT:
+ return "no font";
+ case E_PSI_GEN_TOOWIDE:
+ return "too wide";
+ case E_PSI_GEN_TOOMANY:
+ return "too many";
+ case E_PSI_FILE_EXIST:
+ return "file already exists";
+ case E_PSI_FILE_NXIST:
+ return "no such file";
+ case E_PSI_FILE_WRITE:
+ return "write error";
+ case E_PSI_FILE_READ:
+ return "read error";
+ case E_PSI_FILE_EOF:
+ return "end of file";
+ case E_PSI_FILE_FULL:
+ return "disk/serial read buffer full";
+ case E_PSI_FILE_NAME:
+ return "invalid name";
+ case E_PSI_FILE_ACCESS:
+ return "access denied";
+ case E_PSI_FILE_LOCKED:
+ return "ressource locked";
+ case E_PSI_FILE_DEVICE:
+ return "no such device";
+ case E_PSI_FILE_DIR:
+ return "no such directory";
+ case E_PSI_FILE_RECORD:
+ return "no such record";
+ case E_PSI_FILE_RDONLY:
+ return "file is read-only";
+ case E_PSI_FILE_INV:
+ return "invalid I/O operation";
+ case E_PSI_FILE_PENDING:
+ return "I/O pending (not yet completed)";
+ case E_PSI_FILE_VOLUME:
+ return "invalid volume name";
+ case E_PSI_FILE_CANCEL:
+ return "cancelled";
+ case E_PSI_FILE_ALLOC:
+ return "no memory for control block";
+ case E_PSI_FILE_DISC:
+ return "unit disconnected";
+ case E_PSI_FILE_CONNECT:
+ return "already connected";
+ case E_PSI_FILE_RETRAN:
+ return "retransmission threshold exceeded";
+ case E_PSI_FILE_LINE:
+ return "physical link failure";
+ case E_PSI_FILE_INACT:
+ return "inactivity timer expired";
+ case E_PSI_FILE_PARITY:
+ return "serial parity error";
+ case E_PSI_FILE_FRAME:
+ return "serial framing error";
+ case E_PSI_FILE_OVERRUN:
+ return "serial overrun error";
+ case E_PSI_MDM_CONFAIL:
+ return "modem cannot connect to remote modem";
+ case E_PSI_MDM_BUSY:
+ return "remote modem busy";
+ case E_PSI_MDM_NOANS:
+ return "remote modem did not answer";
+ case E_PSI_MDM_BLACKLIST:
+ return "number blacklisted by the modem";
+ case E_PSI_FILE_NOTREADY:
+ return "drive not ready";
+ case E_PSI_FILE_UNKNOWN:
+ return "unknown media";
+ case E_PSI_FILE_DIRFULL:
+ return "directory full";
+ case E_PSI_FILE_PROTECT:
+ return "write-protected";
+ case E_PSI_FILE_CORRUPT:
+ return "media corrupt";
+ case E_PSI_FILE_ABORT:
+ return "aborted operation";
+ case E_PSI_FILE_ERASE:
+ return "failed to erase flash media";
+ case E_PSI_FILE_INVALID:
+ return "invalid file for DBF system";
+ case E_PSI_GEN_POWER:
+ return "power failure";
+ case E_PSI_FILE_TOOBIG:
+ return "too big";
+ case E_PSI_GEN_DESCR:
+ return "bad descriptor";
+ case E_PSI_GEN_LIB:
+ return "bad entry point";
+ case E_PSI_FILE_NDISC:
+ return "could not diconnect";
+ case E_PSI_FILE_DRIVER:
+ return "bad driver";
+ case E_PSI_FILE_COMPLETION:
+ return "operation not completed";
+ case E_PSI_GEN_BUSY:
+ return "server busy";
+ case E_PSI_GEN_TERMINATED:
+ return "terminated";
+ case E_PSI_GEN_DIED:
+ return "died";
+ case E_PSI_FILE_HANDLE:
+ return "bad handle";
+ case E_PSI_NOT_SIBO:
+ return "invalid operation for RFSV16";
+ default:
+ return "Unknown error";
+ }
+}
+
diff --git a/lib/rfsv.h b/lib/rfsv.h
new file mode 100644
index 0000000..e6006ef
--- /dev/null
+++ b/lib/rfsv.h
@@ -0,0 +1,151 @@
+#ifndef _rfsv_h_
+#define _rfsv_h_
+
+class ppsocket;
+class bufferStore;
+class bufferArray;
+
+#define RFSV_SENDLEN 2000
+
+typedef int (*cpCallback_t)(long);
+
+// Abstract base class of RFSV ; 16-bit and 32-bit variants implement this
+// interface
+class rfsv {
+ public:
+ virtual ~rfsv() {}
+ virtual void reset() = 0;
+ virtual void reconnect() = 0;
+ virtual long getStatus() = 0;
+ virtual const char *getConnectName() = 0;
+ virtual long fopen(long, const char *, long &) = 0;
+ virtual long mktemp(long *, char *) = 0;
+ virtual long fcreatefile(long, const char *, long &) = 0;
+ virtual long freplacefile(long, const char *, long &) = 0;
+ virtual long fopendir(long, const char *, long &) = 0;
+ virtual long fclose(long) = 0;
+ virtual long dir(const char *, bufferArray *) = 0;
+ virtual long fgetmtime(const char *, long *) = 0;
+ virtual long fsetmtime(const char *, long) = 0;
+ virtual long fgetattr(const char *, long *) = 0;
+ virtual long fgeteattr(const char *, long *, long *, long *) =0;
+ virtual long fsetattr(const char *, long, long) = 0;
+ virtual long dircount(const char *, long *) = 0;
+ virtual long devlist(long *) = 0;
+ virtual char *devinfo(int, long *, long *, long *, long *) = 0;
+ virtual char *opAttr(long) = 0;
+ virtual long opMode(long) = 0;
+ virtual long fread(long, unsigned char *, long) = 0;
+ virtual long fwrite(long, unsigned char *, long) = 0;
+ virtual long copyFromPsion(const char *, const char *, cpCallback_t) = 0;
+ virtual long copyToPsion(const char *, const char *, cpCallback_t) = 0;
+ virtual long fsetsize(long, long) = 0;
+ virtual long fseek(long, long, long) = 0;
+ virtual long mkdir(const char *) = 0;
+ virtual long rmdir(const char *) = 0;
+ virtual long rename(const char *, const char *) = 0;
+ virtual long remove(const char *) = 0;
+
+ char *opErr(long);
+
+ enum seek_mode {
+ PSI_SEEK_SET = 1,
+ PSI_SEEK_CUR = 2,
+ PSI_SEEK_END = 3
+ };
+
+ enum open_flags {
+ PSI_O_RDONLY = 00,
+ PSI_O_WRONLY = 01,
+ PSI_O_RDWR = 02,
+ };
+
+ enum open_mode {
+ PSI_O_CREAT = 0100,
+ PSI_O_EXCL = 0200,
+ PSI_O_TRUNC = 01000,
+ PSI_O_APPEND = 02000,
+ };
+
+ enum errs {
+ E_PSI_GEN_NONE = 0,
+ E_PSI_GEN_FAIL = -1,
+ E_PSI_GEN_ARG = -2,
+ E_PSI_GEN_OS = -3,
+ E_PSI_GEN_NSUP = -4,
+ E_PSI_GEN_UNDER = -5,
+ E_PSI_GEN_OVER = -6,
+ E_PSI_GEN_RANGE = -7,
+ E_PSI_GEN_DIVIDE = -8,
+ E_PSI_GEN_INUSE = -9,
+ E_PSI_GEN_NOMEMORY = - 10,
+ E_PSI_GEN_NOSEGMENTS = -11,
+ E_PSI_GEN_NOSEM = -12,
+ E_PSI_GEN_NOPROC = -13,
+ E_PSI_GEN_OPEN = -14,
+ E_PSI_GEN_NOTOPEN = -15,
+ E_PSI_GEN_IMAGE = -16,
+ E_PSI_GEN_RECEIVER = -17,
+ E_PSI_GEN_DEVICE = -18,
+ E_PSI_GEN_FSYS = -19,
+ E_PSI_GEN_START = -20,
+ E_PSI_GEN_NOFONT = -21,
+ E_PSI_GEN_TOOWIDE = -22,
+ E_PSI_GEN_TOOMANY = -23,
+ E_PSI_FILE_EXIST = -32,
+ E_PSI_FILE_NXIST = -33,
+ E_PSI_FILE_WRITE = -34,
+ E_PSI_FILE_READ = -35,
+ E_PSI_FILE_EOF = -36,
+ E_PSI_FILE_FULL = -37,
+ E_PSI_FILE_NAME = -38,
+ E_PSI_FILE_ACCESS = -39,
+ E_PSI_FILE_LOCKED = -40,
+ E_PSI_FILE_DEVICE = -41,
+ E_PSI_FILE_DIR = -42,
+ E_PSI_FILE_RECORD = -43,
+ E_PSI_FILE_RDONLY = -44,
+ E_PSI_FILE_INV = -45,
+ E_PSI_FILE_PENDING = -46,
+ E_PSI_FILE_VOLUME = -47,
+ E_PSI_FILE_CANCEL = -48,
+ E_PSI_FILE_ALLOC = -49,
+ E_PSI_FILE_DISC = -50,
+ E_PSI_FILE_CONNECT = -51,
+ E_PSI_FILE_RETRAN = -52,
+ E_PSI_FILE_LINE = -53,
+ E_PSI_FILE_INACT = -54,
+ E_PSI_FILE_PARITY = -55,
+ E_PSI_FILE_FRAME = -56,
+ E_PSI_FILE_OVERRUN = -57,
+ E_PSI_MDM_CONFAIL = -58,
+ E_PSI_MDM_BUSY = -59,
+ E_PSI_MDM_NOANS = -60,
+ E_PSI_MDM_BLACKLIST = -61,
+ E_PSI_FILE_NOTREADY = -62,
+ E_PSI_FILE_UNKNOWN = -63,
+ E_PSI_FILE_DIRFULL = -64,
+ E_PSI_FILE_PROTECT = -65,
+ E_PSI_FILE_CORRUPT = -66,
+ E_PSI_FILE_ABORT = -67,
+ E_PSI_FILE_ERASE = -68,
+ E_PSI_FILE_INVALID = -69,
+ E_PSI_GEN_POWER = -100,
+ E_PSI_FILE_TOOBIG = -101,
+ E_PSI_GEN_DESCR = -102,
+ E_PSI_GEN_LIB = -103,
+ E_PSI_FILE_NDISC = -104,
+ E_PSI_FILE_DRIVER = -105,
+ E_PSI_FILE_COMPLETION = -106,
+ E_PSI_GEN_BUSY = -107,
+ E_PSI_GEN_TERMINATED = -108,
+ E_PSI_GEN_DIED = -109,
+ E_PSI_FILE_HANDLE = -110,
+
+ // Special error code for "Operation not permitted in RFSV16"
+ E_PSI_NOT_SIBO = -200
+ };
+};
+
+#endif
+
diff --git a/lib/rfsv16.cc b/lib/rfsv16.cc
new file mode 100644
index 0000000..9420b57
--- /dev/null
+++ b/lib/rfsv16.cc
@@ -0,0 +1,836 @@
+//
+// RFSV16 - An implementation of the PSION SIBO RFSV Client protocol
+//
+// Copyright (C) 1999 Philip Proudman
+// Modifications for plptools:
+// Copyright (C) 1999 Matt J. Gumbley <matt@gumbley.demon.co.uk>
+// Sources: rfsv32.cc by Fritz Elfert, and rfsv16.cc by Philip Proudman
+// Descriptions of the RFSV16 protocol by Michael Pieper, Olaf Flebbe & Me.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// e-mail philip.proudman@btinternet.com
+
+#include <stream.h>
+#include <stdlib.h>
+#include <fstream.h>
+#include <iomanip.h>
+#include <time.h>
+#include <string.h>
+
+#include "defs.h"
+#include "bool.h"
+#include "rfsv16.h"
+#include "bufferstore.h"
+#include "ppsocket.h"
+#include "bufferarray.h"
+
+rfsv16::rfsv16(ppsocket *_skt) : serNum(0)
+{
+ skt = _skt;
+ reset();
+}
+
+// move to base class?
+rfsv16::~rfsv16()
+{
+ bufferStore a;
+ a.addStringT("Close");
+ if (status == E_PSI_GEN_NONE)
+ skt->sendBufferStore(a);
+ skt->closeSocket();
+}
+
+// move to base class?
+void rfsv16::
+reconnect()
+{
+cerr << "rfsv16::reconnect" << endl;
+ skt->closeSocket();
+ skt->reconnect();
+ serNum = 0;
+ reset();
+}
+
+// move to base class?
+void rfsv16::
+reset()
+{
+cerr << "rfsv16::reset" << endl;
+ bufferStore a;
+ status = E_PSI_FILE_DISC;
+ a.addStringT(getConnectName());
+ if (skt->sendBufferStore(a)) {
+ if (skt->getBufferStore(a) == 1) {
+ if (!strcmp(a.getString(0), "Ok"))
+ status = E_PSI_GEN_NONE;
+ }
+ }
+}
+
+// move to base class?
+long rfsv16::
+getStatus()
+{
+ return status;
+}
+
+// move to base class?
+const char *rfsv16::
+getConnectName()
+{
+ return "SYS$RFSV.*";
+}
+
+int rfsv16::
+convertName(const char* orig, char *retVal)
+{
+ int len = strlen(orig);
+ char *temp = new char [len+1];
+
+ // FIXME: need to return 1 if OOM?
+ for (int i=0; i <= len; i++) {
+ if (orig[i] == '/')
+ temp[i] = '\\';
+ else
+ temp[i] = orig[i];
+ }
+
+ if (len == 0 || temp[1] != ':') {
+ // We can automatically supply a drive letter
+ strcpy(retVal, DDRIVE);
+
+ if (len == 0 || temp[0] != '\\') {
+ strcat(retVal, DBASEDIR);
+ }
+ else {
+ retVal[strlen(retVal)-1] = 0;
+ }
+
+ strcat(retVal, temp);
+ }
+ else {
+ strcpy(retVal, temp);
+ }
+
+ delete [] temp;
+ cout << retVal << endl;
+ return 0;
+}
+
+long rfsv16::
+fopen(long attr, const char *name, long &handle)
+{
+ bufferStore a;
+ char realName[200];
+ int rv = convertName(name, realName);
+ if (rv) return (long)rv;
+
+ // FIXME: anything that calls fopen should NOT do the name
+ // conversion - it's just done here.
+
+ a.addWord(attr & 0xFFFF);
+ a.addString(realName);
+ a.addByte(0x00); // Needs to be manually Null-Terminated.
+ if (!sendCommand(FOPEN, a))
+ return E_PSI_FILE_DISC;
+
+ long res = getResponse(a);
+ // cerr << "fopen, getword 0 is " << hex << setw(2) << a.getWord(0) << endl;
+ // cerr << "fopen, getlen is " << hex << setw(2) << a.getLen() << endl;
+ // cerr << "fopen, res is " << hex << setw(2) << res << endl;
+ if (!res && a.getLen() == 4 && a.getWord(0) == 0) {
+ handle = (long)a.getWord(2);
+ return 0;
+ }
+ // cerr << "fopen: Unknown response (" << attr << "," << name << ") " << a <<endl;
+ return res;
+}
+
+// internal
+long rfsv16::
+mktemp(long *handle, char *tmpname)
+{
+cerr << "rfsv16::mktemp ***" << endl;
+ return 0;
+}
+
+// internal and external
+long rfsv16::
+fcreatefile(long attr, const char *name, long &handle)
+{
+cerr << "rfsv16::fcreatefile ***" << endl;
+ return 0;
+}
+
+// this is internal - not used by plpnfsd, unlike fcreatefile
+long rfsv16::
+freplacefile(long attr, const char *name, long &handle)
+{
+cerr << "rfsv16::freplacefile ***" << endl;
+ return 0;
+}
+
+// internal
+long rfsv16::
+fopendir(long attr, const char *name, long &handle)
+{
+cerr << "rfsv16::fopendir ***" << endl;
+ return 0;
+}
+
+long rfsv16::
+fclose(long fileHandle)
+{
+ bufferStore a;
+ a.addWord(fileHandle & 0xFFFF);
+ if (!sendCommand(FCLOSE, a))
+ return E_PSI_FILE_DISC;
+ long res = getResponse(a);
+ if (!res && a.getLen() == 2)
+ return (long)a.getWord(0);
+ cerr << "fclose: Unknown response "<< a <<endl;
+ return 1;
+}
+
+long rfsv16::
+dir(const char *dirName, bufferArray * files)
+{
+ long fileHandle;
+ long res;
+
+ long status = fopen(P_FDIR, dirName, fileHandle);
+ if (status != 0) {
+ return status;
+ }
+
+ while (1) {
+ bufferStore a;
+ a.addWord(fileHandle & 0xFFFF);
+ if (!sendCommand(FDIRREAD, a))
+ return E_PSI_FILE_DISC;
+ res = getResponse(a);
+ if (res)
+ break;
+ a.discardFirstBytes(4); // Don't know what these mean!
+ while (a.getLen() > 16) {
+ int version = a.getWord(0);
+ if (version != 2) {
+ cerr << "dir: not version 2" << endl;
+ return 1;
+ }
+ int status = a.getWord(2);
+ long size = a.getDWord(4);
+ long date = a.getDWord(8);
+ const char *s = a.getString(16);
+ a.discardFirstBytes(17+strlen(s));
+
+ bufferStore temp;
+ temp.addDWord(date);
+ temp.addDWord(size);
+ temp.addDWord((long)status);
+ temp.addStringT(s);
+ files->pushBuffer(temp);
+ }
+ }
+ if ((short int)res == E_PSI_FILE_EOF)
+ res = 0;
+ fclose(fileHandle);
+ return res;
+}
+
+char * rfsv16::
+opAttr(long attr)
+{
+ static char buf[11];
+ buf[0] = ((attr & rfsv16::P_FAWRITE) ? 'w' : '-');
+ buf[1] = ((attr & rfsv16::P_FAHIDDEN) ? 'h' : '-');
+ buf[2] = ((attr & rfsv16::P_FASYSTEM) ? 's' : '-');
+ buf[3] = ((attr & rfsv16::P_FAVOLUME) ? 'v' : '-');
+ buf[4] = ((attr & rfsv16::P_FADIR) ? 'd' : '-');
+ buf[5] = ((attr & rfsv16::P_FAMOD) ? 'm' : '-');
+ buf[6] = ((attr & rfsv16::P_FAREAD) ? 'r' : '-');
+ buf[7] = ((attr & rfsv16::P_FAEXEC) ? 'x' : '-');
+ buf[8] = ((attr & rfsv16::P_FASTREAM) ? 'b' : '-');
+ buf[9] = ((attr & rfsv16::P_FATEXT) ? 't' : '-');
+ buf[10] = '\0';
+ return (char *) (&buf);
+}
+
+
+long rfsv16::
+opMode(long mode)
+{
+ long ret = 0;
+
+ ret |= ((mode & 03) == PSI_O_RDONLY) ? 0 : P_FUPDATE;
+ ret |= (mode & PSI_O_TRUNC) ? P_FREPLACE : 0;
+ ret |= (mode & PSI_O_CREAT) ? P_FCREATE : 0;
+ ret |= (mode & PSI_O_APPEND) ? P_FAPPEND : 0;
+ ret |= (mode & PSI_O_EXCL) ? 0 : P_FSHARE;
+ return ret;
+}
+
+long rfsv16::
+fgetmtime(const char *name, long *mtime)
+{
+cerr << "rfsv16::fgetmtime" << endl;
+ // NB: fgetattr, fgeteattr is almost identical...
+ bufferStore a;
+ char realName[200];
+ int rv = convertName(name, realName);
+ if (rv) return rv;
+ a.addString(realName);
+ a.addByte(0x00); // needs to be null-terminated,
+ // and this needs sending in the length word.
+ if (!sendCommand(FINFO, a))
+ return E_PSI_FILE_DISC;
+
+ long res = getResponse(a);
+ if (res != 0)
+ return res;
+ if (a.getLen() == 2) {
+ cerr << "fgetmtime: Error " << a.getWord(0) << " on file " << name << endl;
+ return 1;
+ }
+ else if (a.getLen() == 18 && a.getWord(0) == 0) {
+ *mtime = a.getDWord(10);
+ return a.getWord(0);
+ }
+ cerr << "fgetmtime: Unknown response (" << name << ") " << a <<endl;
+ return 1;
+}
+
+long rfsv16::
+fsetmtime(const char *name, long mtime)
+{
+cerr << "rfsv16::fsetmtime ***" << endl;
+ // I don't think there's a protocol frame that allows us to set the
+ // modification time. SFDATE allows setting of creation time...
+ return E_PSI_NOT_SIBO;
+}
+
+long rfsv16::
+fgetattr(const char *name, long *attr)
+{
+ // NB: fgetmtime, fgeteattr are almost identical...
+ bufferStore a;
+ char realName[200];
+ int rv = convertName(name, realName);
+ if (rv) return rv;
+ a.addString(realName);
+ a.addByte(0x00); // needs to be null-terminated,
+ // and this needs sending in the length word.
+ if (!sendCommand(FINFO, a))
+ return E_PSI_FILE_DISC;
+
+ long res = getResponse(a);
+ if (res != 0)
+ return res;
+ if (a.getLen() == 2) {
+ cerr << "fgetattr: Error " << a.getWord(0) << " on file " << name << endl;
+ return 1;
+ }
+ else if (a.getLen() == 18 && a.getWord(0) == 0) {
+ *attr = (long)(a.getWord(4));
+ return a.getWord(0);
+ }
+ cerr << "fgetattr: Unknown response (" << name << ") " << a <<endl;
+ return 1;
+}
+
+long rfsv16::
+fgeteattr(const char *name, long *attr, long *size, long *time)
+{
+ bufferStore a;
+ char realName[200];
+ int rv = convertName(name, realName);
+ if (rv) return rv;
+ a.addString(realName);
+ a.addByte(0x00); // needs to be null-terminated,
+ // and this needs sending in the length word.
+ if (!sendCommand(FINFO, a))
+ return E_PSI_FILE_DISC;
+
+ long res = getResponse(a);
+ if (res != 0)
+ return res;
+ if (a.getLen() == 2) {
+ cerr << "fgeteattr: Error " << a.getWord(0) << " on file " << name << endl;
+ return 1;
+ }
+ else if (a.getLen() == 18 && a.getWord(0) == 0) {
+ *attr = (long)(a.getWord(4));
+ *size = a.getDWord(6);
+ *time = a.getDWord(10);
+ return a.getWord(0);
+ }
+ cerr << "fgeteattr: Unknown response (" << name << ") " << a <<endl;
+ return 1;
+}
+
+long rfsv16::
+fsetattr(const char *name, long seta, long unseta)
+{
+cerr << "rfsv16::fsetattr" << endl;
+ // seta are attributes to set; unseta are attributes to unset. Need to
+ // turn this into attributes to change state and a bit mask.
+ // 210000
+ // 008421
+ // a shr
+ long statusword = seta & (~ unseta);
+ statusword ^= 0x0000001; // r bit is inverted
+ long bitmask = seta | unseta;
+ // cerr << "seta is " << hex << setw(2) << setfill('0') << seta << endl;
+ // cerr << "unseta is " << hex << setw(2) << setfill('0') << unseta << endl;
+ // cerr << "statusword is " << hex << setw(2) << setfill('0') << statusword << endl;
+ // cerr << "bitmask is " << hex << setw(2) << setfill('0') << bitmask << endl;
+ bufferStore a;
+ a.addWord(statusword & 0xFFFF);
+ a.addWord(bitmask & 0xFFFF);
+ a.addString(name);
+ a.addByte(0x00); // needs to be null-terminated,
+ // and this needs sending in the length word.
+ if (!sendCommand(SFSTAT, a))
+ return E_PSI_FILE_DISC;
+ return getResponse(a);
+}
+
+long rfsv16::
+dircount(const char *name, long *count)
+{
+ long fileHandle;
+ long res;
+ *count = 0;
+
+ long status = fopen(P_FDIR, name, fileHandle);
+ if (status != 0) {
+ return status;
+ }
+
+ while (1) {
+ bufferStore a;
+ a.addWord(fileHandle & 0xFFFF);
+ if (!sendCommand(FDIRREAD, a))
+ return E_PSI_FILE_DISC;
+ res = getResponse(a);
+ if (res)
+ break;
+ a.discardFirstBytes(4); // Don't know what these mean!
+ while (a.getLen() > 16) {
+ int version = a.getWord(0);
+ if (version != 2) {
+ cerr << "dir: not version 2" << endl;
+ return 1;
+ }
+ // int status = a.getWord(2);
+ // long size = a.getDWord(4);
+ // long date = a.getDWord(8);
+ const char *s = a.getString(16);
+ a.discardFirstBytes(17+strlen(s));
+ (*count)++;
+ }
+ }
+ if ((short int)res == E_PSI_FILE_EOF)
+ res = 0;
+ fclose(fileHandle);
+ return res;
+}
+
+long rfsv16::
+devlist(long *devbits)
+{
+ long res;
+ long fileHandle;
+ *devbits = 0;
+
+ // The following is taken from a trace between a Series 3c and PsiWin.
+ // Hope it works! We PARSE to find the correct node, then FOPEN
+ // (P_FDEVICE) this, FDEVICEREAD each entry, setting the appropriate
+ // drive-letter-bit in devbits, then FCLOSE.
+
+ bufferStore a;
+ a.init();
+ a.addByte(0x00); // no Name 1
+ a.addByte(0x00); // no Name 2
+ a.addByte(0x00); // no Name 3
+ if (!sendCommand(PARSE, a))
+ return E_PSI_FILE_DISC;
+ res = getResponse(a);
+ if (res)
+ return res;
+
+ // Find the drive to FOPEN
+ char name[4] = { 'x', ':', '\\', '\0' } ;
+ a.discardFirstBytes(8); // Result, fsys, dev, path, file, file, ending, flag
+ /* This leaves R E M : : M : \ */
+ name[0] = (char) a.getByte(5); // the M
+ long status = fopen(P_FDEVICE, name, fileHandle);
+ if (status != 0) {
+ return status;
+ }
+ while (1) {
+ bufferStore a;
+ a.init();
+ a.addWord(fileHandle & 0xFFFF);
+ if (!sendCommand(FDEVICEREAD, a))
+ return E_PSI_FILE_DISC;
+ res = getResponse(a);
+ if (res)
+ break;
+ a.discardFirstBytes(2); // Result
+ int version = a.getWord(0);
+ if (version != 2) {
+ cerr << "devlist: not version 2" << endl;
+ return 1; // FIXME
+ }
+ char drive = a.getByte(64);
+ if (drive >= 'A' && drive <= 'Z') {
+ int shift = (drive - 'A');
+ (*devbits) |= (long) ( 1 << shift );
+ }
+ else {
+ cerr << "devlist: non-alphabetic drive letter ("
+ << drive << ")" << endl;
+ }
+ }
+ if ((short int)res == E_PSI_FILE_EOF)
+ res = 0;
+ fclose(fileHandle);
+ return res;
+}
+
+char *rfsv16::
+devinfo(int devnum, long *vfree, long *vtotal, long *vattr,
+ long *vuniqueid)
+{
+ bufferStore a;
+ long res;
+ long fileHandle;
+
+ // Again, this is taken from an excahnge between PsiWin and a 3c.
+ // For each drive, we PARSE with its drive letter to get a response
+ // (which we ignore), then do a STATUSDEVICE to get the info.
+
+ a.init();
+ a.addByte((char) (devnum + 'A')); // Name 1
+ a.addByte(':');
+ a.addByte(0x00);
+ a.addByte(0x00); // No name 2
+ a.addByte(0x00); // No name 3
+ if (!sendCommand(PARSE, a))
+ return NULL;
+ res = getResponse(a);
+ if (res) {
+ // cerr << "devinfo PARSE res is " << dec << (signed short int) res << endl;
+ return NULL;
+ }
+
+ a.init();
+ a.addByte((char) (devnum + 'A')); // Name 1
+ a.addByte(':');
+ a.addByte('\\');
+ a.addByte(0x00);
+ if (!sendCommand(STATUSDEVICE, a))
+ return NULL;
+ res = getResponse(a);
+ if (res) {
+ // cerr << "devinfo STATUSDEVICE res is " << dec << (signed short int) res << endl;
+ return NULL;
+ }
+ a.discardFirstBytes(2); // Result
+ int type = a.getWord(2);
+ int changeable = a.getWord(4);
+ long size = a.getDWord(6);
+ long free = a.getDWord(10);
+ const char *volume = a.getString(14);
+ int battery = a.getWord(30);
+ const char *devicename = a.getString(62);
+ *vfree = free;
+ *vtotal = size;
+ *vattr = type;
+ *vuniqueid = 0;
+ static char name[2] = { 'x', '\0' };
+ name[0] = (char) (devnum + 'A');
+ return strdup(name);
+}
+
+bool rfsv16::
+sendCommand(enum commands cc, bufferStore & data)
+{
+ bool result;
+ bufferStore a;
+ a.addWord(cc);
+ a.addWord(data.getLen());
+ a.addBuff(data);
+ result = skt->sendBufferStore(a);
+ if (!result)
+ status = E_PSI_FILE_DISC;
+ return result;
+}
+
+
+long rfsv16::
+getResponse(bufferStore & data)
+{
+ // getWord(2) is the size field
+ // which is the body of the response not counting the command (002a) and
+ // the size word.
+ if (skt->getBufferStore(data) == 1 &&
+ data.getWord(0) == 0x2a &&
+ data.getWord(2) == data.getLen()-4) {
+ data.discardFirstBytes(4);
+ long ret = data.getWord(0);
+ return ret;
+ } else
+ status = E_PSI_FILE_DISC;
+ cerr << "rfsv16::getResponse: duff response. Size field:" <<
+data.getWord(2) << " Frame size:" << data.getLen()-4 << " Result field:" <<
+data.getWord(4) << endl;
+ return status;
+}
+
+char * rfsv16::
+opErr(long status)
+{
+cerr << "rfsv16::opErr 0x" << hex << setfill('0') << setw(4)
+ << status << " (" << dec << (signed short int)status << ")" << endl;
+ return rfsv::opErr(status);
+}
+
+long rfsv16::
+fread(long handle, unsigned char *buf, long len)
+{
+cerr << "rfsv16::fread ***" << endl;
+ bufferStore a;
+ long remaining = len;
+ // Read in blocks of 291 bytes; the maximum payload for an RFSV frame.
+ // ( As seen in traces ) - this isn't optimal: RFSV can handle
+ // fragmentation of frames, where only the first FREAD RESPONSE frame
+ // has a RESPONSE (00 2A), SIZE and RESULT field. Every subsequent frame
+ // just has data, 297 bytes (or less) of it.
+ const int maxblock = 291;
+ long readsofar = 0;
+ while (remaining) {
+ long thisblock = (remaining > maxblock) ? maxblock : remaining;
+cerr << "fread: " << dec << remaining << " bytes remain. This block is " << thisblock
+<< " bytes." << endl;
+ a.init();
+ a.addWord(handle);
+ a.addWord(thisblock);
+ sendCommand(FREAD, a);
+ long res = getResponse(a);
+ remaining -= a.getLen();
+// copy the data to buf
+
+cerr << "fread getResponse returned " << dec<< (signed short int) res << " data: " << a << dec <<endl;
+ if (res) {
+ return res;
+ }
+ }
+ return len;
+}
+
+long rfsv16::
+fwrite(long handle, unsigned char *buf, long len)
+{
+cerr << "rfsv16::fwrite ***" << endl;
+ return 0;
+}
+
+long rfsv16::
+copyFromPsion(const char *from, const char *to, cpCallback_t cb)
+{
+cerr << "rfsv16::copyFromPsion" << endl;
+ long handle;
+ long res;
+ long len;
+
+ if ((res = fopen(P_FSHARE | P_FSTREAM, from, handle)) != 0)
+ return res;
+cerr << "fopen response is " << dec << (signed short int)res << endl;
+ ofstream op(to);
+ if (!op) {
+ fclose(handle);
+ return -1;
+ }
+ do {
+ unsigned char buf[2000];
+ if ((len = fread(handle, buf, sizeof(buf))) > 0)
+ op.write(buf, len);
+ if (cb) {
+ if (!cb(len)) {
+ len = E_PSI_FILE_CANCEL;
+ break;
+ }
+ }
+ } while (len > 0);
+
+ fclose(handle);
+ op.close();
+ return len;
+}
+
+long rfsv16::
+copyToPsion(const char *from, const char *to, cpCallback_t cb)
+{
+cerr << "rfsv16::copyToPsion" << endl;
+ long handle;
+ long res;
+
+ ifstream ip(from);
+ if (!ip)
+ return E_PSI_FILE_NXIST;
+ res = fcreatefile(P_FSTREAM | P_FUPDATE, to, handle);
+ if (res != 0) {
+ res = freplacefile(P_FSTREAM | P_FUPDATE, to, handle);
+ if (res != 0)
+ return res;
+ }
+ unsigned char *buff = new unsigned char[RFSV_SENDLEN];
+ int total = 0;
+ while (ip && !ip.eof()) {
+ ip.read(buff, RFSV_SENDLEN);
+ bufferStore tmp(buff, ip.gcount());
+ int len = tmp.getLen();
+ total += len;
+ if (len == 0)
+ break;
+ bufferStore a;
+ a.addDWord(handle);
+ a.addBuff(tmp);
+ if (!sendCommand(FWRITE, a)) { // FIXME: need to check params
+ fclose(handle);
+ ip.close();
+ delete[]buff;
+ return E_PSI_FILE_DISC;
+ }
+ res = getResponse(a);
+ if (res) {
+ fclose(handle);
+ ip.close();
+ delete[]buff;
+ return res;
+ }
+ if (cb) {
+ if (!cb(len)) {
+ fclose(handle);
+ ip.close();
+ delete[]buff;
+ return E_PSI_FILE_CANCEL;
+ }
+ }
+ }
+ fclose(handle);
+ ip.close();
+ delete[]buff;
+ return 0;
+}
+
+long rfsv16::
+fsetsize(long handle, long size)
+{
+cerr << "rfsv16::fsetsize ***" << endl;
+ return 0;
+}
+
+/*
+ * Unix-like implementation off fseek with one
+ * exception: If seeking beyond eof, the gap
+ * contains garbage instead of zeroes.
+ */
+long rfsv16::
+fseek(long handle, long pos, long mode)
+{
+cerr << "rfsv16::fseek ***" << endl;
+ return 0;
+}
+
+long rfsv16::
+mkdir(const char* dirName)
+{
+ char realName[200];
+ int rv = convertName(dirName, realName);
+ if (rv) return rv;
+ bufferStore a;
+ a.addString(realName);
+ a.addByte(0x00); // needs to be null-terminated,
+ // and this needs sending in the length word.
+ sendCommand(MKDIR, a);
+ long res = getResponse(a);
+ if (!res && a.getLen() == 2) {
+ // Correct response
+ return a.getWord(0);
+ }
+ cerr << "Unknown response from mkdir "<< a <<endl;
+ return 1;
+}
+
+long rfsv16::
+rmdir(const char *dirName)
+{
+ // There doesn't seem to be an RMDIR command, but DELETE works. We
+ // should probably check to see if the file is a directory first!
+ return remove(dirName);
+}
+
+long rfsv16::
+rename(const char *oldName, const char *newName)
+{
+cerr << "rfsv16::rename ***" << endl;
+ char realOldName[200];
+ int rv = convertName(oldName, realOldName);
+ if (rv) return rv;
+ char realNewName[200];
+ rv = convertName(newName, realNewName);
+ if (rv) return rv;
+ bufferStore a;
+ a.addString(realOldName);
+ a.addByte(0x00); // needs to be null-terminated,
+ // and this needs sending in the length word.
+ a.addString(realNewName);
+ a.addByte(0x00); // needs to be null-terminated,
+ // and this needs sending in the length word.
+ sendCommand(RENAME, a);
+ long res = getResponse(a);
+ if (!res && a.getLen() == 2) {
+ // Correct response
+ return a.getWord(0);
+ }
+ cerr << "Unknown response from rename "<< a <<endl;
+ return 1;
+}
+
+long rfsv16::
+remove(const char* psionName)
+{
+ char realName[200];
+ int rv = convertName(psionName, realName);
+ if (rv) return rv;
+ bufferStore a;
+ a.addString(realName);
+ a.addByte(0x00); // needs to be null-terminated,
+ // and this needs sending in the length word.
+ sendCommand(DELETE, a);
+ long res = getResponse(a);
+ if (!res && a.getLen() == 2) {
+ // Correct response
+ return a.getWord(0);
+ }
+ cerr << "Unknown response from delete "<< a <<endl;
+ return 1;
+}
+
+
diff --git a/lib/rfsv16.h b/lib/rfsv16.h
new file mode 100644
index 0000000..175e540
--- /dev/null
+++ b/lib/rfsv16.h
@@ -0,0 +1,127 @@
+#ifndef _rfsv16_h_
+#define _rfsv16_h_
+
+#include "rfsv.h"
+
+class rfsv16 : public rfsv {
+ public:
+ rfsv16(ppsocket *);
+ ~rfsv16();
+ void reset(); // these 2 added
+ void reconnect();
+
+ // these are the original publics
+ long dir(const char *, bufferArray *);
+ /*long read(const char* psionName, const char* localName);
+ long write(const char* localName, const char* psionName);*/
+ long mkdir(const char *);
+
+ // these are FS' promotions
+ long dircount(const char *, long *);
+ long copyFromPsion(const char *, const char *, cpCallback_t);
+ long copyToPsion(const char *, const char *, cpCallback_t);
+ long rmdir(const char *);
+ long remove(const char *); // MJG: was this del? FE: yes
+ long rename(const char *, const char *);
+ long mktemp(long *, char *);
+ long fgeteattr(const char *, long *, long *, long *);
+ long fgetattr(const char *, long *);
+ long fsetattr(const char *, long seta, long unseta);
+ long fgetmtime(const char *, long *);
+ long fsetmtime(const char *, long);
+ long fopendir(long, const char *, long &);
+ long fopen(long, const char *, long &);
+ long fcreatefile(long, const char *, long &);
+ long freplacefile(long, const char *, long &);
+ long fseek(long, long, long);
+ long fread(long, unsigned char *, long);
+ long fwrite(long, unsigned char *, long);
+ long fsetsize(long, long);
+ long fclose(long);
+
+ long devlist(long *);
+ char *devinfo(int, long *, long *, long *, long *);
+ long getStatus();
+ char *opErr(long);
+ char *opAttr(long);
+ long opMode(long);
+
+private:
+ enum commands {
+ FOPEN = 0, // File Open
+ FCLOSE = 2, // File Close
+ FREAD = 4, // File Read
+ FDIRREAD = 6, // Read Directory entries
+ FDEVICEREAD = 8, // Device Information
+ FWRITE = 10, // File Write
+ FSEEK = 12, // File Seek
+ FFLUSH = 14, // Flush
+ FSETEOF = 16,
+ RENAME = 18,
+ DELETE = 20,
+ FINFO = 22,
+ SFSTAT = 24,
+ PARSE = 26,
+ MKDIR = 28,
+ OPENUNIQUE = 30,
+ STATUSDEVICE = 32,
+ PATHTEST = 34,
+ STATUSSYSTEM = 36,
+ CHANGEDIR = 38,
+ SFDATE = 40,
+ RESPONSE = 42
+ };
+
+ enum fopen_attrib {
+ P_FOPEN = 0x0000, /* Open file */
+ P_FCREATE = 0x0001, /* Create file */
+ P_FREPLACE = 0x0002, /* Replace file */
+ P_FAPPEND = 0x0003, /* Append records */
+ P_FUNIQUE = 0x0004, /* Unique file open */
+ P_FSTREAM = 0x0000, /* Stream access to a binary file */
+ P_FSTREAM_TEXT = 0x0010, /* Stream access to a text file */
+ P_FTEXT = 0x0020, /* Record access to a text file */
+ P_FDIR = 0x0030, /* Record access to a directory file */
+ P_FFORMAT = 0x0040, /* Format a device */
+ P_FDEVICE = 0x0050, /* Record access to device name list */
+ P_FNODE = 0x0060, /* Record access to node name list */
+ P_FUPDATE = 0x0100, /* Read and write access */
+ P_FRANDOM = 0x0200, /* Random access */
+ P_FSHARE = 0x0400 /* File can be shared */
+ };
+
+ enum status_enum {
+ P_FAWRITE = 0x0001, /* can the file be written to? */
+ P_FAHIDDEN = 0x0002, /* set if file is hidden */
+ P_FASYSTEM = 0x0004, /* set if file is a system file */
+ P_FAVOLUME = 0x0008, /* set if the name is a volume name */
+ P_FADIR = 0x0010, /* set if file is a directory file */
+ P_FAMOD = 0x0020, /* has the file been modified? */
+ P_FAREAD = 0x0100, /* can the file be read? */
+ P_FAEXEC = 0x0200, /* is the file executable? */
+ P_FASTREAM = 0x0400, /* is the file a byte stream file? */
+ P_FATEXT = 0x0800 /* is it a text file? */
+ };
+
+ const char *getConnectName();
+
+ // File handlers
+ //long fopen(fopen_attrib a, const char* file, int &handle); // returns status 0=OK
+ //long fclose(int fileHandle);
+
+ // Miscellaneous
+ int convertName(const char*, char *);
+
+ // Communication
+ bool sendCommand(enum commands, bufferStore &);
+ long getResponse(bufferStore &);
+
+ // Vars
+ ppsocket *skt;
+ // MJG: not sure what these are yet
+ int serNum;
+ long status; // current connection status
+ int tDiff; // don't think this is used anywhere
+};
+
+#endif
diff --git a/lib/rfsv32.cc b/lib/rfsv32.cc
index 447a693..d4df37f 100644
--- a/lib/rfsv32.cc
+++ b/lib/rfsv32.cc
@@ -33,8 +33,6 @@
#include "ppsocket.h"
#include "bufferarray.h"
-#define RFSV_SENDLEN 230
-
rfsv32::rfsv32(ppsocket * _skt) : serNum(0)
{
skt = _skt;
@@ -45,7 +43,7 @@ rfsv32::~rfsv32()
{
bufferStore a;
a.addStringT("Close");
- if (status == PSI_ERR_NONE)
+ if (status == E_PSI_GEN_NONE)
skt->sendBufferStore(a);
skt->closeSocket();
}
@@ -63,12 +61,12 @@ void rfsv32::
reset()
{
bufferStore a;
- status = PSI_ERR_DISCONNECTED;
+ status = E_PSI_FILE_DISC;
a.addStringT(getConnectName());
if (skt->sendBufferStore(a)) {
if (skt->getBufferStore(a) == 1) {
if (!strcmp(a.getString(0), "Ok"))
- status = PSI_ERR_NONE;
+ status = E_PSI_GEN_NONE;
}
}
}
@@ -82,7 +80,7 @@ getStatus()
const char *rfsv32::
getConnectName()
{
- return "SYS$RFSV.*";
+ return "SYS$RFSV";
}
char *rfsv32::
@@ -105,7 +103,7 @@ fopen(long attr, const char *name, long &handle)
a.addString(n);
free(n);
if (!sendCommand(OPEN_FILE, a))
- return PSI_ERR_DISCONNECTED;
+ return E_PSI_FILE_DISC;
long res = getResponse(a);
if (!res && a.getLen() == 4) {
handle = a.getDWord(0);
@@ -119,7 +117,7 @@ mktemp(long *handle, char *tmpname)
{
bufferStore a;
if (!sendCommand(TEMP_FILE, a))
- return PSI_ERR_DISCONNECTED;
+ return E_PSI_FILE_DISC;
long res = getResponse(a);
if (res == 0) {
*handle = a.getDWord(0);
@@ -138,7 +136,7 @@ fcreatefile(long attr, const char *name, long &handle)
a.addString(n);
free(n);
if (!sendCommand(CREATE_FILE, a))
- return PSI_ERR_DISCONNECTED;
+ return E_PSI_FILE_DISC;
long res = getResponse(a);
if (!res && a.getLen() == 4)
handle = a.getDWord(0);
@@ -155,7 +153,7 @@ freplacefile(long attr, const char *name, long &handle)
a.addString(n);
free(n);
if (!sendCommand(REPLACE_FILE, a))
- return PSI_ERR_DISCONNECTED;
+ return E_PSI_FILE_DISC;
long res = getResponse(a);
if (!res && a.getLen() == 4)
handle = a.getDWord(0);
@@ -172,7 +170,7 @@ fopendir(long attr, const char *name, long &handle)
a.addString(n);
free(n);
if (!sendCommand(OPEN_DIR, a))
- return PSI_ERR_DISCONNECTED;
+ return E_PSI_FILE_DISC;
long res = getResponse(a);
if (!res && a.getLen() == 4)
handle = a.getDWord(0);
@@ -185,7 +183,7 @@ fclose(long handle)
bufferStore a;
a.addDWord(handle);
if (!sendCommand(CLOSE_HANDLE, a))
- return PSI_ERR_DISCONNECTED;
+ return E_PSI_FILE_DISC;
return getResponse(a);
}
@@ -206,6 +204,7 @@ micro2time(unsigned long microHi, unsigned long microLo)
micro -= pes;
micro += EPOCH_DIFF_SECS;
micro -= EPOCH_2H;
+ micro += 3600; /* 1 hour PJC */
return (long) micro;
}
@@ -218,6 +217,7 @@ time2micro(unsigned long time, unsigned long &microHi, unsigned long &microLo)
micro += pes;
micro -= EPOCH_DIFF_SECS;
micro += EPOCH_2H;
+ micro -= 3600; /* 1 hour PJC */
micro *= (unsigned long long)1000000;
microLo = (micro & (unsigned long long)0x0FFFFFFFF);
micro >>= 32;
@@ -228,7 +228,7 @@ long rfsv32::
dir(const char *name, bufferArray * files)
{
long handle;
- long res = fopendir(PSI_ATTR_HIDDEN | PSI_ATTR_SYSTEM | PSI_ATTR_DIRECTORY, name, handle);
+ long res = fopendir(EPOC_ATTR_HIDDEN | EPOC_ATTR_SYSTEM | EPOC_ATTR_DIRECTORY, name, handle);
if (res != 0)
return res;
@@ -236,7 +236,7 @@ dir(const char *name, bufferArray * files)
bufferStore a;
a.addDWord(handle);
if (!sendCommand(READ_DIR, a))
- return PSI_ERR_DISCONNECTED;
+ return E_PSI_FILE_DISC;
res = getResponse(a);
if (res)
break;
@@ -270,12 +270,40 @@ dir(const char *name, bufferArray * files)
a.discardFirstBytes(d);
}
}
- if (res == PSI_ERR_EoF)
+ if (res == E_PSI_FILE_EOF)
res = 0;
fclose(handle);
return res;
}
+// beware this returns static data
+char * rfsv32::
+opAttr(long attr)
+{
+ static char buf[10];
+ buf[0] = ((attr & rfsv32::EPOC_ATTR_DIRECTORY) ? 'd' : '-');
+ buf[1] = ((attr & rfsv32::EPOC_ATTR_RONLY) ? '-' : 'w');
+ buf[2] = ((attr & rfsv32::EPOC_ATTR_HIDDEN) ? 'h' : '-');
+ buf[3] = ((attr & rfsv32::EPOC_ATTR_SYSTEM) ? 's' : '-');
+ buf[4] = ((attr & rfsv32::EPOC_ATTR_ARCHIVE) ? 'a' : '-');
+ buf[5] = ((attr & rfsv32::EPOC_ATTR_VOLUME) ? 'v' : '-');
+ buf[6] = ((attr & rfsv32::EPOC_ATTR_NORMAL) ? 'n' : '-');
+ buf[7] = ((attr & rfsv32::EPOC_ATTR_TEMPORARY) ? 't' : '-');
+ buf[8] = ((attr & rfsv32::EPOC_ATTR_COMPRESSED) ? 'c' : '-');
+ buf[9] = '\0';
+ return (char *) (&buf);
+}
+
+long rfsv32::
+opMode(long mode)
+{
+ long ret = 0;
+
+ ret |= (((mode & 03) == PSI_O_RDONLY) ? 0 : EPOC_OMODE_READ_WRITE);
+ ret |= (mode & PSI_O_EXCL) ? 0 : EPOC_OMODE_SHARE_READERS;
+ return ret;
+}
+
long rfsv32::
fgetmtime(const char *name, long *mtime)
{
@@ -285,7 +313,7 @@ fgetmtime(const char *name, long *mtime)
a.addString(n);
free(n);
if (!sendCommand(MODIFIED, a))
- return PSI_ERR_DISCONNECTED;
+ return E_PSI_FILE_DISC;
long res = getResponse(a);
if (res != 0)
return res;
@@ -306,7 +334,7 @@ fsetmtime(const char *name, long mtime)
a.addString(n);
free(n);
if (!sendCommand(SET_MODIFIED, a))
- return PSI_ERR_DISCONNECTED;
+ return E_PSI_FILE_DISC;
long res = getResponse(a);
if (res != 0)
return res;
@@ -322,7 +350,7 @@ fgetattr(const char *name, long *attr)
a.addString(n);
free(n);
if (!sendCommand(ATT, a))
- return PSI_ERR_DISCONNECTED;
+ return E_PSI_FILE_DISC;
long res = getResponse(a);
if (res != 0)
return res;
@@ -339,7 +367,7 @@ fgeteattr(const char *name, long *attr, long *size, long *time)
a.addString(n);
free(n);
if (!sendCommand(REMOTE_ENTRY, a))
- return PSI_ERR_DISCONNECTED;
+ return E_PSI_FILE_DISC;
long res = getResponse(a);
if (res != 0)
return res;
@@ -367,7 +395,7 @@ fsetattr(const char *name, long seta, long unseta)
a.addString(n);
free(n);
if (!sendCommand(SET_ATT, a))
- return PSI_ERR_DISCONNECTED;
+ return E_PSI_FILE_DISC;
return getResponse(a);
}
@@ -375,7 +403,7 @@ long rfsv32::
dircount(const char *name, long *count)
{
long handle;
- long res = fopendir(PSI_ATTR_HIDDEN | PSI_ATTR_SYSTEM | PSI_ATTR_DIRECTORY, name, handle);
+ long res = fopendir(EPOC_ATTR_HIDDEN | EPOC_ATTR_SYSTEM | EPOC_ATTR_DIRECTORY, name, handle);
*count = 0;
if (res != 0)
return res;
@@ -384,7 +412,7 @@ dircount(const char *name, long *count)
bufferStore a;
a.addDWord(handle);
if (!sendCommand(READ_DIR, a))
- return PSI_ERR_DISCONNECTED;
+ return E_PSI_FILE_DISC;
res = getResponse(a);
if (res)
break;
@@ -400,7 +428,7 @@ dircount(const char *name, long *count)
}
}
fclose(handle);
- if (res == PSI_ERR_EoF)
+ if (res == E_PSI_FILE_EOF)
res = 0;
return res;
}
@@ -412,7 +440,7 @@ devlist(long *devbits)
long res;
if (!sendCommand(GET_DRIVE_LIST, a))
- return PSI_ERR_DISCONNECTED;
+ return E_PSI_FILE_DISC;
res = getResponse(a);
*devbits = 0;
if ((res == 0) && (a.getLen() == 26)) {
@@ -451,9 +479,9 @@ devinfo(int devnum, long *vfree, long *vtotal, long *vattr,
bool rfsv32::
sendCommand(enum commands cc, bufferStore & data)
{
- if (status == PSI_ERR_DISCONNECTED) {
+ if (status == E_PSI_FILE_DISC) {
reconnect();
- if (status == PSI_ERR_DISCONNECTED)
+ if (status == E_PSI_FILE_DISC)
return false;
}
bool result;
@@ -467,7 +495,7 @@ sendCommand(enum commands cc, bufferStore & data)
a.addBuff(data);
result = skt->sendBufferStore(a);
if (!result)
- status = PSI_ERR_DISCONNECTED;
+ status = E_PSI_FILE_DISC;
return result;
}
@@ -478,155 +506,14 @@ getResponse(bufferStore & data)
data.getWord(0) == 0x11) {
long ret = data.getDWord(4);
data.discardFirstBytes(8);
- return ret;
+ return err2psierr(ret);
} else
- status = PSI_ERR_DISCONNECTED;
+ status = E_PSI_FILE_DISC;
return status;
}
-char * rfsv32::
-opErr(long status)
-{
- enum errs e = (enum errs) status;
- switch (e) {
- case PSI_ERR_NONE:
- return "";
- case PSI_ERR_NOT_FOUND:
- return "not found";
- case PSI_ERR_GENERAL:
- return "general";
- break;
- case PSI_ERR_CANCEL:
- return "cancelled";
- break;
- case PSI_ERR_NO_MEMORY:
- return "out of memory";
- break;
- case PSI_ERR_NOT_SUPPORTED:
- return "unsupported";
- break;
- case PSI_ERR_ARGUMENT:
- return "bad argument";
- break;
- case PSI_ERR_TOTAL_LOSS_OF_PRECISION:
- return "total loss of precision";
- break;
- case PSI_ERR_BAD_HANDLE:
- return "bad handle";
- break;
- case PSI_ERR_OVERFLOW:
- return "overflow";
- break;
- case PSI_ERR_UNDERFLOW:
- return "underflow";
- break;
- case PSI_ERR_ALREADY_EXISTS:
- return "file already exists";
- break;
- case PSI_ERR_PATH_NOT_FOUND:
- return "path not found";
- break;
- case PSI_ERR_DIED:
- return "DIED";
- break;
- case PSI_ERR_IN_USE:
- return "resource in use";
- break;
- case PSI_ERR_SERVER_TERMINATED:
- return "server terminated";
- break;
- case PSI_ERR_SERVER_BUSY:
- return "server busy";
- break;
- case PSI_ERR_COMPLETION:
- return "completed";
- break;
- case PSI_ERR_NOT_READY:
- return "not ready";
- break;
- case PSI_ERR_UNKNOWN:
- return "unknown";
- break;
- case PSI_ERR_CORRUPT:
- return "corrupt";
- break;
- case PSI_ERR_ACCESS_DENIED:
- return "permission denied";
- break;
- case PSI_ERR_LOCKED:
- return "resource locked";
- break;
- case PSI_ERR_WRITE:
- return "write";
- break;
- case PSI_ERR_DISMOUNTED:
- return "dismounted";
- break;
- case PSI_ERR_EoF:
- return "end of file";
- break;
- case PSI_ERR_DISK_FULL:
- return "disk full";
- break;
- case PSI_ERR_BAD_DRIVER:
- return "bad driver";
- break;
- case PSI_ERR_BAD_NAME:
- return "bad name";
- break;
- case PSI_ERR_COMMS_LINE_FAIL:
- return "comms line failed";
- break;
- case PSI_ERR_COMMS_FRAME:
- return "comms framing error";
- break;
- case PSI_ERR_COMMS_OVERRUN:
- return "comms overrun";
- break;
- case PSI_ERR_COMMS_PARITY:
- return "comms parity error";
- break;
- case PSI_ERR_TIMEOUT:
- return "timed out";
- break;
- case PSI_ERR_COULD_NOT_CONNECT:
- return "could not connect";
- break;
- case PSI_ERR_COULD_NOT_DISCONNECT:
- return "could not disconnect";
- break;
- case PSI_ERR_DISCONNECTED:
- return "unit disconnected";
- break;
- case PSI_ERR_BAD_LIBRARY_ENTRY_POINT:
- return "bad library entry point";
- break;
- case PSI_ERR_BAD_DESCRIPTOR:
- return "bad descriptor";
- break;
- case PSI_ERR_ABORT:
- return "abort";
- break;
- case PSI_ERR_TOO_BIG:
- return "too big";
- break;
- case PSI_ERR_DIVIDE_BY_ZERO:
- return "division by zero";
- break;
- case PSI_ERR_BAD_POWER:
- return "bad power";
- break;
- case PSI_ERR_DIR_FULL:
- return "directory full";
- break;
- default:
- return "Unknown error";
- break;
- }
-}
-
long rfsv32::
-fread(long handle, char *buf, long len)
+fread(long handle, unsigned char *buf, long len)
{
long res;
long count = 0;
@@ -634,9 +521,9 @@ fread(long handle, char *buf, long len)
do {
bufferStore a;
a.addDWord(handle);
- a.addDWord(((len-count) > 2000)?2000:(len-count));
+ a.addDWord(((len-count) > RFSV_SENDLEN)?RFSV_SENDLEN:(len-count));
if (!sendCommand(READ_FILE, a))
- return PSI_ERR_DISCONNECTED;
+ return E_PSI_FILE_DISC;
if ((res = getResponse(a)) != 0)
return res;
res = a.getLen();
@@ -650,20 +537,20 @@ fread(long handle, char *buf, long len)
}
long rfsv32::
-fwrite(long handle, char *buf, long len)
+fwrite(long handle, unsigned char *buf, long len)
{
long res;
long total = 0;
long count;
do {
- count = ((len - total) > 2000)?2000:(len - total);
+ count = ((len - total) > RFSV_SENDLEN)?RFSV_SENDLEN:(len - total);
bufferStore a;
bufferStore tmp((unsigned char *)buf, count);
a.addDWord(handle);
a.addBuff(tmp);
if (!sendCommand(WRITE_FILE, a))
- return PSI_ERR_DISCONNECTED;
+ return E_PSI_FILE_DISC;
if ((res = getResponse(a)) != 0)
return res;
total += count;
@@ -673,42 +560,48 @@ fwrite(long handle, char *buf, long len)
}
long rfsv32::
-copyFromPsion(const char *from, const char *to)
+copyFromPsion(const char *from, const char *to, cpCallback_t cb)
{
long handle;
long res;
long len;
- if ((res = fopen(PSI_OMODE_SHARE_READERS | PSI_OMODE_BINARY, from, handle)) != 0)
+ if ((res = fopen(EPOC_OMODE_SHARE_READERS | EPOC_OMODE_BINARY, from, handle)) != 0)
return res;
ofstream op(to);
if (!op) {
fclose(handle);
return -1;
}
+ unsigned char *buff = new unsigned char[RFSV_SENDLEN];
do {
- char buf[2000];
- if ((len = fread(handle, buf, sizeof(buf))) > 0)
- op.write(buf, len);
+ if ((len = fread(handle, buff, RFSV_SENDLEN)) > 0)
+ op.write(buff, len);
+ if (cb) {
+ if (!cb(len)) {
+ len = E_PSI_FILE_CANCEL;
+ break;
+ }
+ }
} while (len > 0);
-
+ delete[]buff;
fclose(handle);
op.close();
return len;
}
long rfsv32::
-copyToPsion(const char *from, const char *to)
+copyToPsion(const char *from, const char *to, cpCallback_t cb)
{
long handle;
long res;
ifstream ip(from);
if (!ip)
- return PSI_ERR_NOT_FOUND;
- res = fcreatefile(PSI_OMODE_BINARY | PSI_OMODE_SHARE_EXCLUSIVE | PSI_OMODE_READ_WRITE, to, handle);
+ return E_PSI_FILE_NXIST;
+ res = fcreatefile(EPOC_OMODE_BINARY | EPOC_OMODE_SHARE_EXCLUSIVE | EPOC_OMODE_READ_WRITE, to, handle);
if (res != 0) {
- res = freplacefile(PSI_OMODE_BINARY | PSI_OMODE_SHARE_EXCLUSIVE | PSI_OMODE_READ_WRITE, to, handle);
+ res = freplacefile(EPOC_OMODE_BINARY | EPOC_OMODE_SHARE_EXCLUSIVE | EPOC_OMODE_READ_WRITE, to, handle);
if (res != 0)
return res;
}
@@ -717,19 +610,33 @@ copyToPsion(const char *from, const char *to)
while (ip && !ip.eof()) {
ip.read(buff, RFSV_SENDLEN);
bufferStore tmp(buff, ip.gcount());
- total += tmp.getLen();
- if (tmp.getLen() == 0)
+ int len = tmp.getLen();
+ total += len;
+ if (len == 0)
break;
bufferStore a;
a.addDWord(handle);
a.addBuff(tmp);
- if (!sendCommand(WRITE_FILE, a))
- return PSI_ERR_DISCONNECTED;
+ if (!sendCommand(WRITE_FILE, a)) {
+ ip.close();
+ delete[]buff;
+ return E_PSI_FILE_DISC;
+ }
res = getResponse(a);
if (res) {
fclose(handle);
+ ip.close();
+ delete[]buff;
return res;
}
+ if (cb) {
+ if (!cb(len)) {
+ fclose(handle);
+ ip.close();
+ delete[]buff;
+ return E_PSI_FILE_CANCEL;
+ }
+ }
}
fclose(handle);
ip.close();
@@ -744,7 +651,7 @@ fsetsize(long handle, long size)
a.addDWord(handle);
a.addDWord(size);
if (!sendCommand(SET_SIZE, a))
- return PSI_ERR_DISCONNECTED;
+ return E_PSI_FILE_DISC;
return getResponse(a);
}
@@ -776,7 +683,7 @@ fseek(long handle, long pos, long mode)
*/
if ((mode < PSI_SEEK_SET) || (mode > PSI_SEEK_END))
- return PSI_ERR_ARGUMENT;
+ return E_PSI_GEN_ARG;
if ((mode == PSI_SEEK_CUR) && (pos >= 0)) {
/* get and save current position */
@@ -784,7 +691,7 @@ fseek(long handle, long pos, long mode)
a.addDWord(handle);
a.addDWord(PSI_SEEK_CUR);
if (!sendCommand(SEEK_FILE, a))
- return PSI_ERR_DISCONNECTED;
+ return E_PSI_FILE_DISC;
if ((res = getResponse(a)) != 0)
return res;
savpos = a.getDWord(0);
@@ -798,7 +705,7 @@ fseek(long handle, long pos, long mode)
a.addDWord(handle);
a.addDWord(PSI_SEEK_END);
if (!sendCommand(SEEK_FILE, a))
- return PSI_ERR_DISCONNECTED;
+ return E_PSI_FILE_DISC;
if ((res = getResponse(a)) != 0)
return res;
savpos = a.getDWord(0);
@@ -809,7 +716,7 @@ fseek(long handle, long pos, long mode)
a.addDWord(handle);
a.addDWord(savpos + pos);
if (!sendCommand(SET_SIZE, a))
- return PSI_ERR_DISCONNECTED;
+ return E_PSI_FILE_DISC;
if ((res = getResponse(a)) != 0)
return res;
pos = 0;
@@ -820,7 +727,7 @@ fseek(long handle, long pos, long mode)
a.addDWord(handle);
a.addDWord(mode);
if (!sendCommand(SEEK_FILE, a))
- return PSI_ERR_DISCONNECTED;
+ return E_PSI_FILE_DISC;
if ((res = getResponse(a)) != 0)
return res;
realpos = a.getDWord(0);
@@ -841,14 +748,14 @@ fseek(long handle, long pos, long mode)
a.addDWord(handle);
a.addDWord(calcpos);
if (!sendCommand(SET_SIZE, a))
- return PSI_ERR_DISCONNECTED;
+ return E_PSI_FILE_DISC;
if ((res = getResponse(a)) != 0)
return res;
a.addDWord(calcpos);
a.addDWord(handle);
a.addDWord(PSI_SEEK_SET);
if (!sendCommand(SEEK_FILE, a))
- return PSI_ERR_DISCONNECTED;
+ return E_PSI_FILE_DISC;
if ((res = getResponse(a)) != 0)
return res;
realpos = a.getDWord(0);
@@ -871,7 +778,7 @@ mkdir(const char *name)
}
free(n);
if (!sendCommand(MK_DIR_ALL, a))
- return PSI_ERR_DISCONNECTED;
+ return E_PSI_FILE_DISC;
return getResponse(a);
}
@@ -890,7 +797,7 @@ rmdir(const char *name)
}
free(n);
if (!sendCommand(RM_DIR, a))
- return PSI_ERR_DISCONNECTED;
+ return E_PSI_FILE_DISC;
return getResponse(a);
}
@@ -907,7 +814,7 @@ rename(const char *oldname, const char *newname)
free(on);
free(nn);
if (!sendCommand(RENAME, a))
- return PSI_ERR_DISCONNECTED;
+ return E_PSI_FILE_DISC;
return getResponse(a);
}
@@ -920,6 +827,63 @@ remove(const char *name)
a.addString(n);
free(n);
if (!sendCommand(DELETE, a))
- return PSI_ERR_DISCONNECTED;
+ return E_PSI_FILE_DISC;
return getResponse(a);
}
+
+static long e2psi[] = {
+ rfsv::E_PSI_FILE_DIRFULL, // -43
+ rfsv::E_PSI_GEN_POWER, // -42
+ rfsv::E_PSI_GEN_DIVIDE, // -41
+ rfsv::E_PSI_FILE_TOOBIG, // -40
+ rfsv::E_PSI_FILE_ABORT, // -39
+ rfsv::E_PSI_GEN_DESCR, // -38
+ rfsv::E_PSI_GEN_LIB, // -37
+ rfsv::E_PSI_FILE_NDISC, // -36
+ rfsv::E_PSI_FILE_DISC, // -35
+ rfsv::E_PSI_FILE_CONNECT, // -34
+ rfsv::E_PSI_FILE_RETRAN, // -33
+ rfsv::E_PSI_FILE_PARITY, // -32
+ rfsv::E_PSI_FILE_OVERRUN, // -31
+ rfsv::E_PSI_FILE_FRAME, // -30
+ rfsv::E_PSI_FILE_LINE, // -29
+ rfsv::E_PSI_FILE_NAME, // -28
+ rfsv::E_PSI_FILE_DRIVER, // -27
+ rfsv::E_PSI_FILE_FULL, // -26
+ rfsv::E_PSI_FILE_EOF, // -25
+ rfsv::E_PSI_GEN_FSYS, // -24
+ rfsv::E_PSI_FILE_WRITE, // -23
+ rfsv::E_PSI_FILE_LOCKED, // -22
+ rfsv::E_PSI_FILE_ACCESS, // -21
+ rfsv::E_PSI_FILE_CORRUPT, // -20
+ rfsv::E_PSI_FILE_UNKNOWN, // -19
+ rfsv::E_PSI_FILE_NOTREADY, // -18
+ rfsv::E_PSI_FILE_COMPLETION, // -17
+ rfsv::E_PSI_GEN_BUSY, // -16
+ rfsv::E_PSI_GEN_TERMINATED, // -15
+ rfsv::E_PSI_GEN_INUSE, // -14
+ rfsv::E_PSI_GEN_DIED, // -13
+ rfsv::E_PSI_FILE_DIR, // -12
+ rfsv::E_PSI_FILE_EXIST, // -11
+ rfsv::E_PSI_GEN_UNDER, // -10
+ rfsv::E_PSI_GEN_OVER, // -9
+ rfsv::E_PSI_FILE_HANDLE, // -8
+ rfsv::E_PSI_GEN_RANGE, // -7
+ rfsv::E_PSI_GEN_ARG, // -6
+ rfsv::E_PSI_GEN_NSUP, // -5
+ rfsv::E_PSI_GEN_NOMEMORY, // -4
+ rfsv::E_PSI_FILE_CANCEL, // -3
+ rfsv::E_PSI_GEN_FAIL, // -2
+ rfsv::E_PSI_FILE_NXIST, // -1
+ rfsv::E_PSI_GEN_NONE // 0
+};
+
+long rfsv32::
+err2psierr(long status)
+{
+ if ((status > E_EPOC_NONE) || (status < E_EPOC_DIR_FULL)) {
+ cerr << "FATAL: inavlid error-code" << endl;
+ return -999;
+ }
+ return e2psi[status - E_EPOC_DIR_FULL];
+}
diff --git a/lib/rfsv32.h b/lib/rfsv32.h
index 00cab2b..8383e72 100644
--- a/lib/rfsv32.h
+++ b/lib/rfsv32.h
@@ -1,121 +1,119 @@
#ifndef _rfsv32_h_
#define _rfsv32_h_
+#include "rfsv.h"
+
class ppsocket;
class bufferStore;
class bufferArray;
-class rfsv32 {
+class rfsv32 : public rfsv {
public:
- rfsv32(ppsocket * skt);
+ rfsv32(ppsocket *);
~rfsv32();
void reset();
void reconnect();
- long dir(const char *name, bufferArray * files);
- long dircount(const char *name, long *count);
- long copyFromPsion(const char *from, const char *to);
- long copyToPsion(const char *from, const char *to);
- long mkdir(const char *name);
- long rmdir(const char *name);
- long remove(const char *name);
- long rename(const char *oldname, const char *newname);
- long mktemp(long *handle, char *tmpname);
- long fgeteattr(const char *name, long *attr, long *size, long *time);
- long fgetattr(const char *name, long *attr);
- long fsetattr(const char *name, long seta, long unseta);
- long fgetmtime(const char *name, long *mtime);
- long fsetmtime(const char *name, long mtime);
- long fopendir(long attr, const char *name, long &handle);
- long fopen(long attr, const char *name, long &handle);
- long fcreatefile(long attr, const char *name, long &handle);
- long freplacefile(long attr, const char *name, long &handle);
- long fseek(long handle, long pos, long mode);
- long fread(long handle, char *buf, long len);
- long fwrite(long handle, char *buf, long len);
- long fsetsize(long handle, long size);
- long fclose(long handle);
+ long dir(const char *, bufferArray *);
+ long dircount(const char *, long *);
+ long copyFromPsion(const char *, const char *, cpCallback_t);
+ long copyToPsion(const char *, const char *, cpCallback_t);
+ long mkdir(const char *);
+ long rmdir(const char *);
+ long remove(const char *);
+ long rename(const char *, const char *);
+ long mktemp(long *, char *);
+ long fgeteattr(const char *, long *, long *, long *);
+ long fgetattr(const char *, long *);
+ long fsetattr(const char *, long, long);
+ long fgetmtime(const char *, long *);
+ long fsetmtime(const char *, long);
+ long fopendir(long, const char *, long &);
+ long fopen(long, const char *, long &);
+ long fcreatefile(long, const char *, long &);
+ long freplacefile(long, const char *, long &);
+ long fseek(long, long, long);
+ long fread(long, unsigned char *, long);
+ long fwrite(long, unsigned char *, long);
+ long fsetsize(long, long);
+ long fclose(long);
- long devlist(long *devbits);
- char *devinfo(int devnum, long *vfree, long *vtotal, long *vattr, long *vuiqueid);
+ long devlist(long *);
+ char *devinfo(int, long *, long *, long *, long *);
long getStatus();
- char *opErr(long status);
-
- enum seek_mode {
- PSI_SEEK_SET = 1,
- PSI_SEEK_CUR = 2,
- PSI_SEEK_END = 3
- };
+ char *opAttr(long);
+ long opMode(long);
+ private:
+
enum file_attrib {
- PSI_ATTR_RONLY = 0x0001,
- PSI_ATTR_HIDDEN = 0x0002,
- PSI_ATTR_SYSTEM = 0x0004,
- PSI_ATTR_DIRECTORY = 0x0010,
- PSI_ATTR_ARCHIVE = 0x0020,
- PSI_ATTR_VOLUME = 0x0040,
- PSI_ATTR_NORMAL = 0x0080,
- PSI_ATTR_TEMPORARY = 0x0100,
- PSI_ATTR_COMPRESSED = 0x0800
+ EPOC_ATTR_RONLY = 0x0001,
+ EPOC_ATTR_HIDDEN = 0x0002,
+ EPOC_ATTR_SYSTEM = 0x0004,
+ EPOC_ATTR_DIRECTORY = 0x0010,
+ EPOC_ATTR_ARCHIVE = 0x0020,
+ EPOC_ATTR_VOLUME = 0x0040,
+ EPOC_ATTR_NORMAL = 0x0080,
+ EPOC_ATTR_TEMPORARY = 0x0100,
+ EPOC_ATTR_COMPRESSED = 0x0800
};
enum open_mode {
- PSI_OMODE_SHARE_EXCLUSIVE = 0x0000,
- PSI_OMODE_SHARE_READERS = 0x0001,
- PSI_OMODE_SHARE_ANY = 0x0002,
- PSI_OMODE_BINARY = 0x0000,
- PSI_OMODE_TEXT = 0x0020,
- PSI_OMODE_READ_WRITE = 0x0200
+ EPOC_OMODE_SHARE_EXCLUSIVE = 0x0000,
+ EPOC_OMODE_SHARE_READERS = 0x0001,
+ EPOC_OMODE_SHARE_ANY = 0x0002,
+ EPOC_OMODE_BINARY = 0x0000,
+ EPOC_OMODE_TEXT = 0x0020,
+ EPOC_OMODE_READ_WRITE = 0x0200
};
- enum errs {
- PSI_ERR_NONE = 0,
- PSI_ERR_NOT_FOUND = -1,
- PSI_ERR_GENERAL = -2,
- PSI_ERR_CANCEL = -3,
- PSI_ERR_NO_MEMORY = -4,
- PSI_ERR_NOT_SUPPORTED = -5,
- PSI_ERR_ARGUMENT = -6,
- PSI_ERR_TOTAL_LOSS_OF_PRECISION = -7,
- PSI_ERR_BAD_HANDLE = -8,
- PSI_ERR_OVERFLOW = -9,
- PSI_ERR_UNDERFLOW = -10,
- PSI_ERR_ALREADY_EXISTS = -11,
- PSI_ERR_PATH_NOT_FOUND = -12,
- PSI_ERR_DIED = -13,
- PSI_ERR_IN_USE = -14,
- PSI_ERR_SERVER_TERMINATED = -15,
- PSI_ERR_SERVER_BUSY = -16,
- PSI_ERR_COMPLETION = -17,
- PSI_ERR_NOT_READY = -18,
- PSI_ERR_UNKNOWN = -19,
- PSI_ERR_CORRUPT = -20,
- PSI_ERR_ACCESS_DENIED = -21,
- PSI_ERR_LOCKED = -22,
- PSI_ERR_WRITE = -23,
- PSI_ERR_DISMOUNTED = -24,
- PSI_ERR_EoF = -25,
- PSI_ERR_DISK_FULL = -26,
- PSI_ERR_BAD_DRIVER = -27,
- PSI_ERR_BAD_NAME = -28,
- PSI_ERR_COMMS_LINE_FAIL = -29,
- PSI_ERR_COMMS_FRAME = -30,
- PSI_ERR_COMMS_OVERRUN = -31,
- PSI_ERR_COMMS_PARITY = -32,
- PSI_ERR_TIMEOUT = -33,
- PSI_ERR_COULD_NOT_CONNECT = -34,
- PSI_ERR_COULD_NOT_DISCONNECT = -35,
- PSI_ERR_DISCONNECTED = -36,
- PSI_ERR_BAD_LIBRARY_ENTRY_POINT = -37,
- PSI_ERR_BAD_DESCRIPTOR = -38,
- PSI_ERR_ABORT = -39,
- PSI_ERR_TOO_BIG = -40,
- PSI_ERR_DIVIDE_BY_ZERO = -41,
- PSI_ERR_BAD_POWER = -42,
- PSI_ERR_DIR_FULL = -43
+ enum epoc_errs {
+ E_EPOC_NONE = 0,
+ E_EPOC_NOT_FOUND = -1,
+ E_EPOC_GENERAL = -2,
+ E_EPOC_CANCEL = -3,
+ E_EPOC_NO_MEMORY = -4,
+ E_EPOC_NOT_SUPPORTED = -5,
+ E_EPOC_ARGUMENT = -6,
+ E_EPOC_TOTAL_LOSS_OF_PRECISION = -7,
+ E_EPOC_BAD_HANDLE = -8,
+ E_EPOC_OVERFLOW = -9,
+ E_EPOC_UNDERFLOW = -10,
+ E_EPOC_ALREADY_EXISTS = -11,
+ E_EPOC_PATH_NOT_FOUND = -12,
+ E_EPOC_DIED = -13,
+ E_EPOC_IN_USE = -14,
+ E_EPOC_SERVER_TERMINATED = -15,
+ E_EPOC_SERVER_BUSY = -16,
+ E_EPOC_COMPLETION = -17,
+ E_EPOC_NOT_READY = -18,
+ E_EPOC_UNKNOWN = -19,
+ E_EPOC_CORRUPT = -20,
+ E_EPOC_ACCESS_DENIED = -21,
+ E_EPOC_LOCKED = -22,
+ E_EPOC_WRITE = -23,
+ E_EPOC_DISMOUNTED = -24,
+ E_EPOC_EoF = -25,
+ E_EPOC_DISK_FULL = -26,
+ E_EPOC_BAD_DRIVER = -27,
+ E_EPOC_BAD_NAME = -28,
+ E_EPOC_COMMS_LINE_FAIL = -29,
+ E_EPOC_COMMS_FRAME = -30,
+ E_EPOC_COMMS_OVERRUN = -31,
+ E_EPOC_COMMS_PARITY = -32,
+ E_EPOC_TIMEOUT = -33,
+ E_EPOC_COULD_NOT_CONNECT = -34,
+ E_EPOC_COULD_NOT_DISCONNECT = -35,
+ E_EPOC_DISCONNECTED = -36,
+ E_EPOC_BAD_LIBRARY_ENTRY_POINT = -37,
+ E_EPOC_BAD_DESCRIPTOR = -38,
+ E_EPOC_ABORT = -39,
+ E_EPOC_TOO_BIG = -40,
+ E_EPOC_DIVIDE_BY_ZERO = -41,
+ E_EPOC_BAD_POWER = -42,
+ E_EPOC_DIR_FULL = -43
};
- private:
enum commands {
CLOSE_HANDLE = 0x01,
OPEN_DIR = 0x10,
@@ -154,15 +152,16 @@ class rfsv32 {
};
const char *getConnectName();
+ long err2psierr(long);
// Communication
- bool sendCommand(enum commands c, bufferStore & data);
- long getResponse(bufferStore & data);
- char *convertSlash(const char *name);
+ bool sendCommand(enum commands, bufferStore &);
+ long getResponse(bufferStore &);
+ char *convertSlash(const char *);
// time-conversion
- unsigned long micro2time(unsigned long microHi, unsigned long microLo);
- void time2micro(unsigned long mtime, unsigned long &microHi, unsigned long &microLo);
+ unsigned long micro2time(unsigned long, unsigned long);
+ void time2micro(unsigned long, unsigned long &, unsigned long &);
// Vars
ppsocket *skt;
diff --git a/lib/rfsvfactory.cc b/lib/rfsvfactory.cc
new file mode 100644
index 0000000..2e2067e
--- /dev/null
+++ b/lib/rfsvfactory.cc
@@ -0,0 +1,86 @@
+//
+// RFSVFACTORY - factory object that creates an appropriate RFSV object
+// based on whatever the NCP daemon discovered in the INFO exchange.
+//
+// Copyright (C) 1999 Matt J. Gumbley <matt@gumbley.demon.co.uk>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+#include <stream.h>
+#include <stdlib.h>
+#include <fstream.h>
+#include <iomanip.h>
+#include <time.h>
+#include <string.h>
+
+#include "defs.h"
+#include "bool.h"
+#include "rfsv.h"
+#include "rfsv16.h"
+#include "rfsv32.h"
+#include "rfsvfactory.h"
+#include "bufferstore.h"
+#include "ppsocket.h"
+#include "bufferarray.h"
+
+rfsvfactory::rfsvfactory(ppsocket *_skt) : serNum(0)
+{
+ skt = _skt;
+}
+
+rfsv * rfsvfactory::create(bool reconnect)
+{
+ // skt is connected to the ncp daemon, which will have (hopefully) seen
+ // an INFO exchange, where the protocol version of the remote Psion was
+ // sent, and noted. We have to ask the ncp daemon which protocol it saw,
+ // so we can instantiate the correct RFSV protocol handler for the
+ // caller. We announce ourselves to the NCP daemon, and the relevant
+ // RFSV module will also announce itself.
+ bufferStore a;
+ a.init();
+ a.addStringT("NCP$INFO");
+ if (!skt->sendBufferStore(a)) {
+ if (!reconnect)
+ cerr << "rfsvfactory::create couldn't send version request" << endl; else {
+ skt->closeSocket();
+ serNum = 0;
+ skt->reconnect();
+ }
+ return NULL;
+ }
+ if (skt->getBufferStore(a) == 1) {
+ if (a.getLen() > 8 && !strncmp(a.getString(), "Series 3", 8)) {
+ return new rfsv16(skt);
+ }
+ else if (a.getLen() > 8 && !strncmp(a.getString(), "Series 5", 8)) {
+ return new rfsv32(skt);
+ }
+ if ((a.getLen() > 8) && !strncmp(a.getString(), "No Psion", 8)) {
+ skt->closeSocket();
+ serNum = 0;
+ skt->reconnect();
+ return NULL;
+ }
+ // Invalid protocol version
+ cerr << "rfsvfactory::create received odd protocol version from
+ncpd! (" << a << ")" << endl;
+ } else {
+ cerr << "rfsvfactory::create sent, response not 1" << endl;
+ }
+
+ // No message returned.
+ return NULL;
+}
+
diff --git a/lib/rfsvfactory.h b/lib/rfsvfactory.h
new file mode 100644
index 0000000..17b7252
--- /dev/null
+++ b/lib/rfsvfactory.h
@@ -0,0 +1,20 @@
+#ifndef _rfsvfactory_h_
+#define _rfsvfactory_h_
+
+#include "rfsv.h"
+
+class ppsocket;
+
+class rfsvfactory {
+ public:
+ rfsvfactory(ppsocket * skt);
+ virtual rfsv * create(bool);
+
+ private:
+ // Vars
+ ppsocket *skt;
+ int serNum;
+};
+
+#endif
+
diff --git a/lib/rpcs.cc b/lib/rpcs.cc
new file mode 100644
index 0000000..5863c5b
--- /dev/null
+++ b/lib/rpcs.cc
@@ -0,0 +1,283 @@
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+
+#include <stream.h>
+#include <stdlib.h>
+#include <fstream.h>
+#include <iomanip.h>
+#include <time.h>
+#include <string.h>
+
+#include "defs.h"
+#include "bool.h"
+#include "rpcs.h"
+#include "bufferstore.h"
+#include "ppsocket.h"
+#include "bufferarray.h"
+
+//
+// public common API
+//
+void rpcs::
+reconnect()
+{
+ skt->closeSocket();
+ skt->reconnect();
+ reset();
+}
+
+void rpcs::
+reset()
+{
+ bufferStore a;
+ status = E_PSI_FILE_DISC;
+ a.addStringT(getConnectName());
+ if (skt->sendBufferStore(a)) {
+ if (skt->getBufferStore(a) == 1) {
+ if (!strcmp(a.getString(0), "Ok"))
+ status = E_PSI_GEN_NONE;
+ }
+ }
+}
+
+long rpcs::
+getStatus()
+{
+ return status;
+}
+
+const char *rpcs::
+getConnectName()
+{
+ return "SYS$RPCS";
+}
+
+//
+// protected internals
+//
+char *rpcs::
+convertSlash(const char *name)
+{
+ char *n = strdup(name);
+ for (char *p = n; *p; p++)
+ if (*p == '/')
+ *p = '\\';
+ return n;
+}
+
+bool rpcs::
+sendCommand(enum commands cc, bufferStore & data)
+{
+ if (status == E_PSI_FILE_DISC) {
+ reconnect();
+ if (status == E_PSI_FILE_DISC)
+ return false;
+ }
+ bool result;
+ bufferStore a;
+ a.addByte(cc);
+ a.addBuff(data);
+ result = skt->sendBufferStore(a);
+ if (!result)
+ status = E_PSI_FILE_DISC;
+ return result;
+}
+
+long rpcs::
+getResponse(bufferStore & data)
+{
+ if (skt->getBufferStore(data) == 1) {
+ long ret = data.getByte(0);
+ return ret;
+ } else
+ status = E_PSI_FILE_DISC;
+ return status;
+}
+
+//
+// APIs, identical on SIBO and EPOC
+//
+int rpcs::
+getNCPversion(int &major, int &minor)
+{
+ bufferStore a;
+ if (!sendCommand(QUERY_NCP, a))
+ return E_PSI_FILE_DISC;
+ long res = getResponse(a);
+ a.discardFirstBytes(1);
+ if (res)
+ return res;
+ if (a.getLen() != 2)
+ return E_PSI_GEN_FAIL;
+ major = a.getByte(0);
+ minor = a.getByte(1);
+ return res;
+}
+
+int rpcs::
+execProgram(const char *program, const char *args)
+{
+ bufferStore a;
+ a.addStringT(program);
+ int l = strlen(program);
+ for (int i = 127; i > l; i--)
+ a.addByte(0);
+ a.addByte(strlen(args));
+ a.addStringT(args);
+ if (!sendCommand(EXEC_PROG, a))
+ return E_PSI_FILE_DISC;
+ long res = getResponse(a);
+cout << res << " " << a << endl;
+ return res;
+}
+
+int rpcs::
+stopProgram(const char *program)
+{
+ bufferStore a;
+ a.addStringT(program);
+ if (!sendCommand(STOP_PROG, a))
+ return E_PSI_FILE_DISC;
+ return getResponse(a);
+}
+
+int rpcs::
+queryProgram(const char *program)
+{
+ bufferStore a;
+ a.addStringT(program);
+ if (!sendCommand(QUERY_PROG, a))
+ return E_PSI_FILE_DISC;
+ return getResponse(a);
+}
+
+int rpcs::
+formatOpen(const char *drive, int &handle, int &count)
+{
+ bufferStore a;
+ a.addStringT(drive);
+ if (!sendCommand(FORMAT_OPEN, a))
+ return E_PSI_FILE_DISC;
+ long res = getResponse(a);
+ a.discardFirstBytes(1);
+ if (res)
+ return res;
+ if (a.getLen() != 4)
+ return E_PSI_GEN_FAIL;
+ handle = a.getWord(0);
+ count = a.getWord(2);
+ return res;
+}
+
+int rpcs::
+formatRead(int handle)
+{
+ bufferStore a;
+ a.addWord(handle);
+ if (!sendCommand(FORMAT_READ, a))
+ return E_PSI_FILE_DISC;
+ return getResponse(a);
+}
+
+int rpcs::
+getUniqueID(const char *device, long &id)
+{
+ bufferStore a;
+ a.addStringT(device);
+ if (!sendCommand(GET_UNIQUEID, a))
+ return E_PSI_FILE_DISC;
+ long res = getResponse(a);
+ a.discardFirstBytes(1);
+ if (res)
+ return res;
+ if (a.getLen() != 4)
+ return E_PSI_GEN_FAIL;
+ id = a.getDWord(0);
+ return res;
+}
+
+int rpcs::
+getOwnerInfo(bufferArray &ret)
+{
+ bufferStore a;
+ if (!sendCommand(GET_OWNERINFO, a))
+ return E_PSI_FILE_DISC;
+ long res = getResponse(a);
+ a.discardFirstBytes(1);
+ if (res)
+ return res;
+ a.addByte(0);
+ int l = a.getLen();
+ char *s = (char *)a.getString(0);
+ for (int i = 0; i < l; i++)
+ if (s[i] == 6)
+ s[i] = 0;
+ ret.clear();
+ while (l > 0) {
+ bufferStore b;
+ b.addStringT(s);
+ ret += b;
+ l -= (strlen(s) + 1);
+ s += (strlen(s) + 1);
+ }
+ return res;
+}
+
+int rpcs::
+getMachineType(int &type)
+{
+ bufferStore a;
+ if (!sendCommand(GET_MACHINETYPE, a))
+ return E_PSI_FILE_DISC;
+ long res = getResponse(a);
+ a.discardFirstBytes(1);
+ if (res)
+ return res;
+ if (a.getLen() != 2)
+ return E_PSI_GEN_FAIL;
+ type = a.getWord(0);
+ return res;
+}
+
+int rpcs::
+fuser(const char *name, char *buf, int bufsize)
+{
+ bufferStore a;
+ a.addStringT(name);
+ if (!sendCommand(FUSER, a))
+ return E_PSI_FILE_DISC;
+ long res = getResponse(a);
+ a.discardFirstBytes(1);
+ if (res)
+ return res;
+ int len = ((int)a.getLen() > bufsize) ? bufsize - 1 : a.getLen();
+ strncpy(buf, a.getString(0), len);
+ buf[len] = '\0';
+ char *p;
+ while ((p = strchr(buf, 6)))
+ *p = '\n';
+ return res;
+}
+
+int rpcs::
+quitServer()
+{
+ bufferStore a;
+ if (!sendCommand(QUIT_SERVER, a))
+ return E_PSI_FILE_DISC;
+ return getResponse(a);
+}
+
diff --git a/lib/rpcs.h b/lib/rpcs.h
new file mode 100644
index 0000000..cb71c88
--- /dev/null
+++ b/lib/rpcs.h
@@ -0,0 +1,103 @@
+#ifndef _rpcs_h_
+#define _rpcs_h_
+
+class ppsocket;
+class bufferStore;
+class bufferArray;
+
+class rpcs {
+ public:
+ virtual ~rpcs() {};
+ void reset();
+ void reconnect();
+ long getStatus();
+
+ // API idendical on SIBO and EPOC
+ int getNCPversion(int &, int &);
+ int execProgram(const char *, const char *);
+ int stopProgram(const char *);
+ int queryProgram(const char *);
+ int formatOpen(const char *, int &, int &);
+ int formatRead(int);
+ int getUniqueID(const char *, long &);
+ int getOwnerInfo(bufferArray &);
+ int getMachineType(int &);
+ int fuser(const char *, char *, int);
+ int quitServer(void);
+
+ // API different on SIBO and EPOC
+ virtual int queryDrive(const char, bufferArray &) = 0;
+ virtual int getCmdLine(const char *, char *, int) = 0;
+
+ // API only existent on EPOC
+ // default-methods for SIBO here.
+ virtual int getMachineInfo(void) { return E_PSI_NOT_SIBO;}
+ virtual int closeHandle(int) { return E_PSI_NOT_SIBO;}
+ virtual int regOpenIter(void) { return E_PSI_NOT_SIBO;}
+ virtual int regReadIter(void) { return E_PSI_NOT_SIBO;}
+ virtual int regWrite(void) { return E_PSI_NOT_SIBO;}
+ virtual int regRead(void) { return E_PSI_NOT_SIBO;}
+ virtual int regDelete(void) { return E_PSI_NOT_SIBO;}
+ virtual int setTime(void) { return E_PSI_NOT_SIBO;}
+ virtual int configOpen(void) { return E_PSI_NOT_SIBO;}
+ virtual int configRead(void) { return E_PSI_NOT_SIBO;}
+ virtual int configWrite(void) { return E_PSI_NOT_SIBO;}
+ virtual int queryOpen(void) { return E_PSI_NOT_SIBO;}
+ virtual int queryRead(void) { return E_PSI_NOT_SIBO;}
+
+ enum errs {
+ E_PSI_GEN_NONE = 0,
+ E_PSI_GEN_FAIL = -1,
+ E_PSI_FILE_DISC = -50,
+ // Special error code for "Operation not permitted in RPCS16"
+ E_PSI_NOT_SIBO = -200
+ };
+
+ enum machs {
+ PSI_MACH_UNKNOWN = 0,
+ PSI_MACH_PC = 1,
+ PSI_MACH_MC = 2,
+ PSI_MACH_HC = 3,
+ PSI_MACH_S3 = 4,
+ PSI_MACH_S3A = 5,
+ PSI_MACH_WORKABOUT = 6,
+ PSI_MACH_SIENNA = 7,
+ PSI_MACH_S3C = 8,
+ PSI_MACH_S5 = 32,
+ PSI_MACH_WINC = 33,
+//TODO: Code for 5mx
+ };
+
+ protected:
+
+ // Vars
+ ppsocket *skt;
+ long status;
+
+ enum commands {
+ QUERY_NCP = 0x00,
+ EXEC_PROG = 0x01,
+ QUERY_DRIVE = 0x02,
+ STOP_PROG = 0x03,
+ QUERY_PROG = 0x04,
+ FORMAT_OPEN = 0x05,
+ FORMAT_READ = 0x06,
+ GET_UNIQUEID = 0x07,
+ GET_OWNERINFO = 0x08,
+ GET_MACHINETYPE = 0x09,
+ GET_CMDLINE = 0x0a,
+ FUSER = 0x0b,
+ CONFIG_OPEN = 0x66,
+ CONFIG_READ = 0x6d,
+ QUIT_SERVER = 0xff
+ };
+
+ // Communication
+ bool sendCommand(enum commands, bufferStore &);
+ long getResponse(bufferStore &);
+ const char *getConnectName();
+
+ char *convertSlash(const char *);
+};
+
+#endif
diff --git a/lib/rpcs16.cc b/lib/rpcs16.cc
new file mode 100644
index 0000000..2786ee8
--- /dev/null
+++ b/lib/rpcs16.cc
@@ -0,0 +1,63 @@
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+
+#include <stream.h>
+#include <stdlib.h>
+#include <fstream.h>
+#include <iomanip.h>
+#include <time.h>
+#include <string.h>
+
+#include "defs.h"
+#include "bool.h"
+#include "rpcs16.h"
+#include "bufferstore.h"
+#include "ppsocket.h"
+
+rpcs16::rpcs16(ppsocket * _skt)
+{
+ skt = _skt;
+ reset();
+}
+
+rpcs16::~rpcs16()
+{
+ bufferStore a;
+ a.addStringT("Close");
+ if (status == E_PSI_GEN_NONE)
+ skt->sendBufferStore(a);
+ skt->closeSocket();
+}
+
+int rpcs16::
+queryDrive(char drive, bufferArray &ret)
+{
+ bufferStore a;
+ a.addByte(drive);
+ if (!sendCommand(rpcs::QUERY_DRIVE, a))
+ return rpcs::E_PSI_FILE_DISC;
+ long res = getResponse(a);
+cout << dec << "qd: " << res << " " << a.getLen() << " a="<< a << endl;
+ if (res)
+ return res;
+ return res;
+}
+
+int rpcs16::
+getCmdLine(const char *process, char *buf, int bufsize)
+{
+ return 0;
+}
diff --git a/lib/rpcs16.h b/lib/rpcs16.h
new file mode 100644
index 0000000..14809ae
--- /dev/null
+++ b/lib/rpcs16.h
@@ -0,0 +1,18 @@
+#ifndef _rpcs16_h_
+#define _rpcs16_h_
+
+#include "rpcs.h"
+
+class ppsocket;
+class bufferStore;
+
+class rpcs16 : public rpcs {
+ public:
+ rpcs16(ppsocket *);
+ ~rpcs16();
+
+ int queryDrive(const char, bufferArray &);
+ int getCmdLine(const char *, char *, int);
+};
+
+#endif
diff --git a/lib/rpcs32.cc b/lib/rpcs32.cc
new file mode 100644
index 0000000..d710b9c
--- /dev/null
+++ b/lib/rpcs32.cc
@@ -0,0 +1,114 @@
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+
+#include <stream.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <fstream.h>
+#include <iomanip.h>
+#include <time.h>
+#include <string.h>
+
+#include "defs.h"
+#include "bool.h"
+#include "rpcs32.h"
+#include "bufferstore.h"
+#include "bufferarray.h"
+#include "ppsocket.h"
+
+rpcs32::rpcs32(ppsocket * _skt)
+{
+ skt = _skt;
+ reset();
+}
+
+rpcs32::~rpcs32()
+{
+ bufferStore a;
+ a.addStringT("Close");
+ if (status == E_PSI_GEN_NONE)
+ skt->sendBufferStore(a);
+ skt->closeSocket();
+}
+
+int rpcs32::
+queryDrive(char drive, bufferArray &ret)
+{
+ bufferStore a;
+ a.addByte(drive);
+ if (!sendCommand(rpcs::QUERY_DRIVE, a))
+ return rpcs::E_PSI_FILE_DISC;
+ getResponse(a);
+ int l = a.getLen();
+ ret.clear();
+//cout << dec << "qd: " << a.getLen() << " a="<< a << endl;
+ while (l > 1) {
+ bufferStore b, c;
+ const char *s;
+ char *p;
+ int pid;
+ int sl;
+
+ s = a.getString(0);
+ sl = strlen(s) + 1;
+ l -= sl;
+ a.discardFirstBytes(sl);
+ p = strstr(s, ".$");
+ if (p) {
+ *p = '\0'; p += 2;
+ sscanf(p, "%d", &pid);
+ } else
+ pid = 0;
+ b.addWord(pid);
+ b.addStringT(s);
+ s = a.getString(0);
+ sl = strlen(s) + 1;
+ l -= sl;
+ a.discardFirstBytes(sl);
+ c.addStringT(s);
+ ret.push(c);
+ ret.push(b);
+ }
+ return 0;
+}
+
+int rpcs32::
+getCmdLine(const char *process, char *buf, int bufsize)
+{
+ return 0;
+}
+
+int rpcs32::
+configOpen(void)
+{
+ bufferStore a;
+cout << "configOpen:" << endl;
+ if (!sendCommand(rpcs::CONFIG_OPEN, a))
+ return rpcs::E_PSI_FILE_DISC;
+ getResponse(a);
+cout << a << endl;
+}
+
+int rpcs32::
+configRead(void)
+{
+ bufferStore a;
+cout << "configRead:" << endl;
+ if (!sendCommand(rpcs::CONFIG_READ, a))
+ return rpcs::E_PSI_FILE_DISC;
+ getResponse(a);
+cout << a << endl;
+}
diff --git a/lib/rpcs32.h b/lib/rpcs32.h
new file mode 100644
index 0000000..e33ef10
--- /dev/null
+++ b/lib/rpcs32.h
@@ -0,0 +1,36 @@
+#ifndef _rpcs32_h_
+#define _rpcs32_h_
+
+#include "rpcs.h"
+
+class ppsocket;
+
+class rpcs32 : public rpcs {
+ public:
+ rpcs32(ppsocket *);
+ ~rpcs32();
+
+ int queryDrive(const char, bufferArray &);
+ int getCmdLine(const char *, char *, int);
+#if 0
+ int getMachineInfo(void);
+ int closeHandle(int);
+ int regOpenIter(void);
+ int regReadIter(void);
+ int regWrite(void);
+ int regRead(void);
+ int regDelete(void);
+ int setTime(void);
+#endif
+ int configOpen(void);
+ int configRead(void);
+#if 0
+ int configWrite(void);
+ int queryOpen(void);
+ int queryRead(void);
+ int quitServer(void);
+#endif
+
+};
+
+#endif
diff --git a/lib/rpcsfactory.cc b/lib/rpcsfactory.cc
new file mode 100644
index 0000000..7358e56
--- /dev/null
+++ b/lib/rpcsfactory.cc
@@ -0,0 +1,85 @@
+//
+// RPCSFACTORY - factory object that creates an appropriate RPCS object
+// based on whatever the NCP daemon discovered in the INFO exchange.
+// Derived from rfsvfactory by Matt J. Gumbley <matt@gumbley.demon.co.uk>
+//
+// Copyright (C) 2000 Fritz Elfert <felfert@to.com>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+#include <stream.h>
+#include <stdlib.h>
+#include <fstream.h>
+#include <iomanip.h>
+#include <time.h>
+#include <string.h>
+
+#include "defs.h"
+#include "bool.h"
+#include "rpcs16.h"
+#include "rpcs32.h"
+#include "rpcsfactory.h"
+#include "bufferstore.h"
+#include "ppsocket.h"
+
+rpcsfactory::rpcsfactory(ppsocket *_skt) : serNum(0)
+{
+ skt = _skt;
+}
+
+rpcs * rpcsfactory::create(bool reconnect)
+{
+ // skt is connected to the ncp daemon, which will have (hopefully) seen
+ // an INFO exchange, where the protocol version of the remote Psion was
+ // sent, and noted. We have to ask the ncp daemon which protocol it saw,
+ // so we can instantiate the correct rpcs protocol handler for the
+ // caller. We announce ourselves to the NCP daemon, and the relevant
+ // rpcs module will also announce itself.
+ bufferStore a;
+ a.init();
+ a.addStringT("NCP$INFO");
+ if (!skt->sendBufferStore(a)) {
+ if (!reconnect)
+ cerr << "rpcsfactory::create couldn't send version request" << endl; else {
+ skt->closeSocket();
+ serNum = 0;
+ skt->reconnect();
+ }
+ return NULL;
+ }
+ if (skt->getBufferStore(a) == 1) {
+ if (a.getLen() > 8 && !strncmp(a.getString(), "Series 3", 8)) {
+ return new rpcs16(skt);
+ }
+ else if (a.getLen() > 8 && !strncmp(a.getString(), "Series 5", 8)) {
+ return new rpcs32(skt);
+ }
+ if ((a.getLen() > 8) && !strncmp(a.getString(), "No Psion", 8)) {
+ skt->closeSocket();
+ serNum = 0;
+ skt->reconnect();
+ return NULL;
+ }
+ // Invalid protocol version
+ cerr << "rpcsfactory::create received odd protocol version from
+ncpd! (" << a << ")" << endl;
+ } else {
+ cerr << "rpcsfactory::create sent, response not 1" << endl;
+ }
+
+ // No message returned.
+ return NULL;
+}
+
diff --git a/lib/rpcsfactory.h b/lib/rpcsfactory.h
new file mode 100644
index 0000000..17a2719
--- /dev/null
+++ b/lib/rpcsfactory.h
@@ -0,0 +1,20 @@
+#ifndef _rpcsfactory_h_
+#define _rpcsfactory_h_
+
+#include "rpcs.h"
+
+class ppsocket;
+
+class rpcsfactory {
+ public:
+ rpcsfactory(ppsocket * skt);
+ virtual rpcs * create(bool);
+
+ private:
+ // Vars
+ ppsocket *skt;
+ int serNum;
+};
+
+#endif
+
diff --git a/ncpd/channel.cc b/ncpd/channel.cc
index a75c791..f52cea1 100644
--- a/ncpd/channel.cc
+++ b/ncpd/channel.cc
@@ -32,6 +32,7 @@
channel::channel(ncp * _ncpController)
{
verbose = 0;
+ ncpChannel = 0;
ncpController = _ncpController;
_terminate = false;
}
@@ -61,17 +62,41 @@ ncpConnect()
}
void channel::
+ncpRegister()
+{
+ ncpController->Register(this);
+}
+
+void channel::
+ncpDoRegisterAck(int ch)
+{
+ ncpController->RegisterAck(ch);
+}
+
+void channel::
ncpDisconnect()
{
ncpController->disconnect(ncpChannel);
}
+short int channel::
+ncpProtocolVersion()
+{
+ return ncpController->getProtocolVersion();
+}
+
void channel::
setNcpChannel(int chan)
{
ncpChannel = chan;
}
+int channel::
+getNcpChannel()
+{
+ return ncpChannel;
+}
+
void channel::
newNcpController(ncp * _ncpController)
{
diff --git a/ncpd/channel.h b/ncpd/channel.h
index a8f5225..2c06d6d 100644
--- a/ncpd/channel.h
+++ b/ncpd/channel.h
@@ -35,18 +35,25 @@ class bufferStore;
class channel {
public:
channel(ncp *ncpController);
+ virtual ~channel() {}
void newNcpController(ncp *ncpController);
void setNcpChannel(int chan);
+ int getNcpChannel(void);
void ncpSend(bufferStore &a);
void setVerbose(short int _verbose);
short int getVerbose();
virtual void ncpDataCallback(bufferStore &a) = NULL;
- virtual const char *getNcpConnectName() = NULL;
+ virtual char *getNcpConnectName() = NULL;
void ncpConnect();
+ void ncpRegister();
+ void ncpDoRegisterAck(int);
virtual void ncpConnectAck() = NULL;
virtual void ncpConnectTerminate() = NULL;
+ virtual void ncpConnectNak() = NULL;
+ virtual void ncpRegisterAck() = NULL;
void ncpDisconnect();
+ short int ncpProtocolVersion();
// The following two calls are used for destructing an instance
virtual bool terminate(); // Mainloop will terminate this class if true
@@ -57,8 +64,8 @@ class channel {
private:
ncp *ncpController;
- bool _terminate;
int ncpChannel;
+ bool _terminate;
};
#endif
diff --git a/ncpd/linkchan.cc b/ncpd/linkchan.cc
index e4891c1..4a2a4d4 100644
--- a/ncpd/linkchan.cc
+++ b/ncpd/linkchan.cc
@@ -23,30 +23,63 @@
// e-mail philip.proudman@btinternet.com
#include <stream.h>
+#include <iomanip.h>
#include "linkchan.h"
#include "bufferstore.h"
+#include "bufferarray.h"
linkChan::linkChan(ncp * _ncpController):channel(_ncpController)
{
+ registerSer = 0x1234;
+ ncpConnect();
}
void linkChan::
ncpDataCallback(bufferStore & a)
{
+ int len = a.getLen();
if (verbose & LINKCHAN_DEBUG_LOG) {
cout << "linkchan: << msg ";
if (verbose & LINKCHAN_DEBUG_DUMP)
cout << a << endl;
else
- cout << a.getLen() << endl;
+ cout << len << endl;
}
+ if ((len > 7) && (a.getByte(0) == 1)) {
+ unsigned int ser = a.getWord(1);
+ int res = a.getWord(3);
+ // int dontknow = a.getWord(5);
+ const char *srvName = a.getString(7);
+ bufferArray newStack;
+ bufferStore se;
+
+ if (verbose & LINKCHAN_DEBUG_LOG)
+ cout << "linkchan: received registerAck: ser=0x" << hex << setw(4)
+ << setfill(0) << ser << " res=" << res << " srvName=\""
+ << srvName << "\"" << endl;
+
+ while (!registerStack.empty()) {
+ se = registerStack.popBuffer();
+ if (se.getWord(0) == ser) {
+ if (verbose & LINKCHAN_DEBUG_LOG)
+ cout << "linkchan: found ser=0x" << hex << setw(4) <<
+ setfill(0) << se.getWord(0) <<
+ " on stack -> callBack to waiting chan" << endl;
+ ncpDoRegisterAck((int)se.getWord(2));
+ } else
+ newStack.pushBuffer(se);
+ }
+ registerStack = newStack;
+ return;
+ }
+ cerr << "linkchan: unknown message " << a.getByte(0) << endl;
}
-const char *linkChan::
+char *linkChan::
getNcpConnectName()
{
- return "LINK.*";
+ return "LINK";
}
void linkChan::
@@ -63,3 +96,25 @@ ncpConnectTerminate()
cout << "linkchan: << ctrm" << endl;
terminateWhenAsked();
}
+
+void linkChan::
+ncpConnectNak()
+{
+ ncpConnectTerminate();
+}
+
+void linkChan::
+Register(channel *ch)
+{
+ bufferStore a;
+ bufferStore stack;
+
+ stack.addWord(registerSer);
+ stack.addWord(ch->getNcpChannel());
+ registerStack.pushBuffer(stack);
+ a.addByte(0);
+ a.addWord(registerSer++);
+ a.addString(ch->getNcpConnectName());
+ a.addByte(0);
+ ncpSend(a);
+}
diff --git a/ncpd/linkchan.h b/ncpd/linkchan.h
index 2e2f7b9..4be75d0 100644
--- a/ncpd/linkchan.h
+++ b/ncpd/linkchan.h
@@ -26,6 +26,7 @@
#define _linkchan_h_
#include "channel.h"
+#include "bufferarray.h"
#define LINKCHAN_DEBUG_LOG 1
#define LINKCHAN_DEBUG_DUMP 2
@@ -35,9 +36,15 @@ class linkChan : public channel {
linkChan(ncp *ncpController);
void ncpDataCallback(bufferStore &a);
- const char *getNcpConnectName();
+ char *getNcpConnectName();
void ncpConnectAck();
void ncpConnectTerminate();
+ void ncpConnectNak();
+ void ncpRegisterAck() {}
+ void Register(channel *);
+ private:
+ int registerSer;
+ bufferArray registerStack;
};
#endif
diff --git a/ncpd/main.cc b/ncpd/main.cc
index 101d7aa..3a0ddb6 100644
--- a/ncpd/main.cc
+++ b/ncpd/main.cc
@@ -52,7 +52,7 @@ checkForNewSocketConnection(ppsocket & skt, int &numScp, socketChan ** scp, ncp
cout << "New socket connection from " << peer << endl;
if ((numScp == 7) || (!a->gotLinkChannel())) {
bufferStore a;
- a.addStringT("No psion");
+ a.addStringT("No Psion Connected\n");
next->sendBufferStore(a);
next->closeSocket();
} else
@@ -119,8 +119,16 @@ main(int argc, char **argv)
pverbose |= PKT_DEBUG_LOG;
if (!strcmp(argv[i], "pd"))
pverbose |= PKT_DEBUG_DUMP;
+ if (!strcmp(argv[i], "ph"))
+ lverbose |= PKT_DEBUG_HANDSHAKE;
if (!strcmp(argv[i], "m"))
verbose = true;
+ if (!strcmp(argv[i], "all")) {
+ nverbose = NCP_DEBUG_LOG | NCP_DEBUG_DUMP;
+ lverbose = LNK_DEBUG_LOG | LNK_DEBUG_DUMP;
+ pverbose = PKT_DEBUG_LOG | PKT_DEBUG_DUMP;
+ verbose = true;
+ }
} else if (!strcmp(argv[i], "-b") && i + 1 < argc) {
baudRate = atoi(argv[++i]);
} else if (!strcmp(argv[i], "-d")) {
@@ -152,7 +160,7 @@ main(int argc, char **argv)
}
ncp *a = new ncp(serialDevice, baudRate, iow);
int numScp = 0;
- socketChan *scp[8];
+ socketChan *scp[MAX_CHANNEL+1];
a->setVerbose(nverbose);
a->setLinkVerbose(lverbose);
diff --git a/ncpd/ncp.cc b/ncpd/ncp.cc
index b13ba62..e1bf96a 100644
--- a/ncpd/ncp.cc
+++ b/ncpd/ncp.cc
@@ -41,9 +41,10 @@ ncp::ncp(const char *fname, int baud, IOWatch & iow)
l = new link(fname, baud, iow);
failed = false;
verbose = 0;
+ protocolVersion = PV_SERIES_5; // until detected on receipt of INFO
// init channels
- for (int i = 0; i < 8; i++)
+ for (int i = 0; i < MAX_CHANNEL; i++)
channelPtr[i] = NULL;
}
@@ -54,13 +55,13 @@ ncp::~ncp()
void ncp::
reset() {
- for (int i = 0; i < 8; i++) {
+ for (int i = 0; i < MAX_CHANNEL; i++) {
if (channelPtr[i])
channelPtr[i]->terminateWhenAsked();
channelPtr[i] = NULL;
}
failed = false;
- gotLinkChan = false;
+ lChan = NULL;
l->reset();
}
@@ -100,6 +101,12 @@ setPktVerbose(short int _verbose)
l->setPktVerbose(_verbose);
}
+short int ncp::
+getProtocolVersion()
+{
+ return protocolVersion;
+}
+
void ncp::
poll()
{
@@ -153,6 +160,7 @@ void ncp::
decodeControlMessage(bufferStore & buff)
{
int remoteChan = buff.getByte(0);
+ short int ver;
interControllerMessageType imt = (interControllerMessageType) buff.getByte(1);
buff.discardFirstBytes(2);
if (verbose & NCP_DEBUG_LOG)
@@ -162,7 +170,7 @@ decodeControlMessage(bufferStore & buff)
{
if (verbose & NCP_DEBUG_LOG) {
if (verbose & NCP_DEBUG_DUMP)
- cout << " " << buff;
+ cout << " [" << buff << "]";
cout << endl;
}
int localChan;
@@ -174,15 +182,20 @@ decodeControlMessage(bufferStore & buff)
b.addByte(0x0);
controlChannel(localChan, NCON_MSG_CONNECT_RESPONSE, b);
+ // NOTE: we don't allow connections from the
+ // Psion to any local "processes" other than
+ // LINK.* - Matt might need to change this for
+ // his NCP<->TCP/IP bridge code...
+
if (!strcmp(buff.getString(0), "LINK.*")) {
- if (gotLinkChan)
+ if (lChan)
failed = true;
if (verbose & NCP_DEBUG_LOG)
cout << "ncp: Link UP" << endl;
- channelPtr[localChan] = new linkChan(this);
- channelPtr[localChan]->setNcpChannel(localChan);
- channelPtr[localChan]->ncpConnectAck();
- gotLinkChan = true;
+ channelPtr[localChan] = lChan = new linkChan(this);
+ lChan->setNcpChannel(localChan);
+ lChan->ncpConnectAck();
+ lChan->setVerbose(verbose);
} else {
if (verbose & NCP_DEBUG_LOG)
cout << "ncp: Link DOWN" << endl;
@@ -196,7 +209,7 @@ decodeControlMessage(bufferStore & buff)
{
int forChan = buff.getByte(0);
if (verbose & NCP_DEBUG_LOG)
- cout << "ch=" << forChan << " stat=";
+ cout << " ch=" << forChan << " stat=";
if (buff.getByte(1) == 0) {
if (verbose & NCP_DEBUG_LOG)
cout << "OK" << endl;
@@ -205,28 +218,43 @@ decodeControlMessage(bufferStore & buff)
channelPtr[forChan]->ncpConnectAck();
} else {
if (verbose & NCP_DEBUG_LOG)
- cout << "ncp: message for unknown channel\n";
+ cout << "ncp: message for unknown channel" << endl;
}
} else {
if (verbose & NCP_DEBUG_LOG)
cout << "Unknown " << (int) buff.getByte(1) << endl;
- channelPtr[forChan]->ncpConnectTerminate();
+ channelPtr[forChan]->ncpConnectNak();
}
}
break;
case NCON_MSG_NCP_INFO:
- if (buff.getByte(0) == 6) {
+ ver = buff.getByte(0);
+ // Series 3c returns '3', as does mclink. PsiWin 1.1
+ // returns version 2. We return whatever version we're
+ // sent, which is rather crude, but works for Series 3
+ // and probably 5. If Symbian have changed EPOC Connect
+ // for the Series 5mx/7, this may need to change.
+ //
+ if (ver == PV_SERIES_5 || ver == PV_SERIES_3) {
bufferStore b;
+ protocolVersion = ver;
if (verbose & NCP_DEBUG_LOG) {
if (verbose & NCP_DEBUG_DUMP)
- cout << " " << buff;
+ cout << " [" << buff << "]";
cout << endl;
}
- b.addByte(6);
- b.addDWord(0);
+ // Fake NCP version 2 for a Series 3 (behave like PsiWin 1.1)
+ if (ver == PV_SERIES_3)
+ ver = 2;
+ b.addByte(ver);
+ // Do we send a time of 0 or a real time?
+ // The Psion uses this to determine whether to
+ // restart. (See protocol docs for details)
+ // b.addDWord(0);
+ b.addDWord(time(NULL));
controlChannel(0, NCON_MSG_NCP_INFO, b);
} else
- cout << "ALERT!!!! Protocol-Version is NOT 6!! (No Series 5?)!" << endl;
+ cout << "ALERT!!!! Unexpected Protocol Version!! (No Series 5/3?)!" << endl;
break;
case NCON_MSG_CHANNEL_DISCONNECT:
if (verbose & NCP_DEBUG_LOG)
@@ -240,7 +268,7 @@ decodeControlMessage(bufferStore & buff)
default:
if (verbose & NCP_DEBUG_LOG) {
if (verbose & NCP_DEBUG_DUMP)
- cout << " " << buff;
+ cout << " [" << buff << "]";
cout << endl;
}
}
@@ -249,24 +277,53 @@ decodeControlMessage(bufferStore & buff)
int ncp::
getFirstUnusedChan()
{
- for (int cNum = 1; cNum < 8; cNum++) {
+ for (int cNum = 1; cNum < MAX_CHANNEL; cNum++) {
if (channelPtr[cNum] == NULL) {
+ if (verbose & NCP_DEBUG_LOG)
+ cout << "ncp: getFirstUnusedChan=" << cNum << endl;
return cNum;
}
}
return 0;
}
+void ncp::
+RegisterAck(int chan)
+{
+ if (verbose & NCP_DEBUG_LOG)
+ cout << "ncp: RegisterAck: chan=" << chan << endl;
+ for (int cNum = 1; cNum < MAX_CHANNEL; cNum++) {
+ channel *ch = channelPtr[cNum];
+ if (ch->getNcpChannel() == chan) {
+ ch->ncpRegisterAck();
+ return;
+ }
+ }
+ cerr << "ncp: RegisterAck: no channel to deliver" << endl;
+}
+
+void ncp::
+Register(channel * ch)
+{
+ if (lChan)
+ lChan->Register(ch);
+ else
+ cerr << "ncp: Register without established lChan" << endl;
+}
+
int ncp::
connect(channel * ch)
{
// look for first unused chan
- int cNum = getFirstUnusedChan();
+ int cNum = ch->getNcpChannel();
+ if (cNum == 0)
+ cNum = getFirstUnusedChan();
if (cNum > 0) {
channelPtr[cNum] = ch;
ch->setNcpChannel(cNum);
bufferStore b;
b.addString(ch->getNcpConnectName());
+ b.addString(".*");
b.addByte(0);
controlChannel(cNum, NCON_MSG_CONNECT_TO_SERVER, b);
return cNum;
@@ -304,6 +361,8 @@ void ncp::
disconnect(int channel)
{
channelPtr[channel]->terminateWhenAsked();
+ if (verbose & NCP_DEBUG_LOG)
+ cout << "ncp: disconnect: channel=" << channel << endl;
channelPtr[channel] = NULL;
bufferStore b;
b.addByte(remoteChanList[channel]);
@@ -327,7 +386,7 @@ hasFailed()
bool ncp::
gotLinkChannel()
{
- return gotLinkChan;
+ return (lChan != NULL);
}
char *ncp::
diff --git a/ncpd/ncp.h b/ncpd/ncp.h
index f24edc6..c71fdc1 100644
--- a/ncpd/ncp.h
+++ b/ncpd/ncp.h
@@ -27,12 +27,14 @@
#include "bool.h"
#include "bufferstore.h"
+#include "linkchan.h"
class link;
class channel;
class IOWatch;
#define NCP_DEBUG_LOG 1
#define NCP_DEBUG_DUMP 2
+#define MAX_CHANNEL 8
class ncp {
public:
@@ -40,6 +42,8 @@ class ncp {
~ncp();
int connect(channel *c); // returns channel, or -1 if failure
+ void Register(channel *c);
+ void RegisterAck(int);
void disconnect(int channel);
void send(int channel, bufferStore &a);
void poll();
@@ -53,6 +57,7 @@ class ncp {
short int getLinkVerbose();
void setPktVerbose(short int);
short int getPktVerbose();
+ short int getProtocolVersion();
private:
enum c { MAX_LEN = 200, LAST_MESS = 1, NOT_LAST_MESS = 2 };
@@ -67,6 +72,7 @@ class ncp {
NCON_MSG_CHANNEL_DISCONNECT=7,
NCON_MSG_NCP_END=8
};
+ enum protocolVersionType { PV_SERIES_5 = 6, PV_SERIES_3 = 3 };
int getFirstUnusedChan();
void decodeControlMessage(bufferStore &buff);
void controlChannel(int chan, enum interControllerMessageType t, bufferStore &command);
@@ -74,11 +80,12 @@ class ncp {
link *l;
unsigned short verbose;
- channel *channelPtr[8];
- bufferStore messageList[8];
- int remoteChanList[8];
- bool gotLinkChan;
+ channel *channelPtr[MAX_CHANNEL+1];
+ bufferStore messageList[MAX_CHANNEL+1];
+ int remoteChanList[MAX_CHANNEL+1];
bool failed;
+ short int protocolVersion;
+ linkChan *lChan;
};
#endif
diff --git a/ncpd/packet.cc b/ncpd/packet.cc
index 8099bb9..26823c8 100644
--- a/ncpd/packet.cc
+++ b/ncpd/packet.cc
@@ -33,6 +33,7 @@
#include <iomanip.h>
#include <errno.h>
#include <sys/ioctl.h>
+#include <termios.h>
extern "C" {
#include "mp_serial.h"
@@ -170,6 +171,10 @@ get(unsigned char &type, bufferStore & ret)
}
if (res < 0)
return false;
+ // XXX Solaris returns 0 on non blocking TTY lines
+ // even when VMIN > 0
+ if( res == 0 && inLen == 0 )
+ return false;
if (inLen >= BUFFERLEN) {
cerr << "packet: input buffer overflow!!!!" << endl;
inLen = 0;
@@ -256,13 +261,17 @@ linkFailed()
int res = ioctl(fd, TIOCMGET, &arg);
if (res < 0)
failed = true;
- if (verbose & PKT_DEBUG_DUMP)
+ if (verbose & PKT_DEBUG_HANDSHAKE)
cout << "packet: DTR:" << ((arg & TIOCM_DTR)?1:0)
<< " RTS:" << ((arg & TIOCM_RTS)?1:0)
<< " DCD:" << ((arg & TIOCM_CAR)?1:0)
<< " DSR:" << ((arg & TIOCM_DSR)?1:0)
<< " CTS:" << ((arg & TIOCM_CTS)?1:0) << endl;
+#ifdef sun
+ if ((arg & TIOCM_CTS) == 0)
+#else
if (((arg & TIOCM_DSR) == 0) || ((arg & TIOCM_CTS) == 0))
+#endif
failed = true;
if ((verbose & PKT_DEBUG_LOG) && failed)
cout << "packet: linkFAILED\n";
diff --git a/ncpd/packet.h b/ncpd/packet.h
index 77ca4e9..26d4282 100644
--- a/ncpd/packet.h
+++ b/ncpd/packet.h
@@ -34,6 +34,7 @@ class IOWatch;
#define PKT_DEBUG_LOG 1
#define PKT_DEBUG_DUMP 2
+#define PKT_DEBUG_HANDSHAKE 4
class packet {
public:
@@ -63,7 +64,7 @@ class packet {
int outLen;
int termLen;
int fd;
- bool verbose;
+ short int verbose;
bool esc;
char *devname;
int baud;
diff --git a/ncpd/socketchan.cc b/ncpd/socketchan.cc
index d78d3b6..a7d612e 100644
--- a/ncpd/socketchan.cc
+++ b/ncpd/socketchan.cc
@@ -39,6 +39,7 @@ iow(_iow)
{
skt = _skt;
connectName = 0;
+ connectTry = 0;
iow.addIO(skt->socket());
connected = false;
}
@@ -61,12 +62,63 @@ ncpDataCallback(bufferStore & a)
cerr << "socketchan: Connect without name!!!\n";
}
-const char *socketChan::
+char *socketChan::
getNcpConnectName()
{
return connectName;
}
+// NCP Command processing
+bool socketChan::
+ncpCommand(bufferStore & a)
+{
+cerr << "socketChan:: received NCP command (" << a << ")" << endl;
+ // str is guaranteed to begin with NCP$, and all NCP commands are
+ // greater than or equal to 8 characters in length.
+ const char *str = a.getString();
+ // unsigned long len = a.getLen();
+ bool ok = false;
+
+ if (!strncmp(str+4, "INFO", 4)) {
+ // Send information discovered during the receipt of the
+ // NCON_MSG_NCP_INFO message.
+ a.init();
+ switch (ncpProtocolVersion()) {
+ case PV_SERIES_3:
+ a.addStringT("Series 3");
+ break;
+ case PV_SERIES_5:
+ a.addStringT("Series 5");
+ break;
+ default:
+ cerr << "ncpd: protocol version not known" << endl;
+ a.addStringT("Unknown!");
+ break;
+ }
+ skt->sendBufferStore(a);
+ ok = true;
+ } else if (!strncmp(str+4, "CONN", 4)) {
+ // Connect to a channel that was placed in 'pending' mode, by
+ // checking the channel table against the ID...
+ // DO ME LATER
+ ok = true;
+ } else if (!strncmp(str+4, "CHAL", 4)) {
+ // Challenge
+ // The idea is that the channel stays in 'secure' mode until a
+ // valid RESP is received
+ // DO ME LATER
+ ok = true;
+ } else if (!strncmp(str+4, "RESP", 4)) {
+ // Reponse - here is the plaintext as sent in the CHAL - the
+ // channel will only open up if this matches what ncpd has for
+ // the encrypted plaintext.
+ // DO ME LATER
+ ok = true;
+ }
+ return ok;
+}
+
+
void socketChan::
ncpConnectAck()
{
@@ -74,24 +126,77 @@ ncpConnectAck()
a.addStringT("Ok");
skt->sendBufferStore(a);
connected = true;
+ connectTry = 3;
}
void socketChan::
ncpConnectTerminate()
{
bufferStore a;
+ connectTry = 0;
a.addStringT("Close");
skt->sendBufferStore(a);
terminateWhenAsked();
}
void socketChan::
+ncpRegisterAck()
+{
+ connectTry++;
+ ncpConnect();
+}
+
+void socketChan::
+ncpConnectNak()
+{
+ if (!connectName || (connectTry > 1))
+ ncpConnectTerminate();
+ else {
+ connectTry++;
+ ncpRegister();
+ }
+}
+
+void socketChan::
socketPoll()
{
if (connectName == 0) {
bufferStore a;
if (skt->getBufferStore(a, false) == 1) {
+ // A client has connected, and is announcing who it
+ // is... e.g. "SYS$RFSV.*"
+ //
+ // An NCP Channel can be in 'Control' or 'Data' mode.
+ // Initially, it is in 'Control' mode, and can accept
+ // certain commands.
+ //
+ // When a command is received that ncpd does not
+ // understand, this is assumed to be a request to
+ // connect to the remote service of that name, and enter
+ // 'data' mode.
+ //
+ // Later, there might be an explicit command to enter
+ // 'data' mode, and also a challenge-response protocol
+ // before any connection can be made.
+ //
+ // All commands begin with "NCP$".
+
+ // There is a magic process name called "NCP$INFO.*"
+ // which is announced by the rfsvfactory. This causes a
+ // response to be issued containing the NCP version
+ // number. The rfsvfactory will create the correct type
+ // of RFSV protocol handler, which will then announce
+ // itself. So, first time in here, we might get the
+ // NCP$INFO.*
+ if (a.getLen() > 8 && !strncmp(a.getString(), "NCP$", 4)) {
+ if (!ncpCommand(a))
+ cerr << "ncpd: command " << a << " unrecognised." << endl;
+ return;
+ }
+
+ // This isn't a command, it's a remote process. Connect.
connectName = strdup(a.getString());
+ connectTry++;
ncpConnect();
}
} else if (connected) {
diff --git a/ncpd/socketchan.h b/ncpd/socketchan.h
index e352b36..5fe7a13 100644
--- a/ncpd/socketchan.h
+++ b/ncpd/socketchan.h
@@ -36,17 +36,23 @@ public:
virtual ~socketChan();
void ncpDataCallback(bufferStore& a);
- const char* getNcpConnectName();
+ char* getNcpConnectName();
void ncpConnectAck();
+ void ncpRegisterAck();
+ void ncpDoRegisterAck(int) {}
void ncpConnectTerminate();
+ void ncpConnectNak();
bool isConnected() const;
void socketPoll();
private:
+ enum protocolVersionType { PV_SERIES_5 = 6, PV_SERIES_3 = 3 };
+ bool ncpCommand(bufferStore &a);
ppsocket* skt;
IOWatch &iow;
char* connectName;
bool connected;
+ int connectTry;
};
#endif
diff --git a/plpftp/ftp.cc b/plpftp/ftp.cc
index 2341ce5..45ec2eb 100644
--- a/plpftp/ftp.cc
+++ b/plpftp/ftp.cc
@@ -32,10 +32,12 @@
#include <unistd.h>
#include <sys/time.h>
#include <sys/stat.h>
+#include <signal.h>
#include "defs.h"
#include "ftp.h"
-#include "rfsv32.h"
+#include "rfsv.h"
+#include "rpcs.h"
#include "bufferarray.h"
#include "bufferstore.h"
@@ -49,6 +51,12 @@ extern "C" {
}
#endif
+static char psionDir[1024];
+static rfsv *comp_a;
+static rpcs *comp_r;
+static int continueRunning;
+
+
void ftp::
resetUnixPwd()
{
@@ -59,8 +67,6 @@ resetUnixPwd()
ftp::ftp()
{
resetUnixPwd();
- strcpy(psionDir, DEFAULT_DRIVE);
- strcat(psionDir, DEFAULT_BASE_DIRECTORY);
}
ftp::~ftp()
@@ -68,29 +74,33 @@ ftp::~ftp()
}
void ftp::usage() {
- cerr << "Unknown command" << endl;
- cerr << " pwd" << endl;
- cerr << " ren <oldname> <newname>" << endl;
- cerr << " touch <psionfile>" << endl;
- cerr << " gtime <psionfile>" << endl;
- cerr << " test <psionfile>" << endl;
- cerr << " gattr <psionfile>" << endl;
- cerr << " sattr [[-|+]rhsa] <psionfile>" << endl;
- cerr << " devs" << endl;
- cerr << " dir|ls" << endl;
- cerr << " dircnt" << endl;
- cerr << " cd <dir>" << endl;
- cerr << " lcd <dir>" << endl;
- cerr << " !<system command>" << endl;
- cerr << " get <psionfile>" << endl;
- cerr << " put <unixfile>" << endl;
- cerr << " mget <shellpattern>" << endl;
- cerr << " mput <shellpattern>" << endl;
- cerr << " del|rm <psionfile>" << endl;
- cerr << " mkdir <psiondir>" << endl;
- cerr << " rmdir <psiondir>" << endl;
- cerr << " prompt" << endl;
- cerr << " bye" << endl;
+ cout << "Known FTP commands:" << endl << endl;
+ cout << " pwd" << endl;
+ cout << " ren <oldname> <newname>" << endl;
+ cout << " touch <psionfile>" << endl;
+ cout << " gtime <psionfile>" << endl;
+ cout << " test <psionfile>" << endl;
+ cout << " gattr <psionfile>" << endl;
+ cout << " sattr [[-|+]rhsa] <psionfile>" << endl;
+ cout << " devs" << endl;
+ cout << " dir|ls" << endl;
+ cout << " dircnt" << endl;
+ cout << " cd <dir>" << endl;
+ cout << " lcd <dir>" << endl;
+ cout << " !<system command>" << endl;
+ cout << " get <psionfile>" << endl;
+ cout << " put <unixfile>" << endl;
+ cout << " mget <shellpattern>" << endl;
+ cout << " mput <shellpattern>" << endl;
+ cout << " del|rm <psionfile>" << endl;
+ cout << " mkdir <psiondir>" << endl;
+ cout << " rmdir <psiondir>" << endl;
+ cout << " prompt" << endl;
+ cout << " hash" << endl;
+ cout << " bye" << endl;
+ cout << endl << "Known RPC commands:" << endl << endl;
+ cout << " ps" << endl;
+ cout << " kill <pid|'all'>" << endl;
}
static int Wildmat(const char *s, char *p);
@@ -146,8 +156,36 @@ Wildmat(const char *s, char *p)
return (*s == '\0');
}
+static int
+checkAbortNoHash(long)
+{
+ return continueRunning;
+}
+
+static int
+checkAbortHash(long)
+{
+ if (continueRunning) {
+ printf("#"); fflush(stdout);
+ }
+ return continueRunning;
+}
+
+static void
+sigint_handler(int i) {
+ continueRunning = 0;
+ signal(SIGINT, sigint_handler);
+}
+
+static void
+sigint_handler2(int i) {
+ continueRunning = 0;
+ fclose(stdin);
+ signal(SIGINT, sigint_handler2);
+}
+
int ftp::
-session(rfsv32 & a, int xargc, char **xargv)
+session(rfsv & a, rpcs & r, int xargc, char **xargv)
{
int argc;
char *argv[10];
@@ -155,6 +193,8 @@ session(rfsv32 & a, int xargc, char **xargv)
char f2[256];
long res;
bool prompt = true;
+ bool hash = false;
+ cpCallback_t cab = checkAbortNoHash;
bool once = false;
if (xargc > 1) {
@@ -163,15 +203,107 @@ session(rfsv32 & a, int xargc, char **xargv)
for (int i = 0; i < argc; i++)
argv[i] = xargv[i+1];
}
+ if (!once) {
+ bufferArray b;
+ if (!r.getOwnerInfo(b)) {
+ int machType;
+ r.getMachineType(machType);
+ cout << "Connected to ";
+ switch (machType) {
+ case rpcs::PSI_MACH_UNKNOWN:
+ cout << "an unknown Device";
+ break;
+ case rpcs::PSI_MACH_PC:
+ cout << "a PC";
+ break;
+ case rpcs::PSI_MACH_MC:
+ cout << "a MC";
+ break;
+ case rpcs::PSI_MACH_HC:
+ cout << "a HC";
+ break;
+ case rpcs::PSI_MACH_S3:
+ cout << "a Serie 3";
+ break;
+ case rpcs::PSI_MACH_S3A:
+ cout << "a Series 3a, 3c or 3mx";
+ break;
+ case rpcs::PSI_MACH_WORKABOUT:
+ cout << "a Workabout";
+ break;
+ case rpcs::PSI_MACH_SIENNA:
+ cout << "a Sienna";
+ break;
+ case rpcs::PSI_MACH_S3C:
+ cout << "a Series 3c";
+ break;
+ case rpcs::PSI_MACH_S5:
+ cout << "a Series 5";
+ break;
+ case rpcs::PSI_MACH_WINC:
+ cout << "a WinC";
+ break;
+ default:
+ cout << "an undefined Device";
+ break;
+ }
+ cout << ", OwnerInfo:" << endl;
+ while (!b.empty())
+ cout << " " << b.pop().getString() << endl;
+ cout << endl;
+ }
+ }
+
+ if (!strcmp(DDRIVE, "AUTO")) {
+ long devbits;
+ long vtotal, vfree, vattr, vuniqueid;
+ int i;
+
+ strcpy(defDrive, "::");
+ if (a.devlist(&devbits) == 0) {
+
+ for (i = 0; i < 26; i++) {
+ if ((devbits & 1) && a.devinfo(i, &vfree, &vtotal, &vattr, &vuniqueid)) {
+ defDrive[0] = 'A' + i;
+ break;
+ }
+ devbits >>= 1;
+ }
+ }
+ if (!strcmp(defDrive, "::")) {
+ cerr << "FATAL: Couln't find default Drive" << endl;
+ return -1;
+ }
+ } else
+ strcpy(defDrive, DDRIVE);
+ strcpy(psionDir, defDrive);
+ strcat(psionDir, DBASEDIR);
+ comp_a = &a;
+ if (!once) {
+ cout << "Psion dir is: \"" << psionDir << "\"" << endl;
+ initReadline();
+ }
+ continueRunning = 1;
+ signal(SIGINT, sigint_handler);
do {
if (!once)
getCommand(argc, argv);
+ if (!strcmp(argv[0], "help")) {
+ usage();
+ continue;
+ }
if (!strcmp(argv[0], "prompt")) {
prompt = !prompt;
cout << "Prompting now " << (prompt?"on":"off") << endl;
continue;
}
+ if (!strcmp(argv[0], "hash")) {
+ hash = !hash;
+ cout << "Hash printing now " << (hash?"on":"off") << endl;
+ cab = (hash) ? checkAbortHash : checkAbortNoHash;
+ continue;
+ }
if (!strcmp(argv[0], "pwd")) {
cout << "Local dir: \"" << localDir << "\"" << endl;
cout << "Psion dir: \"" << psionDir << "\"" << endl;
@@ -199,6 +331,17 @@ session(rfsv32 & a, int xargc, char **xargv)
strcat(f1, argv[1]);
if ((res = a.fgeteattr(f1, &attr, &size, &time)) != 0)
errprint(res, a);
+ else {
+ // never used to do this
+ char dateBuff[100];
+ struct tm *t;
+ t = localtime(&time);
+ strftime(dateBuff, 100, "%c", t);
+ cout << a.opAttr(attr);
+ cout << " " << dec << setw(10) << setfill(' ') << size;
+ cout << " " << dateBuff;
+ cout << " " << argv[1] << endl;
+ }
continue;
}
if (!strcmp(argv[0], "gattr") && (argc == 2)) {
@@ -207,11 +350,13 @@ session(rfsv32 & a, int xargc, char **xargv)
strcat(f1, argv[1]);
if ((res = a.fgetattr(f1, &attr)) != 0)
errprint(res, a);
- else
- cout << hex << setw(4) << setfill('0') << attr << endl;
+ else {
+ cout << hex << setw(4) << setfill('0') << attr;
+ cout << " (" << a.opAttr(attr) << ")" << endl;
+ }
continue;
}
- if (!strcmp(argv[0], "gtime")) {
+ if (!strcmp(argv[0], "gtime") && (argc == 2)) {
long mtime;
strcpy(f1, psionDir);
strcat(f1, argv[1]);
@@ -226,7 +371,7 @@ session(rfsv32 & a, int xargc, char **xargv)
}
continue;
}
- if (!strcmp(argv[0], "sattr")) {
+ if (!strcmp(argv[0], "sattr") && (argc == 2)) {
long attr[2];
int aidx = 0;
char *p = argv[1];
@@ -287,7 +432,8 @@ session(rfsv32 & a, int xargc, char **xargv)
if (vname != NULL) {
cout << (char) ('A' + i) << " " <<
hex << setw(4) << setfill('0') << vattr << " " <<
- setw(12) << setfill(' ') << setiosflags(ios::left) << vname << resetiosflags(ios::left) << dec << setw(9) <<
+ setw(12) << setfill(' ') << setiosflags(ios::left) <<
+ vname << resetiosflags(ios::left) << dec << setw(9) <<
vtotal << setw(9) << vfree << setw(10) << vuniqueid << endl;
free(vname);
}
@@ -298,14 +444,14 @@ session(rfsv32 & a, int xargc, char **xargv)
errprint(res, a);
continue;
}
- if ((!strcmp(argv[0], "ls")) || (!strcmp(argv[0], "dir"))) {
+ if (!strcmp(argv[0], "ls") || !strcmp(argv[0], "dir")) {
bufferArray files;
if ((res = a.dir(psionDir, &files)) != 0)
errprint(res, a);
else
while (!files.empty()) {
bufferStore s;
- s = files.popBuffer();
+ s = files.pop();
long date = s.getDWord(0);
long size = s.getDWord(4);
long attr = s.getDWord(8);
@@ -313,15 +459,7 @@ session(rfsv32 & a, int xargc, char **xargv)
struct tm *t;
t = localtime(&date);
strftime(dateBuff, 100, "%c", t);
- cout << ((attr & rfsv32::PSI_ATTR_DIRECTORY) ? "d" : "-");
- cout << ((attr & rfsv32::PSI_ATTR_RONLY) ? "-" : "w");
- cout << ((attr & rfsv32::PSI_ATTR_HIDDEN) ? "h" : "-");
- cout << ((attr & rfsv32::PSI_ATTR_SYSTEM) ? "s" : "-");
- cout << ((attr & rfsv32::PSI_ATTR_ARCHIVE) ? "a" : "-");
- cout << ((attr & rfsv32::PSI_ATTR_VOLUME) ? "v" : "-");
- cout << ((attr & rfsv32::PSI_ATTR_NORMAL) ? "n" : "-");
- cout << ((attr & rfsv32::PSI_ATTR_TEMPORARY) ? "t" : "-");
- cout << ((attr & rfsv32::PSI_ATTR_COMPRESSED) ? "c" : "-");
+ cout << a.opAttr(attr);
cout << " " << dec << setw(10) << setfill(' ') << size;
cout << " " << dateBuff;
cout << " " << s.getString(12) << endl;
@@ -332,9 +470,10 @@ session(rfsv32 & a, int xargc, char **xargv)
if (argc == 1)
resetUnixPwd();
else {
- if (chdir(argv[1]) == 0)
- strcpy(localDir, argv[1]);
- else
+ if (chdir(argv[1]) == 0) {
+ getcwd(localDir, sizeof(localDir));
+ strcat(localDir, "/");
+ } else
cerr << "No such directory" << endl
<< "Keeping original directory \"" << localDir << "\"" << endl;
}
@@ -342,8 +481,8 @@ session(rfsv32 & a, int xargc, char **xargv)
}
if (!strcmp(argv[0], "cd")) {
if (argc == 1) {
- strcpy(psionDir, DEFAULT_DRIVE);
- strcat(psionDir, DEFAULT_BASE_DIRECTORY);
+ strcpy(psionDir, defDrive);
+ strcat(psionDir, DBASEDIR);
} else {
long tmp;
if (!strcmp(argv[1], "..")) {
@@ -369,10 +508,16 @@ session(rfsv32 & a, int xargc, char **xargv)
}
if ((f1[strlen(f1) -1] != '/') && (f1[strlen(f1) -1] != '\\'))
strcat(f1,"\\");
- if ((res = a.dircount(f1, &tmp)) == 0)
+ if ((res = a.dircount(f1, &tmp)) == 0) {
+ for (char *p = f1; *p; p++)
+ if (*p == '/')
+ *p = '\\';
strcpy(psionDir, f1);
- else
+ }
+ else {
+ errprint(res, a);
cerr << "Keeping original directory \"" << psionDir << "\"" << endl;
+ }
}
continue;
}
@@ -389,9 +534,14 @@ session(rfsv32 & a, int xargc, char **xargv)
else
strcat(f2, argv[2]);
gettimeofday(&stime, 0L);
- if ((res = a.copyFromPsion(f1, f2)) != 0)
+ if ((res = a.copyFromPsion(f1, f2, cab)) != 0) {
+ if (hash)
+ cout << endl;
+ continueRunning = 1;
errprint(res, a);
- else {
+ } else {
+ if (hash)
+ cout << endl;
gettimeofday(&etime, 0L);
long dsec = etime.tv_sec - stime.tv_sec;
long dhse = (etime.tv_usec / 10000) -
@@ -419,7 +569,7 @@ session(rfsv32 & a, int xargc, char **xargv)
}
while (!files.empty()) {
bufferStore s;
- s = files.popBuffer();
+ s = files.pop();
char temp[100];
long attr = s.getDWord(8);
@@ -441,23 +591,29 @@ session(rfsv32 & a, int xargc, char **xargv)
} while (temp[1] != 0 || (temp[0] != 'y' && temp[0] != 'n'));
if (temp[0] != 'n') {
strcpy(f1, psionDir);
- strcat(f1, s.getString());
+ strcat(f1, s.getString(12));
strcpy(f2, localDir);
- strcat(f2, s.getString());
+ strcat(f2, s.getString(12));
if (temp[0] == 'l') {
for (char *p = f2; *p; p++)
*p = tolower(*p);
}
- if ((res = a.copyFromPsion(f1, f2)) != 0) {
+ if ((res = a.copyFromPsion(f1, f2, cab)) != 0) {
+ if (hash)
+ cout << endl;
+ continueRunning = 1;
errprint(res, a);
break;
- } else
+ } else {
+ if (hash)
+ cout << endl;
cout << "Transfer complete\n";
+ }
}
}
continue;
}
- if (!strcmp(argv[0], "put")) {
+ if (!strcmp(argv[0], "put") && (argc >= 2)) {
struct timeval stime;
struct timeval etime;
struct stat stbuf;
@@ -470,9 +626,14 @@ session(rfsv32 & a, int xargc, char **xargv)
else
strcat(f2, argv[2]);
gettimeofday(&stime, 0L);
- if ((res = a.copyToPsion(f1, f2)) != 0)
+ if ((res = a.copyToPsion(f1, f2, cab)) != 0) {
+ if (hash)
+ cout << endl;
+ continueRunning = 1;
errprint(res, a);
- else {
+ } else {
+ if (hash)
+ cout << endl;
gettimeofday(&etime, 0L);
long dsec = etime.tv_sec - stime.tv_sec;
long dhse = (etime.tv_usec / 10000) -
@@ -526,11 +687,17 @@ session(rfsv32 & a, int xargc, char **xargv)
if (temp[0] == 'y') {
strcpy(f2, psionDir);
strcat(f2, de->d_name);
- if ((res = a.copyToPsion(f1, f2)) != 0) {
+ if ((res = a.copyToPsion(f1, f2, cab)) != 0) {
+ if (hash)
+ cout << endl;
+ continueRunning = 1;
errprint(res, a);
break;
- } else
+ } else {
+ if (hash)
+ cout << endl;
cout << "Transfer complete\n";
+ }
}
}
} while (de);
@@ -539,22 +706,22 @@ session(rfsv32 & a, int xargc, char **xargv)
cerr << "Error in directory name \"" << localDir << "\"\n";
continue;
}
- if (!strcmp(argv[0], "del") ||
- !strcmp(argv[0], "rm")) {
+ if ((!strcmp(argv[0], "del") ||
+ !strcmp(argv[0], "rm")) && (argc == 2)) {
strcpy(f1, psionDir);
strcat(f1, argv[1]);
if ((res = a.remove(f1)) != 0)
errprint(res, a);
continue;
}
- if (!strcmp(argv[0], "mkdir")) {
+ if (!strcmp(argv[0], "mkdir") && (argc == 2)) {
strcpy(f1, psionDir);
strcat(f1, argv[1]);
if ((res = a.mkdir(f1)) != 0)
errprint(res, a);
continue;
}
- if (!strcmp(argv[0], "rmdir")) {
+ if (!strcmp(argv[0], "rmdir") && (argc == 2)) {
strcpy(f1, psionDir);
strcat(f1, argv[1]);
if ((res = a.rmdir(f1)) != 0)
@@ -568,79 +735,274 @@ session(rfsv32 & a, int xargc, char **xargv)
strcat(cmd, " ");
strcat(cmd, argv[i]);
}
- system(cmd);
+ if (strlen(cmd))
+ system(cmd);
+ else {
+ char *sh;
+ cout << "Starting subshell ...\n";
+ sh = getenv("SHELL");
+ if (!sh)
+ sh = "/bin/sh";
+ system(sh);
+ }
+ continue;
+ }
+ // RPCS commands
+ // if (!strcmp(argv[0], "xxx")) {
+ // r.configOpen();
+ // continue;
+ // }
+ if (!strcmp(argv[0], "run") && (argc >= 2)) {
+ char argbuf[1024];
+ char cmdbuf[1024];
+
+ argbuf[0] = 0;
+ for (int i = 2; i < argc; i++) {
+ if (i > 2) {
+ strcat(argbuf, " ");
+ strcat(argbuf, argv[i]);
+ } else
+ strcpy(argbuf, argv[i]);
+ }
+ if (argv[1][1] != ':') {
+ strcpy(cmdbuf, psionDir);
+ strcat(cmdbuf, argv[1]);
+ } else
+ strcpy(cmdbuf, argv[1]);
+ r.execProgram(cmdbuf, argbuf);
+ continue;
+ }
+ if (!strcmp(argv[0], "kill") && (argc >= 2)) {
+ bufferArray tmp, tmp2;
+ bool anykilled = false;
+ r.queryDrive('C', tmp);
+ tmp2 = tmp;
+ for (int i = 1; i < argc; i++) {
+ int kpid;
+ tmp = tmp2;
+ if (!strcmp(argv[i], "all"))
+ kpid = -1;
+ else
+ sscanf(argv[i], "%d", &kpid);
+ while (!tmp.empty()) {
+ bufferStore bs = tmp.pop();
+ tmp.pop();
+ int pid = bs.getWord(0);
+ const char *proc = bs.getString(2);
+ if (kpid == -1 || kpid == pid) {
+ char pbuf[128];
+ sprintf(pbuf, "%s.$%d", proc, pid);
+ r.stopProgram(pbuf);
+ anykilled = true;
+ }
+ }
+ if (kpid == -1)
+ break;
+ }
+ if (!anykilled)
+ cerr << "no such process" << endl;
+ continue;
+ }
+ if (!strcmp(argv[0], "ps")) {
+ bufferArray tmp;
+ r.queryDrive('C', tmp);
+ cout << "PID CMD ARGS" << endl;
+ while (!tmp.empty()) {
+ bufferStore bs = tmp.pop();
+ bufferStore bs2 = tmp.pop();
+ int pid = bs.getWord(0);
+ const char *proc = bs.getString(2);
+ const char *arg = bs2.getString();
+
+ printf("%5d %-12s %s\n", pid, proc, arg);
+ }
continue;
}
if (strcmp(argv[0], "bye") && strcmp(argv[0], "quit"))
- usage();
- } while (strcmp(argv[0], "bye") && strcmp(argv[0], "quit") && !once);
+ cerr << "syntax error. Try \"help\"" << endl;
+ } while (strcmp(argv[0], "bye") && strcmp(argv[0], "quit") && !once &&
+ continueRunning);
return a.getStatus();
}
void ftp::
-errprint(long errcode, rfsv32 & a) {
+errprint(long errcode, rfsv & a) {
cerr << "Error: " << a.opErr(errcode) << endl;
}
-int ftp::
-convertName(const char *orig, char *retVal)
+#if HAVE_LIBREADLINE
+static char *all_commands[] = {
+ "pwd", "ren", "touch", "gtime", "test", "gattr", "sattr", "devs",
+ "dir", "ls", "dircnt", "cd", "lcd", "get", "put", "mget", "mput",
+ "del", "rm", "mkdir", "rmdir", "prompt", "bye", "ps", "kill", "run", NULL
+};
+
+static char *localfile_commands[] = {
+ "lcd ", "put ", "mput ", NULL
+};
+
+static char *remote_dir_commands[] = {
+ "cd ", "rmdir ", NULL
+};
+
+static bufferArray *comp_files = NULL;
+static long maskAttr;
+
+static char*
+filename_generator(char *text, int state)
{
- int len = strlen(orig);
- char *temp = new char[len + 1];
-
- for (int i = 0; i <= len; i++) {
- if (orig[i] == '/')
- temp[i] = '\\';
- else
- temp[i] = orig[i];
+ static int len;
+
+
+ if (!state) {
+ long res;
+ len = strlen(text);
+ if (comp_files)
+ delete comp_files;
+ comp_files = new bufferArray();
+ if ((res = comp_a->dir(psionDir, comp_files)) != 0) {
+ cerr << "Error: " << comp_a->opErr(res) << endl;
+ return NULL;
+ }
}
- if (len == 0 || temp[1] != ':') {
- // We can automatically supply a drive letter
- strcpy(retVal, DEFAULT_DRIVE);
+ while (!comp_files->empty()) {
+ bufferStore s;
+ s = comp_files->pop();
+ long attr = s.getDWord(8);
- if (len == 0 || temp[0] != '\\') {
- strcat(retVal, DEFAULT_BASE_DIRECTORY);
- } else {
- retVal[strlen(retVal) - 1] = 0;
+ if ((attr & maskAttr) == 0)
+ continue;
+ if (!(strncmp(s.getString(12), text, len))) {
+ char fnbuf[512];
+ strcpy(fnbuf, s.getString(12));
+ if (attr & 0x10)
+ strcat(fnbuf, "/");
+ return (strdup(fnbuf));
}
+ }
+ return NULL;
+}
- strcat(retVal, temp);
- } else {
- strcpy(retVal, temp);
+static char *
+command_generator(char *text, int state)
+{
+ static int idx, len;
+ char *name;
+
+ if (!state) {
+ idx = 0;
+ len = strlen(text);
}
- delete[]temp;
+ while ((name = all_commands[idx])) {
+ idx++;
+ if (!strncmp(name, text, len))
+ return (strdup(name));
+ }
+ return NULL;
+}
+
+static int
+null_completion() {
return 0;
}
+static char **
+do_completion(char *text, int start, int end)
+{
+ char **matches = NULL;
+
+ rl_completion_entry_function = (Function *)null_completion;
+ if (start == 0)
+ matches = completion_matches(text, command_generator);
+ else {
+ int idx = 0;
+ char *name;
+
+ rl_filename_quoting_desired = 1;
+ while ((name = localfile_commands[idx])) {
+ idx++;
+ if (!strncmp(name, rl_line_buffer, strlen(name))) {
+ rl_completion_entry_function = NULL;
+ return NULL;
+ }
+ }
+ maskAttr = 0xffff;
+ idx = 0;
+ while ((name = remote_dir_commands[idx])) {
+ idx++;
+ if (!strncmp(name, rl_line_buffer, strlen(name)))
+ maskAttr = 0x0010;
+ }
+
+ matches = completion_matches(text, filename_generator);
+ }
+ return matches;
+}
+#endif
+
+void ftp::
+initReadline(void)
+{
+#if HAVE_LIBREADLINE
+ rl_readline_name = "plpftp";
+ rl_completion_entry_function = (Function *)null_completion;
+ rl_attempted_completion_function = (CPPFunction *)do_completion;
+#endif
+}
+
void ftp::
getCommand(int &argc, char **argv)
{
- int ws;
- char *bp;
+ int ws, quote;
static char buf[1024];
buf[0] = 0; argc = 0;
- while (!strlen(buf)) {
- bp = readline("> ");
+ while (!strlen(buf) && continueRunning) {
+ signal(SIGINT, sigint_handler2);
+#if HAVE_LIBREADLINE
+ char *bp = readline("> ");
if (!bp) {
strcpy(buf, "bye");
cout << buf << endl;
} else {
strcpy(buf, bp);
+#if HAVE_LIBHISTORY
add_history(buf);
+#endif
free(bp);
}
+#else
+ cout << "> ";
+ cout.flush();
+ cin.getline(buf, 1023);
+ if (cin.eof()) {
+ strcpy(buf, "bye");
+ cout << buf << endl;
+ }
+#endif
+ signal(SIGINT, sigint_handler);
}
- ws = 1;
+ ws = 1; quote = 0;
for (char *p = buf; *p; p++)
- if ((*p == ' ') || (*p == '\t')) {
- ws = 1;
- *p = 0;
- } else {
- if (ws)
- argv[argc++] = p;
- ws = 0;
+ switch (*p) {
+ case ' ':
+ case '\t':
+ if (!quote) {
+ ws = 1;
+ *p = 0;
+ }
+ break;
+ case '"':
+ quote = 1 - quote;
+ if (!quote)
+ *p = 0;
+ break;
+ default:
+ if (ws) {
+ argv[argc++] = p;
+ }
+ ws = 0;
}
}
diff --git a/plpftp/ftp.h b/plpftp/ftp.h
index 38edf40..a89fd62 100644
--- a/plpftp/ftp.h
+++ b/plpftp/ftp.h
@@ -27,33 +27,39 @@
#include "bool.h"
-class rfsv32;
+class rfsv;
+class rpcs;
class bufferStore;
class bufferArray;
-#define DEFAULT_DRIVE "C:"
-#define DEFAULT_BASE_DIRECTORY "\\"
-
class ftp {
public:
ftp();
~ftp();
- int session(rfsv32 & a, int xargc, char **xargv);
+ int session(rfsv & a, rpcs & r, int xargc, char **xargv);
private:
void getCommand(int &argc, char **argv);
+ void initReadline(void);
// utilities
bool unixDirExists(const char *dir);
void getUnixDir(bufferArray & files);
void resetUnixPwd();
void usage();
- void errprint(long errcode, rfsv32 & a);
+ void errprint(long errcode, rfsv & a);
void cd(const char *source, const char *cdto, char *dest);
- int convertName(const char *orig, char *retVal);
+ // MJG: note, this isn't actually used anywhere
+ int convertName(const char *orig, char *retVal);
+#ifdef HAVE_READLINE
+ char *filename_generator(char *, int);
+ char *command_generator(char *, int);
+ char **do_completion(char *, int, int);
+#endif
+ char defDrive[9];
char localDir[1024];
- char psionDir[1024];
+ // char psionDir[1024];
};
#endif
diff --git a/plpftp/main.cc b/plpftp/main.cc
index 816c58a..8d00574 100644
--- a/plpftp/main.cc
+++ b/plpftp/main.cc
@@ -31,7 +31,10 @@
#include "defs.h"
#include "bool.h"
#include "ppsocket.h"
-#include "rfsv32.h"
+#include "rfsv.h"
+#include "rfsvfactory.h"
+#include "rpcs.h"
+#include "rpcsfactory.h"
#include "ftp.h"
#include "bufferstore.h"
@@ -48,6 +51,7 @@ ftpHeader()
cout << "PLPFTP Version " << VERSION;
cout << " Copyright (C) 1999 Philip Proudman" << endl;
cout << " Additions Copyright (C) 1999 Fritz Elfert <felfert@to.com>" << endl;
+ cout << " & (C) 1999 Matt Gumbley <matt@gumbley.demon.co.uk>" << endl;
cout << "PLP comes with ABSOLUTELY NO WARRANTY;" << endl;
cout << "This is free software, and you are welcome to redistribute it" << endl;
cout << "under GPL conditions; see the COPYING file in the distribution." << endl;
@@ -59,7 +63,9 @@ int
main(int argc, char **argv)
{
ppsocket *skt;
- rfsv32 *a;
+ ppsocket *skt2;
+ rfsv *a;
+ rpcs *r;
ftp f;
int status = 0;
sigset_t sigset;
@@ -80,10 +86,26 @@ main(int argc, char **argv)
if (argc < 2)
ftpHeader();
skt = new ppsocket();
- skt->connect(NULL, sockNum);
- a = new rfsv32(skt);
- status = f.session(*a, argc, argv);
-
- delete a;
+ if (!skt->connect(NULL, sockNum)) {
+ cout << "plpftp: could not connect to ncpd" << endl;
+ return 1;
+ }
+ skt2 = new ppsocket();
+ if (!skt2->connect(NULL, sockNum)) {
+ cout << "plpftp: could not connect to ncpd" << endl;
+ return 1;
+ }
+ rfsvfactory *rf = new rfsvfactory(skt);
+ rpcsfactory *rp = new rpcsfactory(skt2);
+ a = rf->create(false);
+ r = rp->create(false);
+ if ((a != NULL) && (r != NULL)) {
+ status = f.session(*a, *r, argc, argv);
+ delete r;
+ delete a;
+ } else {
+ cout << "plpftp: could not create rfsv object" << endl;
+ status = 1;
+ }
return status;
}
diff --git a/plpnfsd/main.cc b/plpnfsd/main.cc
index 77f178a..206d902 100644
--- a/plpnfsd/main.cc
+++ b/plpnfsd/main.cc
@@ -8,10 +8,12 @@
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
+#include <syslog.h>
#include "defs.h"
#include "bool.h"
-#include "rfsv32.h"
+#include "rfsv.h"
+#include "rfsvfactory.h"
#include "bufferstore.h"
#include "bufferarray.h"
#include "ppsocket.h"
@@ -19,16 +21,30 @@ extern "C" {
#include "rfsv_api.h"
}
-static rfsv32 *a;
+static rfsv *a;
+static rfsvfactory *rf;
+static char *a_filename;
+static long a_handle;
+static long a_offset;
+static long a_openmode;
long rfsv_isalive() {
- return (a->getStatus() == 0);
+ if (!a) {
+ a = rf->create(true);
+ if (a != NULL)
+ return (a->getStatus() == 0);
+ }
+ return 0;
}
long rfsv_dir(const char *file, dentry **e) {
bufferArray entries;
dentry *tmp;
- long ret = a->dir(&(*file), &entries);
+ long ret;
+
+ if (!a)
+ return -1;
+ ret = a->dir(&(*file), &entries);
while (!entries.empty()) {
bufferStore s;
s = entries.popBuffer();
@@ -46,10 +62,14 @@ long rfsv_dir(const char *file, dentry **e) {
}
long rfsv_dircount(const char *file, long *count) {
+ if (!a)
+ return -1;
return a->dircount(&(*file), &(*count));
}
long rfsv_rmdir(const char *name) {
+ if (!a)
+ return -1;
return a->rmdir(name);
}
@@ -60,48 +80,129 @@ long rfsv_mkdir(const char *file) {
}
long rfsv_remove(const char *file) {
+ if (!a)
+ return -1;
return a->remove(file);
}
long rfsv_fclose(long handle) {
+ if (!a)
+ return -1;
return a->fclose(handle);
}
long rfsv_fopen(long attr, const char *file, long *handle) {
long ph;
- long ret = a->fopen(attr, file, ph);
+ long ret;
+
+ if (!a)
+ return -1;
+ ret = a->fopen(a->opMode(attr), file, ph);
*handle = ph;
return ret;
}
long rfsv_fcreate(long attr, const char *file, long *handle) {
long ph;
- long ret = a->fcreatefile(attr, file, ph);
+ long ret;
+
+ if (!a)
+ return -1;
+ ret = a->fcreatefile(attr, file, ph);
*handle = ph;
return ret;
}
-long rfsv_read(char *buf, long offset, long len, long handle) {
- long ret = a->fseek(handle, offset, rfsv32::PSI_SEEK_SET);
- if (ret >= 0)
- ret = a->fread(handle, buf, len);
+static long rfsv_opencached(const char *name, long mode) {
+ long ret;
+ int retry = 100;
+
+ if (!a)
+ return -1;
+ while (((ret = a->fopen(a->opMode(mode), name, a_handle))
+ == rfsv::E_PSI_GEN_INUSE) && retry--)
+ ;
+ if (ret)
+ return ret;
+ a_offset = 0;
+ a_openmode = mode;
+ a_filename = strdup(name);
return ret;
}
-long rfsv_write(char *buf, long offset, long len, long handle) {
- long ret = a->fseek(handle, offset, rfsv32::PSI_SEEK_SET);
- if (ret >= 0)
- ret = a->fwrite(handle, buf, len);
+static long rfsv_closecached() {
+ if (!a)
+ return -1;
+ if (!a_filename)
+ return 0;
+ a->fclose(a_handle);
+ free(a_filename);
+ a_filename = 0;
+ return 0;
+}
+
+long rfsv_read(char *buf, long offset, long len, char *name) {
+ // FIXME: this might break on RFSV16?
+ long ret = 0;
+
+ if (!a)
+ return -1;
+ if (!a_filename || strcmp(a_filename, name) || a_openmode != rfsv::PSI_O_RDONLY) {
+ rfsv_closecached();
+ if((ret = rfsv_opencached(name, rfsv::PSI_O_RDONLY)))
+ return ret;
+ }
+ if (a_offset != offset)
+ ret = a->fseek(a_handle, offset, rfsv::PSI_SEEK_SET);
+ if (ret >= 0) {
+ a_offset = offset;
+ ret = a->fread(a_handle, (unsigned char *)buf, len);
+ if (ret <= 0)
+ return ret;
+ a_offset += ret;
+ }
+ return ret;
+}
+
+long rfsv_write(char *buf, long offset, long len, char *name) {
+ // FIXME: this might break on RFSV16?
+ long ret = 0;
+
+ if (!a)
+ return -1;
+
+ if (!a_filename || strcmp(a_filename, name) || a_openmode != rfsv::PSI_O_RDWR) {
+ if ((ret = rfsv_closecached()))
+ return ret;
+ if ((ret = rfsv_opencached(name, rfsv::PSI_O_RDWR)))
+ return ret;
+ }
+ if (a_offset != offset)
+ ret = a->fseek(a_handle, offset, rfsv::PSI_SEEK_SET);
+ if (ret >= 0) {
+ a_offset = offset;
+ ret = a->fwrite(a_handle, (unsigned char *)buf, len);
+ if (ret <= 0)
+ return ret;
+ a_offset += ret;
+ }
return ret;
}
long rfsv_setmtime(const char *name, long time) {
+ if (!a)
+ return -1;
return a->fsetmtime(name, time);
}
long rfsv_setsize(const char *name, long size) {
long ph;
- long ret = a->fopen(rfsv32::PSI_OMODE_READ_WRITE, name, ph);
+ long ret;
+ // FIXME: this might break on RFSV16?
+
+ if (!a)
+ return -1;
+ ret = a->fopen(a->opMode(rfsv::PSI_O_RDWR), name, ph);
if (!ret) {
ret = a->fsetsize(ph, size);
a->fclose(ph);
@@ -110,10 +211,14 @@ long rfsv_setsize(const char *name, long size) {
}
long rfsv_setattr(const char *name, long sattr, long dattr) {
+ if (!a)
+ return -1;
return a->fsetattr(name, dattr, sattr);
}
long rfsv_getattr(const char *name, long *attr, long *size, long *time) {
+ if (!a)
+ return -1;
return a->fgeteattr(&(*name), &(*attr), &(*size), &(*time));
}
@@ -122,11 +227,15 @@ long rfsv_statdev(char letter) {
int devnum = letter - 'A';
char *name;
- name = a->devinfo(devnum, &vfree, &vtotal, &vattr, &vuniqueid);
+ if (!a)
+ return -1;
+ name = a->devinfo(devnum, &vfree, &vtotal, &vattr, &vuniqueid);
return (name == NULL);
}
long rfsv_rename(const char *oldname, const char *newname) {
+ if (!a)
+ return -1;
return a->rename(oldname, newname);
}
@@ -136,6 +245,8 @@ long rfsv_drivelist(int *cnt, device **dlist) {
long ret;
int i;
+ if (!a)
+ return -1;
ret = a->devlist(&devbits);
if (ret == 0)
for (i = 0; i<26; i++) {
@@ -171,6 +282,7 @@ int main(int argc, char**argv) {
char *mdir = DDIR;
int sockNum = DPORT;
int verbose = 0;
+ int status = 0;
for (int i = 1; i < argc; i++) {
if (!strcmp(argv[i], "-p") && i + 1 < argc) {
@@ -187,10 +299,21 @@ int main(int argc, char**argv) {
} else
usage();
}
-
signal(SIGPIPE, SIG_IGN);
skt = new ppsocket();
- skt->connect(NULL, sockNum);
- a = new rfsv32(skt);
- return mp_main(verbose, mdir, user);
+ if (!skt->connect(NULL, sockNum)) {
+ cerr << "plpnfsd: could not connect to ncpd" << endl;
+ status = 1;
+ } else {
+ rf = new rfsvfactory(skt);
+ a = rf->create(true);
+ openlog("plpnfsd", LOG_PID|LOG_CONS, LOG_DAEMON);
+ if (a != NULL)
+ syslog(LOG_INFO, "connected, status is %d", status);
+ else
+ syslog(LOG_INFO, "could not create rfsv object, connect delayed");
+ status = mp_main(verbose, mdir, user);
+ delete a;
+ }
+ exit(status);
}
diff --git a/plpnfsd/mp_main.c b/plpnfsd/mp_main.c
index 23623c6..3c3cab9 100644
--- a/plpnfsd/mp_main.c
+++ b/plpnfsd/mp_main.c
@@ -46,7 +46,8 @@ fattr root_fattr =
{0, 0}
};
-#if defined(hpux) || defined(__SVR4) || defined(__sgi)
+#if defined(hpux) || defined(__SVR4) || defined(__sgi)
+#ifndef sun
void
usleep(usec)
int usec;
@@ -57,7 +58,7 @@ int usec;
t.tv_usec = (long) (usec % 1000000);
select(0, (fd_set *) 0, (fd_set *) 0, (fd_set *) 0, &t);
}
-
+#endif
#endif /* hpux */
int
diff --git a/plpnfsd/mp_mount.c b/plpnfsd/mp_mount.c
index e607629..f0a82d4 100644
--- a/plpnfsd/mp_mount.c
+++ b/plpnfsd/mp_mount.c
@@ -589,6 +589,7 @@ mount_and_run(char *dir, void (*proc)(), nfs_fh *root_fh)
get_num(cp->inode)->name, dcp->offset);
clean_cache(&attrcache);
query_cache = 0; /* clear the GETDENTS "cache". */
+ rfsv_closecached();
}
}
}
diff --git a/plpnfsd/mp_pfs_ops.c b/plpnfsd/mp_pfs_ops.c
index 5bd0a55..669d435 100644
--- a/plpnfsd/mp_pfs_ops.c
+++ b/plpnfsd/mp_pfs_ops.c
@@ -729,7 +729,6 @@ nfsproc_read_2(struct readargs *ra)
fattr *fp;
struct cache *cp;
struct dcache *dcp;
- long phandle;
long pattr;
long psize;
long ptime;
@@ -752,30 +751,34 @@ nfsproc_read_2(struct readargs *ra)
res.status = NFS_OK;
return &res;
}
- if (rfsv_fopen(1, inode->name, &phandle) != 0) {
- res.status = rfsv_isalive() ? NFSERR_NOENT : NO_PSION;
- return &res;
- }
- if (rfsv_read(rop, ra->offset,
- ra->count, phandle) < 0) {
- rfsv_fclose(phandle);
+
+ if(rfsv_read(rop, ra->offset,
+ ra->count, inode->name) < 0) {
res.status = rfsv_isalive() ? NFSERR_NOENT : NO_PSION;
return &res;
}
- rfsv_fclose(phandle);
- rfsv_getattr(inode->name, &pattr, &psize, &ptime);
+
fp = &res.readres_u.reply.attributes;
- pattr2attr(pattr, psize, ptime, fp, (unsigned char *) ra->file.data);
- if (cp == 0)
- cp = add_cache(&attrcache, inode->inode, fp);
+ if(!cp) // Problem: if an epoc process is enlarging the file, we wont recognize it
+ {
+ rfsv_getattr(inode->name, &pattr, &psize, &ptime);
+ pattr2attr(pattr, psize, ptime, fp, (unsigned char *) ra->file.data);
+ cp = add_cache(&attrcache, inode->inode, fp);
+ }
+ else
+ {
+ *fp = cp->attr;
+ }
+
+
- len = fp->size - ra->offset;
+ len = cp->actual_size - ra->offset;
if (len > ra->count)
len = ra->count;
- if (fp->size < ra->offset)
+ if (cp->actual_size < ra->offset)
len = 0;
if (debug > 1)
- debuglog("Read: filesize %d read %d @ %d\n", fp->size, len, ra->offset);
+ debuglog("Read: filesize %d read %d @ %d\n", cp->actual_size,len,ra->offset);
res.readres_u.reply.data.data_len = len;
res.readres_u.reply.data.data_val = (char *) rop;
@@ -870,7 +873,6 @@ nfsproc_write_2(writeargs *wa)
struct dcache *dcp;
fattr *fp;
struct attrstat *gres;
- long phandle;
int len, dlen, doff;
if (!inode) {
@@ -922,18 +924,11 @@ nfsproc_write_2(writeargs *wa)
debuglog("writing off: %d, len: %d, act: %d\n",
dcp->offset, dcp->len, cp->actual_size);
- if (rfsv_fopen(0x200, inode->name, &phandle) != 0) {
- debuglog("write: open failed\n");
- res.status = rfsv_isalive() ? NFSERR_NOSPC : NO_PSION;
- return &res;
- }
- if (rfsv_write(dcp->data, dcp->offset, dcp->len, phandle) != dcp->len) {
- rfsv_fclose(phandle);
+ if (rfsv_write(dcp->data, dcp->offset, dcp->len, inode->name) != dcp->len) {
debuglog("write: dump failed\n");
res.status = rfsv_isalive() ? NFSERR_NOSPC : NO_PSION;
return &res;
}
- rfsv_fclose(phandle);
dcp->towrite = 0;
len = dcp->offset + dcp->len;
if (len > cp->actual_size)
diff --git a/plpnfsd/rfsv_api.h b/plpnfsd/rfsv_api.h
index b1993f9..b63911d 100644
--- a/plpnfsd/rfsv_api.h
+++ b/plpnfsd/rfsv_api.h
@@ -18,8 +18,8 @@ extern long rfsv_rename(const char *oldname, const char *newname);
extern long rfsv_fclose(long handle);
extern long rfsv_fopen(long attr, const char *name, long *handle);
extern long rfsv_fcreate(long attr, const char *name, long *handle);
-extern long rfsv_read(char *buf, long offset, long len, long handle);
-extern long rfsv_write(char *buf, long offset, long len, long handle);
+extern long rfsv_read(char *buf, long offset, long len, char *name);
+extern long rfsv_write(char *buf, long offset, long len, char *name);
extern long rfsv_getattr(const char *name, long *attr, long *size, long *time);
extern long rfsv_setattr(const char *name, long sattr, long dattr);
extern long rfsv_setsize(const char *name, long size);
@@ -28,5 +28,6 @@ extern long rfsv_drivelist(int *cnt, device **devlist);
extern long rfsv_dircount(const char *name, long *count);
extern long rfsv_statdev(char letter);
extern long rfsv_isalive();
+extern long rfsv_closecached(void);
#endif