h29343
s 00003/00003/00977
d D 2.21 94/05/05 21:33:56 tim 34 33
c added full support for checksums
e
s 00021/00001/00959
d D 2.20 94/05/05 20:54:16 tim 33 32
c added code for checksumming, also (I hope ) fixed the problem whereby the put went apeshit and looped forever.
e
s 00009/00000/00951
d D 2.19 94/04/20 13:32:16 tim 32 31
c added copyright and warrantee statment
e
s 00001/00001/00950
d D 2.18 94/03/22 21:19:50 tim 31 30
c changed some of the help text
e
s 00006/00002/00945
d D 2.17 94/03/22 21:15:41 tim 30 29
c fixed bug in the psgfb code (I missed a variable in the printf)
c added some more text to the help printout
e
s 00001/00001/00946
d D 2.16 94/03/22 21:07:38 tim 29 28
c minor tweak so the restart option works properly (I was sending a numm path and the psion wants some value so we now send m: which is always there)
e
s 00003/00000/00944
d D 2.15 94/03/22 19:33:08 tim 28 27
c added code to the attributes stuff to force PSFILEFILE if not a directory
e
s 00030/00000/00914
d D 2.14 94/03/22 18:54:16 tim 27 26
c added new routinet to get the modification timeof the file, and set it to be ro or rw
e
s 00051/00000/00863
d D 2.13 94/03/21 21:23:36 tim 26 25
c added 3 new routings to get the file size (psgetsize) access mode (psgetrw)
c and attributes (psgetatts)
e
s 00026/00011/00837
d D 2.12 94/03/20 18:45:11 tim 25 24
c added some berret error handling code, next job do some more work on handling errors which are valid (i.e. mkdir when one already exists etc)
e
s 00001/00001/00847
d D 2.11 94/03/20 00:14:44 tim 24 23
c added sccs id strings
e
s 00002/00112/00846
d D 2.10 94/03/19 19:02:16 tim 23 22
c Removed the code for the ascii transfer mode, this never realy worked
c and always caused me great difficulties in working out why so I removed it, especialy as the binary mode seems to work perfectly well
e
s 00007/00007/00951
d D 2.9 94/03/19 17:04:01 tim 22 21
c modified debug levels so that all pslib debugcall values are at 3 or above
e
s 00109/00001/00849
d D 2.8 94/03/17 21:55:42 tim 21 19
c Added new variable debugcall which outputs all the subrouting calls, (very verbose) number of levels
c 1 high level
c 2 some comms calls
c 3 cll comms calls
c 5 utility calls
e
s 00000/00000/00850
d R 3.1 93/12/30 14:39:02 tim 20 19
c version 3 a rewrite to handle the use of xmodem transfer methods
c as these are 1, faster 2, have better error recovery, 3 result in smaller code
c as the xmodem stuff is integral to the psion prom
e
s 00001/00001/00849
d D 2.7 93/12/24 12:28:59 tim 19 18
c fixed a var type problem in pssetpath
e
s 00018/00049/00832
d D 2.6 93/12/20 12:57:38 tim 18 17
c fixed minor naming probs
e
s 00008/00013/00873
d D 2.5 93/12/20 02:42:49 tim 17 16
c fixed string setting sequence problem in pssp and pssetpath
e
s 00006/00004/00880
d D 2.4 93/12/20 02:27:24 tim 16 15
c more fixing forgoten calls to seperated pathnames
e
s 00001/00001/00883
d D 2.3 93/12/20 02:21:20 tim 15 14
c fix typo in pssetpath
e
s 00041/00002/00843
d D 2.2 93/12/20 02:20:14 tim 14 13
c put the psionparse code back in (this will need some work soon though to handle the
c case of M:\fred which would normaly imply fred is the filename and there is no directory component
e
s 00021/00154/00824
d D 2.1 93/12/20 01:42:22 tim 13 12
c heavy mods for version 2, there is now no seperate support for partition, directoy and
c path, instead we use a (admitedly more sensible approach) of just treating the path as a single
c string
e
s 00006/00007/00972
d D 1.11 93/05/12 13:31:29 tim 12 11
c changed all calls to index to be strchr for xopem compatibility
e
s 00002/00002/00977
d D 1.10 93/05/12 13:16:53 tim 11 10
c fix to reinsert sccs keywords
e
s 00005/00001/00974
d D 1.9 93/02/24 14:16:37 tim 10 9
c added support for auto version sense failing
e
s 00005/00016/00970
d D 1.8 93/01/11 12:02:23 tim 9 8
c added support for dynamic selection of the debuging state
e
s 00127/00000/00859
d D 1.7 93/01/11 10:07:27 tim 8 7
c finished implementing version checking and comparison routines
e
s 00001/00001/00858
d D 1.6 93/01/05 14:28:33 tim 7 6
c slight fix to psversion
e
s 00017/00006/00842
d D 1.5 93/01/05 14:24:45 tim 6 5
c updates to the version code
e
s 00022/00000/00826
d D 1.4 93/01/04 15:53:42 tim 5 4
c addad the start of verion support
e
s 00001/00001/00825
d D 1.3 93/01/04 14:00:25 tim 4 3
c changed the handshaking from XCMD> to >
e
s 00004/00003/00822
d D 1.2 92/12/29 13:21:51 tim 3 1
c added support for command line selection of device
e
s 00000/00000/00825
d R 1.2 92/12/29 13:02:03 tim 2 1
c just a save
e
s 00825/00000/00000
d D 1.1 92/12/23 11:58:05 tim 1 0
c date and time created 92/12/23 11:58:05 by tim
e
u
U
f e 0
t
T
I 32
/* (C) Tim Graves 20th April 1994
   This code is supplied AS IS. no warrantee either expressed or implied 
   is provided. This code may be freeley modified and modified as long as my
   origional authorship is acknowledged. 
   
   Tim Graves
    Sun Microsystems
     
     */
E 32
I 1
/* a set of routines for transfering data between the Psion and the Sun machines
   where possible I have provided a sensible wrapper for the low level function
   This program should be started BEFORE the suncom program on the psion */
#include <stdio.h>
#include <ctype.h>
#include <sys/termios.h>
#include <fcntl.h>
I 8
#include <string.h>
E 8
#include "psion.h"
#define MAXSEND 200
I 6
D 11
#define DEFVSNSTR "1.3"
E 11
I 11
D 16
#define DEFVSNSTR "%I%"
E 16
I 16
#define DEFVSNSTR "2.3"
E 16
E 11
E 6

I 5
D 6
static char * vsn "%A%"
E 6
I 6
D 10
static char vsn[]= "%A%" ;
E 10
I 10
D 11
static char vsn[]= "@(#) pslib.c 1.8@(#)" ;
E 11
I 11
D 16
static char vsn[]= "%A%" ;
E 16
I 16
D 24
static char vsn[]= "@(#) pslib.c 2.3@(#)" ;
E 24
I 24
static char vsn[]= "%A%" ;
E 24
E 16
E 11
E 10
E 6
E 5
D 13
char pspart[10] = "" ;
char psdir [255] = "";
char psfname[30] = "";
int pspartset, psdirset, psfnameset ;
E 13
I 13
char pspath[255] = "";
I 14
char pspart[10] = "" ;
char psdir [255] = "";
char psfname[30] = "";
E 14
int pspathset ;
E 13
int tmode ;
int transct ;
I 9
int debuglink = FALSE ;
I 21
extern int debugcall ;
E 21
E 9

I 5
D 6
double version = -1;
E 6
I 6
char version[100] ="X" ;
I 8
D 12
extern char * index() ;
E 12
E 8
E 6

E 5
int devid;
struct termios initial, modified ;

D 13
psionparse(psionstr, pp, pd, pf)
char * psionstr, * pp, * pd, * pf ;
{
	char * tmp ;

	/* this routine assumes a directory name exisit (not unreasonable with a psion */
	/* first remove the LOC:: from the string */
	psionstr += 5 ;
	/* (Simple Hu !) */
	/* now extract the next two characters which will be drive name and :*/
	pp[0] = psionstr[0] ;
	pp[1] = psionstr[1] ;
	pp[2] = '\0' ;

	/* increment psionstr to remove the drive spec  and leading \ from the filenames */
	psionstr += 3 ;
	/* isnt pointer arithmetic fun ! */
	/* now find the last \ in the remaining name, this will be the
	end of the directory string */
	tmp = strrchr(psionstr, '\\') ;
	/* terminate the directory name */
	tmp[0] = '\0' ;
	/* tmp will include the \ (now '\0') so increment by one */
	tmp ++ ;
	/* extract the filename from psionstr using tmp */
	strcpy (pf, tmp) ;
	/* now the dir name which will be null terminated (see above) */
	strcpy (pd, psionstr) ;
}

E 13
psisset(qn)
int qn ;
{
I 21
	if (debugcall >= 3)
		printf("CALL: psisset (qn = %d)\n", qn) ;
E 21
D 13
	if (qn == PART)
		return(pspartset) ;
	else if (qn == DIR)
		return(psdirset) ;
	else if (qn == FNAME) 
		return(psfnameset) ;
E 13
I 13
	if (qn == PATH)
		return(pspathset) ;
E 13
	else
		return (BADPARAM) ;
}

pstrans()
{
I 21
	if (debugcall >= 3)
		printf("CALL: pstrans()\n") ;
E 21
	return(transct) ;
}

D 3
psinit(restart)
E 3
I 3
psinit(restart, devname)
E 3
int restart ;
I 3
char * devname ;
E 3
{
I 21
   if (debugcall >= 3)
	printf("CALL: psinit (restart = %d, devname = %s)\n", restart, devname) ;
E 21
   devid = 0 ;
   tmode = BINARY ;
D 3
   psinitlink("") ;
E 3
I 3
   psinitlink(devname) ;
E 3
   /* is we are doing a restart we send the online cmd by hand
      WITHOUT waiting for any fancy XCMD> prompts to come back
      to us */
   if (restart)
	psrestart() ;
   else
   	psreply("XONLINE") ;
   psbinary() ;
}

psrestart()
{
	char length[5] ;

I 21
	if (debugcall >= 1 )
		printf("CALL: psrestart()\n") ;
E 21
D 3
	/* cheat the system for the restart mod only. to have got here 
E 3
I 3
	/* cheat the system for the restart mode only. to have got here 
E 3
	   we know that the link opened correctley */
	write(devid, "$02ol",5) ;
	psreply("XONLINE") ;
D 16
	psup() ;
E 16
I 16
	pspath[0] = '\0' ;
D 29
	pssp("") ;
E 29
I 29
	pssp("m:") ;
E 29
	
E 16
}

psinitlink(devstr) 
char * devstr ;
{
I 21
	if (debugcall >= 3)
		printf("CALL: psinitlink (devstr = %s)\n", devstr) ;
E 21
	if (strlen(devstr) == 0)
	{
D 13
		if ((devid = open("/dev/ttya", O_RDWR , 0)) == -1)
E 13
I 13
		if ((devid = open(DEVFILE, O_RDWR , 0)) == -1)
E 13
			pserror ("Error in opening device\n") ;
	}
	else
	{
		if ((devid = open(devstr, O_RDWR, 0)) == -1)
			pserror ("Error in openint device\n") ;
	}

	/* we need to remove the echo as it confuses the psion (tremendously!) */
	/* first get the current structure for storage and modification*/
	ioctl(devid, TCGETS, &initial);
	ioctl(devid, TCGETS, &modified);
	/* remove the echo line */
	modified.c_lflag = modified.c_lflag & ~ECHO ;
	/* stop it from doing any flay input processing */
	modified.c_lflag = modified.c_lflag & ~IEXTEN ;
	/* setup the input and output speeds */
	modified.c_cflag = B9600 | CS8 | CREAD | ( B9600 << IBSHIFT ) ;
	/* remove incomming parity checks */
	modified.c_iflag = modified.c_iflag & ~INPCK ;
	/* remove CR on input, make life a bit easier on the input routing coding ! */
	modified.c_iflag = modified.c_iflag | IGNCR ; 
	/* strip down to 7 characters */
	modified.c_iflag = modified.c_iflag | ISTRIP ;
	/* Install xon/xoff flow control */
	/*modified.c_iflag = modified.c_iflag | IXON | IXOFF ;*/
	/* remove flow control */
	modified.c_iflag = modified.c_iflag & ~IXON ;
	modified.c_iflag = modified.c_iflag & ~IXOFF ;
	modified.c_cflag = modified.c_cflag & ~CRTSCTS ;
	/* ensure that on output we only send newline, not CRNL */
	modified.c_oflag = modified.c_oflag | ONLRET ;
	/* and just to make sure remove the output processing facility */
	modified.c_oflag = modified.c_oflag & ~OPOST ;
	/* set the new params */
	ioctl(devid, TCSETS, &modified) ;

}

/* reset the terminal device and close the link down */
psshutdown(ret)
int ret ;
{
I 21
D 22
	if (debugcall >= 2)
E 22
I 22
	if (debugcall >= 3)
E 22
		printf("CALL psshutdown (ret = %d)\n", ret) ;
E 21
	/* we need to reset the terminal flags to their initial state ! */
	ioctl (devid, TCSETS, &initial) ;

	if (devid != -1)
		close (devid) ;

	exit(ret) ;
}

/* send a command to the psion */
pscommand (msg)
char * msg ;
{
I 21
D 22
	if (debugcall >= 2)
E 22
I 22
	if (debugcall >= 3)
E 22
		printf("CALL: pscommand (msg = %s)\n", msg) ;
E 21
	psputline(msg) ;
}

/* send some text to the psion */
psputline1 (str,len)
char * str ;
int len ;
{
	char length[5] ;
I 21
	if (debugcall >= 4)
		printf("CALL: psputline1 (OMITED)\n") ;
E 21
D 4
	psresponse("XCMD>") ;
E 4
I 4
	psresponse(">") ;
E 4
	/* New method - send the length in 3 ascii bytes then send the 
	   remainder of the text in one fell swoop, no terminator etc */
	sprintf(length, "$%2.2X", len) ;
	write(devid, length, 3) ;
	write(devid, str, strlen(str)) ;
D 9
#ifdef DEBUG
	printf("Len %s, Sent :%s:\n", length, str) ;
#endif
#ifdef PARTDEBUG
	if (len < 20)
E 9
I 9

	if (debuglink)
E 9
		printf("Len %s, Sent :%s:\n", length, str) ;
D 9
	else
		printf("Transfer Sent Len %s\n", length) ;
#endif
E 9
}

psputline(str)
char * str;
{
I 21
	if (debugcall >= 4)
		printf("CALL: psputline (OMITED)\n") ;
E 21
	psputline1(str, strlen(str)) ;
}

/* get a line of text from the psion, remove any newlines etc */
psresponse(str)
char * str ;
{
I 21
	if (debugcall >= 3)
		printf("CALL psresponse (OMITED)\n") ;
E 21
	psreadstr(str, 1000) ;
	if (str[strlen(str)] == '\n') ;
	   str[strlen(str)] == '\0' ;
D 9
#ifdef DEBUG
	printf("Len %d, Got:%s:\n", strlen(str), str) ;
#endif
#ifdef PARTDEBUG
	if (str[0] == 'X')
E 9
I 9

	if (debuglink)
E 9
		printf("Len %d, Got:%s:\n", strlen(str), str) ;
D 9
	else
		printf("Got Len %d\n", strlen(str) );
#endif
E 9
}

/* get a line of text from the psion and remove any terminating newlines */
psreadstr(string, count)
char * string ;
int count ;
{
	int ctr ;
I 21
	if (debugcall >= 3)
		printf("CALL: psreadstr (string OMITED, count = %d)\n",  count) ;
E 21
	ctr = 0 ;
	ctr = read(devid, string, count) ;
	string[ctr -1] = '\0' ;
	if (string[ctr - 1] == '\n') ;
	   string[ctr - 1] == '\0' ; 
	/*   New method, the psion sends a string length, two hex charachers
	   and then the string in hex, no newlines etc come into play*/
	/*
	int ctr, cnt;
	char cntstr[10] ;
	ctr = read(devid, cntstr, 2) ;
	cnt = dehex(cntstr) ;
	ctr = read(devid, string,  */
}

/* send a file to the psion, remove the file if it exists. if we have been 
   passed a null string use the file name we are sending as the local files name
   */
pssendfile(fname)
char * fname ;
{
I 21
D 22
	if (debugcall >= 2)
E 22
I 22
	if (debugcall >= 3)
E 22
		printf("CALL: pssendfile (fname = %s)\n", fname) ;
E 21
I 18
	/* then parse pspath to extract the filename component */
	psgetfname() ;
E 18
D 14
	/* first remove the target file is required */
E 14
I 14
	/* first remove the target file if required */
E 14
	psclearfile() ;
I 14
D 18
	/* then parse pspath to extract the filename component */
	psionparse(pspath) ;
E 14
	if (strlen(fname) == 0)
E 18
I 18
	if ( strlen(fname) == 0)
	{
E 18
		psgf(psfname) ;
I 18
	}
E 18
	else
		psgf(fname) ;
	/* the above command is misnamed as if refers to getting a file on the psion ! */
}

I 33
	
E 33
/* we have an error, print the message ans shutdown */
pserror(str)
char * str ;
{
I 21
	if (debugcall >= 3)
		printf("CALL: pserror (str = %s)\n", str) ;
E 21
	fprintf(stderr, "%s\n", str) ;
	psshutdown(6) ;
}

psgf(fname)
char * fname ;
{
I 21
D 22
	if (debugcall >= 2)
E 22
I 22
	if (debugcall >= 3)
E 22
		printf("CALL: psgf (fname = %s)\n", fname) ;
E 21
	if (tmode == ASCII)
D 23
		psgfa(fname) ;
E 23
I 23
		printf("ASCII mode is nolonger supported\n");
E 23
	else
		psgfb(fname) ;
}

/* send the file named in the parameter to the psion. this assumes that the 
   file does not exist on the psion and that the remote path is correct
   then send a hex file */

psgfb(fname)
char * fname ;
{
	FILE *fd ;
	char sendstr [255], tmpstr [10] ;
	char ch ;
	int ctr ;
	int fileid ;

I 21
D 22
	if (debugcall >= 2)
E 22
I 22
	if (debugcall >= 3)
E 22
		printf("CALL: psgfb(fname = %s)\n", fname) ;
E 21
	transct = 0 ;

	if ((fileid = open(fname, O_RDONLY , 0)) == -1)
	{
D 25
	   pserror ("File not found, psgf\n") ;
	   psshutdown (1) ;
E 25
I 25
D 30
	   printf("Error in puting %s, not found on local machine\n") ;
E 30
I 30
	   printf("Error in puting %s, not found on local machine\n", fname) ;
E 30
	   return ;
E 25
	}

	pscommand("gf") ;

	psreply("XSTARTGET") ;
D 25
	if (psquery("XBADOPEN"))
	   return ;
E 25
I 25
	if (psquery("XBADOPEN") == TRUE)
	{
		if (findvar(VAR_HELPFULL) != NULL)
D 30
			printf("HELP: Error in getting file from the psion, cannot open it\n") ; 
E 30
I 30
		{
			printf("HELP: Error in getting file from the psion, cannot open it.\n") ; 
			printf("HELP: Either the disk is full, there are to many files or the directory\n") ;
			printf("HELP: does not exist\n") ;
		}
E 30
	   	return ;
	 }
E 25

	ctr = 0 ;
	sendstr[0] = '\0' ;

	while (read(fileid, &ch, 1) == 1)
	{
	   pstoas(ch, tmpstr) ;
	   strcat(sendstr, tmpstr) ;
	   ctr += 2 ;
	   transct ++ ;
	   if (ctr > MAXSEND)
	   {
	      psputline(sendstr) ;
	      ctr = 0 ;
	      sendstr[0] = '\0' ;
	   }
	}
	/* clear out any data in the string */
	if (ctr != 0)
	{
	   psputline(sendstr) ;
	}

	psputline("XE") ;
D 25
	psquery("XENDGET") ;
E 25
I 25
	psreply("XENDGET") ;
E 25
D 33
	close(fd) ;
E 33
I 33
	close(fileid) ;
E 33
}

D 23
/* send the file named in the parameter to the psion. this assumes that the 
   file does not exist on the psion and that the remote path is correct
   then send a text file */

psgfa(fname)
char * fname ;
{
	FILE *fd ;
	char sendstr [255], tmpstr [10] ;
	char ch ;
	int ctr ;
	int fileid ;
D 21

E 21
I 21
D 22
 	if (debugcall >= 2)
E 22
I 22
 	if (debugcall >= 3)
E 22
		printf("CALL: psgfa(fname = %s)\n", fname) ;
E 21
	transct = 0  ;

	if ((fileid = open(fname, O_RDONLY , 0)) == -1)
	{
	   pserror ("File not found, psgf\n") ;
	   psshutdown (1) ;
	}

	pscommand("gf") ;

	psreply("XSTARTGET") ;
	if (psquery("XBADOPEN"))
	   return ;

	ctr = 0 ;
	sendstr[0] = '\0' ;

	while (read(fileid, &ch, 1) == 1)
	{
	   sendstr[ctr] = ch ;
	   ctr += 1 ;
	   transct ++ ;
	   if (ctr > MAXSEND)
	   {
	      psputline1(sendstr, ctr) ;
	      ctr = 0 ;
	      sendstr[0] = '\0' ;
	   }
	}
	/* clear out any data in the string */
	if (ctr != 0)
	{
	   psputline1(sendstr, ctr) ;
	}

	psputline("XE") ;
	psquery("XENDGET") ;
	close(fd) ;
}


E 23
pstoas(ch, str) 
char ch ;
char * str ;
{
	int msn, lsn ;
	int tmp ;
I 21
	if (debugcall >= 5)
		printf("CALL: pstoas (OMITED)\n") ;
E 21
	tmp = ch & 0xFF ;
	msn = ((int) tmp) / 16 ;
	lsn = (int) tmp - (msn * 16) ;
	str[0] = 'A' + msn ;
	str[1] = 'A' + lsn ;
	str[2] = '\0' ;
}

psrecfile(fname)
char * fname ;
{
I 14
	/* parse the name to get the filename component */
D 18
	psionparse(pspath) ;
E 18
E 14
	/* if the file exists remotley */
I 21
D 22
	if (debugcall >= 2)
E 22
I 22
	if (debugcall >= 3)
E 22
		printf("CALL: psrecfile (fname = %s)\n", fname) ;
E 21
D 18
	if (psef())
E 18
I 18
	if (psep())
E 18
I 14
	{
E 14
D 18
	/* check to see if fname is null, if so use the system file name */
E 18
		if (strlen(fname) == 0)
I 18
		{
			psgetfname() ;
E 18
			pspf(psfname) ;
I 18
		}
E 18
		else
			pspf(fname) ;
I 14
	}
E 14
}

/* call the appropriate transfer method */
pspf(fname)
char * fname ;
{
I 21
	if (debugcall >= 3)
		printf("CALL: pspf (fname = %s)\n", fname) ;
E 21
	if (tmode == ASCII)
D 23
		pspfa(fname) ;
E 23
I 23
		printf("ASCII mode is nolonger supported\n") ;
E 23
	else
		pspfb(fname) ;
}

D 23
pspfa(fname)
char * fname ;
{
	FILE *fd ;
	char recstr [255], tmpstr [10] ;
	char ch, dehex() ;
	int fileid,ctr, len ;

I 21
	if (debugcall >= 3)
		printf("CALL: psgfa (fname = %s)\n", fname) ;
E 21
	transct = 0 ;

	if ((fileid = open(fname, O_WRONLY|O_CREAT , 420)) == -1)
	{
	   pserror ("File not found, pspfa\n") ;
	   psshutdown (1) ;
	}

	pscommand("pf") ;

	psreply("XSTARTPUT") ;
	if (psquery("XBADOPEN"))
	   return ;

	psresponse(recstr) ;
	while (strcmp(recstr, "XE") != 0)
	{
		ctr = 0 ;
		len = strlen(recstr) ;
		while ( ctr <= (len - 2))
		{
			ch = dehex(recstr + ctr) ;
			write(fileid, &ch, 1) ;
			ctr += 2 ;
			transct ++ ;
		}
		psresponse(recstr) ;
	}

	psquery("XENDPUT") ;
	close(fileid) ;


}

E 23
pspfb(fname)
char * fname ;
{
	FILE *fd ;
	char recstr [255], tmpstr [10] ;
	char ch, dehex() ;
	int fileid, ctr, len ;
I 21
	if (debugcall >= 3)
		printf("CALL: psgfb (fname = %s)\n", fname) ;
E 21

	transct = 0 ;

	if ((fileid = open(fname, O_WRONLY |O_CREAT, 420)) == -1)
	{
D 25
	   pserror ("File not found, pspfb\n") ;
	   psshutdown (1) ;
E 25
I 25
D 31
	   printf("ERROR: Cant open file to put\n") ;
E 31
I 31
	   printf("ERROR: Cant open file (%s) to recieve the data\n") ;
E 31
	   return ;
E 25
	}

	pscommand("pf") ;

	psreply("XSTARTPUT") ;
	if (psquery("XBADOPEN"))
D 25
	   return ;
E 25
I 25
	{
		if (findvar(VAR_HELPFULL) != NULL)
			printf("Error in put, cannot open the file on the psion\n") ;
		return ;
	}
E 25

	psresponse(recstr) ;
	while (strcmp(recstr, "XE") != 0)
	{
		ctr = 0 ;
		len = strlen(recstr) ;
		while ( ctr <= (len - 2))
		{
			ch = dehex(recstr + ctr) ;
			write(fileid, &ch, 1) ;
			ctr += 2 ;
			transct ++ ;
		}
		psresponse(recstr) ;
	}

	psquery("XENDPUT") ;
	close(fileid) ;

}

char dehex (str)
char * str ;
{
   char ch ;
   int tmp ;
   char tmpstr[6] ;

I 21
   if (debugcall >= 5)
	printf("CALL: dehex (OMITED)\n") ;
E 21
   tmpstr[0] = '0' ;
   tmpstr[1] = 'x' ;
   tmpstr[2] = str[0] ;
   tmpstr[3] = str[1] ;
   tmpstr[4] = '\0' ;

   sscanf(tmpstr, "%i", &tmp) ;

   ch = (char) tmp ;
   return (ch) ;
}

psscreenoff()
{
I 21
	if (debugcall >= 3)
		printf("CALL: psscreenoff ()\n") ;
E 21
	pscommand("is") ;
	if (psquery ("XYES") == 1)
		pssc() ;
		
}

psscreenon()
{
I 21
	if (debugcall >= 3)
		printf("CALL: psscreenon ()\n") ;
E 21
	pscommand("is") ;
	if (psquery ("XNO") == 1)
		pssc() ;
		
}

pssc()
{
I 21
	if (debugcall >= 3)
		printf("CALL: pssc()\n") ;
E 21
	pscommand("sc") ;
	psreply("XOK") ;
}

psverboseoff()
{
I 21
	if (debugcall >= 3)
		printf("CALL: psverboseoff()\n") ;
E 21
	pscommand("iv") ;
	if (psquery ("XYES") == 1)
		psvb() ;
		
}

psverboseon()
{
I 21
	if (debugcall >= 3)
		printf("CALL: psverboseon()\n") ;
E 21
	pscommand("iv") ;
	if (psquery ("XNO") == 1)
		psvb() ;
		
I 5
}

D 6
double psversion()
E 6
I 6
char * psversion()
E 6
{
	char vsnstr[100] ;

I 21
	if (debugcall >= 3)
		printf("CALL: psversion()\n") ;
E 21
D 6
	/* if the version is less than 0 it has not been aquired */
	if (version < 0)
E 6
I 6
	/* if the first char of version is X we have not got the version
	   yet so get it and store it, otherwise just return the pointer
	   to the version string */
	if (version[0] == 'X')
E 6
	{
		psvn(vsnstr) ;
D 6
		version = atof(vsnstr) ;
E 6
I 6
		/* copy from the second char as the first will be X */
D 7
		strcpy(version, vsnstr ++) ;
E 7
I 7
		strcpy(version, &vsnstr[1]) ;
I 10
		/* if the first char is B (the psion will return XBADCMD
		   if it doesnot support version checking yet) run pssetdefvsn */
		if (version[0] == 'B')
			pssetdefvsn() ;
E 10
E 7
E 6
	}
	return (version) ;
}
I 6

I 8
/* compare psion vsn string to sun vsn string, if the psion one is later return
   GREATERTHAN, if they are the same EQUAL otherwise LESSTHAN */
psvsncmp(vsstr)
char * vsstr ;
{
	char * psvnstr ;
	char * ps1, *ps2, *ps3, *ps4 ;
	char * ss1, *ss2, *ss3, *ss4 ;
	char nstr[1] ;
	int pint, vint ;

I 21
	if (debugcall >= 3)
		printf("CALL: psvsncmp(vsstr = %s)\n", vsstr) ;
E 21
	/* first ensure that we have the correct version */
	psvnstr = psversion() ;

	/* initialise the nstr */
	nstr[0] = '\0' ;

	/* now extract the strings */
	ps1 = psvnstr ;
	ss1 = vsstr ;

	/* locate the next . */
D 12
	psvnstr = index(psvnstr, '.') ;
	vsstr = index(vsstr, '.') ;
E 12
I 12
	psvnstr = strchr(psvnstr, '.') ;
	vsstr = strchr(vsstr, '.') ;
E 12
	if (psvnstr == NULL)
		psvnstr = nstr ;
	else
		psvnstr ++;/* skip over the . */
	if (vsstr == NULL)
		vsstr = nstr ;
	else
		vsstr ++ ; /* see above */
	
	ps2 = psvnstr;
	ss2 = vsstr ;
	/*  and the next */
D 12
	psvnstr = index(psvnstr, '.') ;
	vsstr = index(vsstr, '.') ;
E 12
I 12
	psvnstr = strchr(psvnstr, '.') ;
	vsstr = strchr(vsstr, '.') ;
E 12
	if (psvnstr == NULL)
		psvnstr = nstr ;
	else
		psvnstr ++;/* skip over the . */
	if (vsstr == NULL)
		vsstr = nstr ;
	else
		vsstr ++ ; /* see above */
	
	ps3 = psvnstr ;
	ss3 = vsstr ;
	/* and the last */
D 12
	psvnstr = index(psvnstr, '.') ;
	vsstr = index(vsstr, '.') ;
E 12
I 12
	psvnstr = strchr(psvnstr, '.') ;
	vsstr = strchr(vsstr, '.') ;
E 12
	if (psvnstr == NULL)
		psvnstr = nstr ;
	else
		psvnstr ++;/* skip over the . */
	if (vsstr == NULL)
		vsstr = nstr ;
	else
		vsstr ++ ; /* see above */

	ps4 = psvnstr ;
	ss4 = vsstr ;

	/* do the first test */
	pint = atoi(ps1) ;
	vint = atoi(ss1) ;

	if (pint > vint)
		return (GREATERTHAN) ;
	else if (pint < vint)
		return (LESSTHAN) ;
	pint = atoi(ps2) ;
	vint = atoi(ss2) ;

	if (pint > vint)
		return (GREATERTHAN) ;
	else if (pint < vint)
		return (LESSTHAN) ;
	pint = atoi(ps3) ;
	vint = atoi(ss3) ;

	if (pint > vint)
		return (GREATERTHAN) ;
	else if (pint < vint)
		return (LESSTHAN) ;
	pint = atoi(ps4) ;
	vint = atoi(ss4) ;

	if (pint > vint)
		return (GREATERTHAN) ;
	else if (pint < vint)
		return (LESSTHAN) ;

	/* they would appear to be the same */
	return (EQUAL) ;
}


psvsngt(vsn)
char * vsn ;
{
I 21
	if (debugcall >= 3)
		printf("CALL: psvsngt(vsn = %s)\n",vsn) ;
E 21
	if (psvsncmp(vsn) == GREATERTHAN)
		return (TRUE) ;
	else
		return(FALSE) ;
}

psvsnlt(vsn)
char * vsn ;
{
I 21
	if (debugcall >= 3)
		printf("CALL: psvsnlt(vsn = %s)\n",vsn) ;
E 21
	if (psvsncmp(vsn) == LESSTHAN)
		return(TRUE) ;
	else
		return(FALSE) ;
}

psvsneq(vsn)
char * vsn ;
{
I 21
	if (debugcall >= 3)
		printf("CALL: psvsneq(vsn = %s)\n",vsn) ;
E 21
	if (psvsncmp(vsn) == EQUAL)
		return(TRUE) ;
	else
		return(FALSE) ;
}
E 8
pssetdefvsn()
{
I 21
	if (debugcall >= 3)
		printf("CALL: pssetdefvsn()\n") ;
E 21
	/* set the default version string */
	strcpy(version, DEFVSNSTR) ;
}

E 6
psvn(vsnstr)
char * vsnstr ;
{
I 21
	if (debugcall >= 3)
		printf("CALL: psvn(OMITED)\n") ;
E 21
	pscommand("vn") ;
	psresponse(vsnstr) ;
E 5
}

psvb()
{
I 21
	if (debugcall >= 3)
		printf("CALL: psvb()\n") ;
E 21
	pscommand("vb") ;
	psreply("XOK") ;
}

psds()
{
D 13
	char part[100], dir[100], filename[100] ;
E 13
I 13
	char path[255] ;
E 13

I 21
	if (debugcall >= 3)
		printf("CALL: psds()\n") ;
E 21
	pscommand("ds") ;
	psreply("XSTART") ;
D 13
	psresponse(part) ;
	psresponse(dir) ;
	psresponse(filename) ;
E 13
I 13
	psresponse(path) ;
E 13
	psreply("XEND") ;
D 23
}

psascii()
{
I 21
	if (debugcall >= 3)
		printf("CALL: psascii()\n") ;
E 21
	tmode = ASCII ;
	pscommand("ia") ;
	if (psquery("XNO") == 1)
		pstm() ;
E 23
}

psbinary()
{
I 21
	if (debugcall >= 3)
		printf("CALL: psbinary()\n") ;
E 21
	tmode = BINARY ;
	pscommand("ia") ;
	if (psquery("XYES") == 1)
		pstm() ;
}

pstm()
{
I 21
	if (debugcall >= 3)
		printf("CALL: pstm()\n") ;
E 21
	pscommand("tm") ;
	psreply("XOK") ;
}
int psquery(str)
char * str ;
{
	char tmp[100] ;
I 21
	if (debugcall >= 3)
		printf("CALL: psquery(str = %s)\n",str) ;
E 21
	psresponse(tmp) ;
	if (strcmp(tmp, str) == 0)
	   return(TRUE) ;
	else
	   return (FALSE) ;
}

psclearfile() 
{
I 21
	if (debugcall >= 3)
		printf("CALL: psclearfile()\n") ;
E 21
D 18
	if (psef() == TRUE)
E 18
I 18
	if (psep() == TRUE)
E 18
D 16
		psrf() ;
E 16
I 16
		psrp() ;
E 16
}

D 18
psef()
{
	pscommand("ef") ;
	if (psquery("XYES") == TRUE)
		return(TRUE) ;
	else
		return(FALSE) ;
}


psed()
{
	pscommand("ed") ;
	return(psquery("XYES") == 1) ;
}

E 18
psep()
{
I 21
	if (debugcall >= 3)
		printf("CALL: psep()\n") ;
E 21
	pscommand("ep") ;
	return(psquery("XYES") == 1);
}

D 13
psrf()
E 13
I 13
psrp()
E 13
{
I 21
	if (debugcall >= 3)
		printf("CALL: psrp()\n") ;
E 21
D 13
	pscommand("rf") ;
E 13
I 13
	pscommand("rp") ;
E 13
D 25
	psreply("XOK") ;
E 25
I 25
	if (!psquery("XOK"))
		printf("ERROR: Cant remove the file on the psion\n") ;
E 25
}

D 13
psrd()
{
	pscommand("rd") ;
	psreply("XOK");
}

E 13
psmd()
{
I 21
	if (debugcall >= 3)
		printf("CALL: psmd()\n") ;
E 21
	pscommand("md");
	psreply("XOK") ;
}

psrl()
{
I 21
	if (debugcall >= 3)
		printf("CALL: psrl()\n") ;
E 21
	pscommand("rl") ;
	psreply("XOK") ;
}


D 13
pslf(fd)
FILE *fd ;
{
	pscommand("lf") ;
	psldir(fd) ;
}

psld(fd)
FILE *fd ;
{
	pscommand("ld") ;
	psldir(fd) ;
}

E 13
pslp(fd)
FILE *fd ;
{
I 21
	if (debugcall >= 3)
		printf("CALL: pslp(OMITED FD)\n") ;
E 21
	pscommand("lp") ;
	psldir(fd) ;
}
psldir(fd)
FILE *fd ;
{
	char txt[255] ;
I 21
	if (debugcall >= 3)
		printf("CALL: psldir(OMITED FD)\n") ;
E 21
	if (psquery("XSTARTLIST"))
		while(1)
		{
			psresponse(txt) ;
			if (strcmp (txt, "XENDLIST") == 0)
				break ;
I 25
			else if (strcmp(txt,"XBADPATH") == 0)
			{
				if (findvar(VAR_HELPFULL) != NULL)
					printf("HELP: Error in listing files, bad path specified\n") ;
				break ;
			}
E 25
			if (fd == NULL)
				printf("File :%s\n", txt) ;
			else
				fprintf(fd, "%s\n", txt) ;
		}
}

psdc()
{
I 21
	if (debugcall >= 3)
		printf("CALL: psdc()\n") ;
E 21
	pscommand("dc") ;
	psreply("XDISCONNECTED") ;
	psshutdown(0) ;
}

psreply (expected)
char * expected ;
{
   char tmp[1000] ;

I 21
	if (debugcall >= 3)
		printf("CALL: psreply(expected = %s)\n",expected) ;
E 21
   psresponse(tmp) ;

   if (strcmp(tmp, expected) == 0)
	return;
D 25
   else
	psshutdown(1);
E 25
I 25
   printf("ERROR, Protocol violation, expected (%s), got (%s), exiting\n",expected, tmp) ;
   psshutdown(1);
E 25
}

psdt (txt)
char * txt ;
{
	char tmp [1000] ;
I 21
	if (debugcall >= 3)
		printf("CALL: psdt(txt = %s)\n",txt) ;
E 21
	strcpy (tmp, "dt ") ;
	strcat (tmp, txt) ;
	pscommand (tmp) ;
	psreply("XOK") ;
}

D 13
pssetpath(part, dir, file)
E 13
I 13
pssetpath(path)
E 13
D 14
char * part, *dir, *file ;
E 14
I 14
char * path ;
E 14
{
I 21
	if (debugcall >= 3)
		printf("CALL: pssetpath(path = %s)\n",path) ;
E 21
D 15
	if (strlen(part) == 0)
E 15
I 15
D 17
	if (strlen(path) == 0)
E 15
D 13
		pssp (pspart) ;
E 13
I 13
		pssp (pspath) ;
E 13
	else
D 13
		pssp(part) ;
E 13
I 13
		pssp(path) ;
E 17
I 17
D 19
	if (strcmp(path, pssetpath) == 0)
E 19
I 19
	if (strcmp(path, pspath) == 0)
E 19
		return ;
	pssp(path) ;
E 17
E 13

D 13
	if (strlen(dir) == 0)
		pssd (psdir) ;
	else
		pssd(dir) ;

	if (strlen(file) == 0)
		pssf(psfname) ;
	else
		pssf (file) ;
E 13
}

D 13
pssp(part)
char *part ;
E 13
I 13
pssp(path)
char *path ;
E 13
{
	char tmp[100] ;

I 21
	if (debugcall >= 3)
		printf("CALL: pssp(path = %s)\n",path) ;
E 21
D 13
	/* is the stored name is the same as the current name save on 
E 13
I 13
	/* if the stored name is the same as the current name save on 
E 13
	   transmitting information */
D 13
	if (strcmp(pspart, part) != 0)
E 13
I 13
D 17
	if (strcmp(pspath, path) != 0)
E 13
	{
		strcpy(tmp, "sp ") ;
D 13
		strcat(tmp, part) ;
E 13
I 13
		strcat(tmp, path) ;
E 17
I 17
	strcpy(pspath, path) ;
	strcpy(tmp, "sp ") ;
D 18
	strcat(tmp, path) ;
E 18
I 18
	strcat(tmp, pspath) ;
E 18
E 17
E 13

D 17
		pscommand(tmp) ;
		psreply ("XOK") ;

D 13
		strcpy(pspart, part) ;
	} /* we will have to reset these two anyway */
	strcpy(psdir, "") ;
	strcpy(psfname, "") ;
E 13
I 13
		strcpy(pspath, path) ;
	} 
E 17
I 17
	pscommand(tmp) ;
	psreply ("XOK") ;
E 17
E 13
}

D 13
psup()
E 13
I 13
ispathset()
E 13
{
I 21
	if (debugcall >= 3)
		printf("CALL: ispathset()\n") ;
E 21
D 13
	pscommand("up") ;
	psreply("XOK") ;
	strcpy(pspart, "") ;
	strcpy(psdir, "") ;
	strcpy(psfname, "") ;
}

pssd(dir)
char * dir ;
{
	char tmp[100] ;

	/* if the stored name is the same as the current name save on data
	   transfer */
	if (strcmp(psdir, dir) != 0)
	{
		strcpy(tmp, "sd ") ;
		strcat(tmp, dir) ;

		pscommand(tmp) ;
		psreply ("XOK") ;
		strcpy(psdir, dir) ;
	}
	/* we will still have to reset the file name */
	strcpy(psfname, "") ;
}

psud()
{
	pscommand("ud") ;
	psreply("XOK") ;
	/* unset the internal file and dir names */
	strcpy(psdir, "") ;
	strcpy(psfname, "") ;
}

pssf(filename)
char * filename ;
{
	char tmp[100] ;

	/* if the store file name and the new are the same ignore the transmit */
	if (strcmp(psfname, filename) != 0)
	{
		strcpy(tmp, "sf ") ;
		strcat(tmp, filename) ;

		pscommand(tmp) ;
		psreply ("XOK") ;
		/* store the file name for internal use */
		strcpy(psfname, filename) ;
	}
}

psuf()
{
	pscommand("uf") ;
	psreply("XOK") ;
	/* unset the internal file name */
	strcpy(psfname, "") ;
}

ispartset()
{
	return(strlen(pspart)) ;
E 13
I 13
	return(strlen(pspath)) ;
E 13
}

I 14
D 18
psionparse(psionstr, pp, pd, pf)
char * psionstr, * pp, * pd, * pf ;
E 18
I 18
psgetfname() 
E 18
{
	char * tmp ;

I 21
	if (debugcall >= 3)
		printf("CALL: psgetfname()\n") ;
E 21
D 18
	/* this routine assumes a directory name exisit (not unreasonable with a psion */
	/* first remove the LOC:: from the string if its there */
	if (strncmp("LOC::", psionstr, 5) == 0)
		psionstr += 5 ;
	/* (Simple Hu !) */
	/* now extract the next two characters which will be drive name and :*/
	pp[0] = psionstr[0] ;
	pp[1] = psionstr[1] ;
	pp[2] = '\0' ;

	/* increment psionstr to remove the drive spec  and leading \ from the filenames */
	psionstr += 3 ;
	/* isnt pointer arithmetic fun ! */
	/* now find the last \ in the remaining name, this will be the
	end of the directory string */
	tmp = strrchr(psionstr, '\\') ;
	/* terminate the directory name */
	tmp[0] = '\0' ;
	/* tmp will include the \ (now '\0') so increment by one */
E 18
I 18
	/* find the last \ in the remaining name, this will be the
	end of the directory component */
	tmp = strrchr(pspath, '\\') ;
	/* tmp will point to the \ so increment by one */
E 18
	tmp ++ ;
D 18
	/* extract the filename from psionstr using tmp */
	strcpy (pf, tmp) ;
	/* now the dir name which will be null terminated (see above) */
	strcpy (pd, psionstr) ;
E 18
I 18
	/* extract the filename from pspath using tmp */
	strcpy (psfname, tmp) ;
E 18
}
I 26

psgetfsize()
{
	char tmp[100] ;
	if (debugcall >= 3)
		printf("CALL: psgetfsize()\n") ;
	
	pscommand("sz") ;
	psresponse(tmp) ;
	if (strcmp(tmp, "XBADPATH") == 0)
		return(0) ;
	return (atoi(tmp+1)) ;
}

psgetrw()
{
	char tmp[100] ;
	if (debugcall >= 3)
		printf("CALL: psgetrw()\n") ;
	pscommand("rw") ;
	psresponse(tmp) ;
	if (strcmp(tmp, "XBADPATH") == 0)
		return(PSBADPATH) ;
	else if (strcmp(tmp, "XRW") == 0)
		return(PSFILERW) ;
	else
		return(PSFILERO) ;
}
I 33
D 34
pscs()
E 34
I 34
long pscs()
E 34
{
	char tmp[100] ;
D 34
	int ret ;
E 34
I 34
	long ret ;
E 34
	if (debugcall >= 3)
		printf("CALL: pscs ()\n") ;
	pscommand("cs") ;
	psresponse(tmp) ; /* get the STARTSUM out of the way */
	psresponse(tmp) ; /* good or bad open ? */
	if (strcmp(tmp, "XBADOPEN") == 0)
		return(PSBADPATH) ;
	psresponse(tmp) ;
	if (strcmp(tmp, "XBADSUM") == 0)
		return(PSBADPATH) ;
D 34
	sscanf(tmp+1 /* skip over the X */, "%x", &ret) ;
E 34
I 34
	sscanf(tmp+1 /* skip over the X */, "%ld", &ret) ;
E 34
	psresponse(tmp) ;/* get the ENDSUM line */
	return (ret) ;
}

E 33
psgetatts()
{
	char tmp [100] ;
	int atts ;
	if (debugcall >= 3)
		printf("CALL: psgetatts()\n") ;
	pscommand("ft") ;
	psresponse(tmp) ;
	atts = 0 ;
	if (strcmp(tmp, "XBADPATH") == 0)
		return(PSBADPATH) ;
	else if (strstr(tmp,"DIR") != NULL)
		atts = atts | PSFILEDIR ;
	else if (strstr(tmp,"TEXT") != NULL)
		atts = atts | PSFILETEXT ;
	else if (strstr(tmp,"HIDDEN") != NULL)
		atts = atts | PSFILEHIDDEN ;
	else if (strstr(tmp, "SYSTEM") != NULL)
		atts = atts | PSFILESYSTEM ;
	else if (strstr(tmp, "VOLUME") != NULL)
		atts = atts | PSFILEVOLUME ;
I 28
	/* if the atts do not say this is a directory, its a file but not a text file */
	if (strstr(tmp, "DIR") == NULL)
		atts = atts | PSFILEFILE ;
E 28
	return (atts) ;
}
I 27
long psgetmodtime()
{
	long pstime ;
	char tmp[100] ;
	if (debugcall >= 3)
		printf("CALL: psgetatts()\n") ;
	pscommand ("ti") ;
	psresponse(tmp) ;
	
	if (strcmp("XBADPATH", tmp) == 0)
		return(-1) ;
	return(atoi(tmp+1)) ;
}

pssetro()
{
	char tmp[100] ;
	if (debugcall >= 3)
		printf("CALL:pssetro()\n") ;
	pscommand("wn") ;
	psresponse(tmp) ;
}
pssetrw()
{
	char tmp[100] ;
	if (debugcall >= 3)
		printf("CALL:pssetrw()\n") ;
	pscommand("wy") ;
	psresponse(tmp) ;
}
E 27
E 26
E 14
E 1
