/* (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
     
     */
/* 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>
#include <string.h>
#include "psion.h"
#define MAXSEND 200
#define DEFVSNSTR "2.3"

static char vsn[]= "@(#) pslib.c 2.21@(#)" ;
char pspath[255] = "";
char pspart[10] = "" ;
char psdir [255] = "";
char psfname[30] = "";
int pspathset ;
int tmode ;
int transct ;
int debuglink = FALSE ;
extern int debugcall ;

char version[100] ="X" ;

int devid;
struct termios initial, modified ;

psisset(qn)
int qn ;
{
	if (debugcall >= 3)
		printf("CALL: psisset (qn = %d)\n", qn) ;
	if (qn == PATH)
		return(pspathset) ;
	else
		return (BADPARAM) ;
}

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

psinit(restart, devname)
int restart ;
char * devname ;
{
   if (debugcall >= 3)
	printf("CALL: psinit (restart = %d, devname = %s)\n", restart, devname) ;
   devid = 0 ;
   tmode = BINARY ;
   psinitlink(devname) ;
   /* 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] ;

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

psinitlink(devstr) 
char * devstr ;
{
	if (debugcall >= 3)
		printf("CALL: psinitlink (devstr = %s)\n", devstr) ;
	if (strlen(devstr) == 0)
	{
		if ((devid = open(DEVFILE, O_RDWR , 0)) == -1)
			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 ;
{
	if (debugcall >= 3)
		printf("CALL psshutdown (ret = %d)\n", ret) ;
	/* 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 ;
{
	if (debugcall >= 3)
		printf("CALL: pscommand (msg = %s)\n", msg) ;
	psputline(msg) ;
}

/* send some text to the psion */
psputline1 (str,len)
char * str ;
int len ;
{
	char length[5] ;
	if (debugcall >= 4)
		printf("CALL: psputline1 (OMITED)\n") ;
	psresponse(">") ;
	/* 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)) ;

	if (debuglink)
		printf("Len %s, Sent :%s:\n", length, str) ;
}

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

/* get a line of text from the psion, remove any newlines etc */
psresponse(str)
char * str ;
{
	if (debugcall >= 3)
		printf("CALL psresponse (OMITED)\n") ;
	psreadstr(str, 1000) ;
	if (str[strlen(str)] == '\n') ;
	   str[strlen(str)] == '\0' ;

	if (debuglink)
		printf("Len %d, Got:%s:\n", strlen(str), str) ;
}

/* get a line of text from the psion and remove any terminating newlines */
psreadstr(string, count)
char * string ;
int count ;
{
	int ctr ;
	if (debugcall >= 3)
		printf("CALL: psreadstr (string OMITED, count = %d)\n",  count) ;
	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 ;
{
	if (debugcall >= 3)
		printf("CALL: pssendfile (fname = %s)\n", fname) ;
	/* then parse pspath to extract the filename component */
	psgetfname() ;
	/* first remove the target file if required */
	psclearfile() ;
	if ( strlen(fname) == 0)
	{
		psgf(psfname) ;
	}
	else
		psgf(fname) ;
	/* the above command is misnamed as if refers to getting a file on the psion ! */
}

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

psgf(fname)
char * fname ;
{
	if (debugcall >= 3)
		printf("CALL: psgf (fname = %s)\n", fname) ;
	if (tmode == ASCII)
		printf("ASCII mode is nolonger supported\n");
	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 ;

	if (debugcall >= 3)
		printf("CALL: psgfb(fname = %s)\n", fname) ;
	transct = 0 ;

	if ((fileid = open(fname, O_RDONLY , 0)) == -1)
	{
	   printf("Error in puting %s, not found on local machine\n", fname) ;
	   return ;
	}

	pscommand("gf") ;

	psreply("XSTARTGET") ;
	if (psquery("XBADOPEN") == TRUE)
	{
		if (findvar(VAR_HELPFULL) != NULL)
		{
			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") ;
		}
	   	return ;
	 }

	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") ;
	psreply("XENDGET") ;
	close(fileid) ;
}

pstoas(ch, str) 
char ch ;
char * str ;
{
	int msn, lsn ;
	int tmp ;
	if (debugcall >= 5)
		printf("CALL: pstoas (OMITED)\n") ;
	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 ;
{
	/* parse the name to get the filename component */
	/* if the file exists remotley */
	if (debugcall >= 3)
		printf("CALL: psrecfile (fname = %s)\n", fname) ;
	if (psep())
	{
		if (strlen(fname) == 0)
		{
			psgetfname() ;
			pspf(psfname) ;
		}
		else
			pspf(fname) ;
	}
}

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

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

	transct = 0 ;

	if ((fileid = open(fname, O_WRONLY |O_CREAT, 420)) == -1)
	{
	   printf("ERROR: Cant open file (%s) to recieve the data\n") ;
	   return ;
	}

	pscommand("pf") ;

	psreply("XSTARTPUT") ;
	if (psquery("XBADOPEN"))
	{
		if (findvar(VAR_HELPFULL) != NULL)
			printf("Error in put, cannot open the file on the psion\n") ;
		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) ;

}

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

   if (debugcall >= 5)
	printf("CALL: dehex (OMITED)\n") ;
   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()
{
	if (debugcall >= 3)
		printf("CALL: psscreenoff ()\n") ;
	pscommand("is") ;
	if (psquery ("XYES") == 1)
		pssc() ;
		
}

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

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

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

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

char * psversion()
{
	char vsnstr[100] ;

	if (debugcall >= 3)
		printf("CALL: psversion()\n") ;
	/* 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')
	{
		psvn(vsnstr) ;
		/* copy from the second char as the first will be X */
		strcpy(version, &vsnstr[1]) ;
		/* 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() ;
	}
	return (version) ;
}

/* 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 ;

	if (debugcall >= 3)
		printf("CALL: psvsncmp(vsstr = %s)\n", vsstr) ;
	/* 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 . */
	psvnstr = strchr(psvnstr, '.') ;
	vsstr = strchr(vsstr, '.') ;
	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 */
	psvnstr = strchr(psvnstr, '.') ;
	vsstr = strchr(vsstr, '.') ;
	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 */
	psvnstr = strchr(psvnstr, '.') ;
	vsstr = strchr(vsstr, '.') ;
	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 ;
{
	if (debugcall >= 3)
		printf("CALL: psvsngt(vsn = %s)\n",vsn) ;
	if (psvsncmp(vsn) == GREATERTHAN)
		return (TRUE) ;
	else
		return(FALSE) ;
}

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

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

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

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

psds()
{
	char path[255] ;

	if (debugcall >= 3)
		printf("CALL: psds()\n") ;
	pscommand("ds") ;
	psreply("XSTART") ;
	psresponse(path) ;
	psreply("XEND") ;
}

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

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

psclearfile() 
{
	if (debugcall >= 3)
		printf("CALL: psclearfile()\n") ;
	if (psep() == TRUE)
		psrp() ;
}

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

psrp()
{
	if (debugcall >= 3)
		printf("CALL: psrp()\n") ;
	pscommand("rp") ;
	if (!psquery("XOK"))
		printf("ERROR: Cant remove the file on the psion\n") ;
}

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

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


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

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

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

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

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

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

pssetpath(path)
char * path ;
{
	if (debugcall >= 3)
		printf("CALL: pssetpath(path = %s)\n",path) ;
	if (strcmp(path, pspath) == 0)
		return ;
	pssp(path) ;

}

pssp(path)
char *path ;
{
	char tmp[100] ;

	if (debugcall >= 3)
		printf("CALL: pssp(path = %s)\n",path) ;
	/* if the stored name is the same as the current name save on 
	   transmitting information */
	strcpy(pspath, path) ;
	strcpy(tmp, "sp ") ;
	strcat(tmp, pspath) ;

	pscommand(tmp) ;
	psreply ("XOK") ;
}

ispathset()
{
	if (debugcall >= 3)
		printf("CALL: ispathset()\n") ;
	return(strlen(pspath)) ;
}

psgetfname() 
{
	char * tmp ;

	if (debugcall >= 3)
		printf("CALL: psgetfname()\n") ;
	/* 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 */
	tmp ++ ;
	/* extract the filename from pspath using tmp */
	strcpy (psfname, tmp) ;
}

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) ;
}
long pscs()
{
	char tmp[100] ;
	long ret ;
	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) ;
	sscanf(tmp+1 /* skip over the X */, "%ld", &ret) ;
	psresponse(tmp) ;/* get the ENDSUM line */
	return (ret) ;
}

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 ;
	/* 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 ;
	return (atts) ;
}
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) ;
}
