#include #include #include #include #include #include "link.h" #ifdef UNIX #include #include #include #include #endif #ifdef QDOS #include #endif #ifdef MSDOS #include #include #include #include #include #include "seriel.h" #else #include #endif /***************************************************************************** * PROTOTYPES *****************************************************************************/ struct item *getdevices(void); /* return pointer to collected devices object */ struct item *getfilenames(char *); /* return pointer to collected filenames in path */ struct item *getdirectories(char *); /* return pointer to collected directories in path */ struct item *collectitems(void); /* receive name items from Z88 and return a linked list */ struct item *allocitem(char *); /* allocate & define a new collected name */ void newitem(char *, struct item **) ; /* add new name item to linked list of collected names */ void releaselist(struct item *); /* release linked list of collected names */ void displayitems(struct item *); /* display collected items to standard output */ void openserialport(void); /* open the serial port */ void closeserialport(void); /* close the serial port */ void writeserport( char *seq, size_t totalbytes ); void getenter(void); /* just get an key press */ void noinfo(void); /* display error message */ void ioerror(void); /* display error message */ void memerror(void); /* display error message */ void quitz88(void); /* quit Server (popdown) */ void devices_stdout(void); /* display Z88 devices to standard output */ void directories_stdout(char *); /* display Z88 directories to standard output */ void checkfile_stdout(char *); /* display 'Yes' to stdout if file exists on Z88 */ void getdate_stdout(char *); /* display update date stamp of Z88 file */ void setdate_stdout(int, char **); /* set Create & Update Date Stamp of Z88 file */ void getver_stdout(void); /* Get EazyLink Server Version and protocol level */ void filesize_stdout(char *filename); /* Get size of file in bytes */ void deletefile_stdout(char *filename); /* Delete file/directory */ void createdir_stdout(char *pathname); /* Create directory path on Z88 filing system */ void renamefile_stdout(int arguments, char **cmdline); void getdefaults_stdout(void); /* Get RAM defaults */ void getfreemem_stdout(void); /* Get total free memory in all RAM cards */ void getfreememcard_stdout(char *devnum); /* Get free memory on specified RAM card */ void getsystime_stdout(void); /* Get Z88 system Date/time (clock) */ void setclock_stdout(int arguments, char **cmdline); /* Set Z88 system Clock */ void sendfiles(int, char **); /* send files to Z88 */ void receivefiles(char *); /* receive files from Z88 */ void files_stdout(char *); /* display Z88 files to standard output */ void settranslation(char *); /* define translation mode during transfer */ void setconversion(char *); /* define linefeed conversion mode during transfer */ void reloadtratable(void); /* update translation table into Server on Z88 */ void receivefile(char *, char *); /* receive z88 file */ void receivefile_stdout(void); /* receive z88 file to standard output */ void receive(char *); /* receive z88 file to host file */ void backupfiles(char *); /* receive backup files from Z88 */ int helloz88(void); /* establish connection with Z88 */ int sendcommand(char *); /* send a command to Z88 */ int synchronize(void); /* synchronisation sequensing before commands */ int transferfile(char *, char *); /* transfer host file contents to Z88 */ int receivefilename(char *); /* receive Z88 filename */ short getbyte(void); /* get a byte from the serial port */ char getcommand(void); /* get a 2 byte command */ char *convz88flnm(char *); /* convert z88 filename to short host filename */ char *convz88flnmpath(char *, char *); /* convert z88 filename to host filename (with path) */ char *convhostflnm(char *, char *); /* convert to short z88 filename, preceeded with z88 path */ char *convhostflnmpath(char *); /* convert host path filename to z88 filename */ char *removedevice(char *); /* remove device name from host path filename */ char *expandpath(char *buffer, char *wildcard); #ifdef MSDOS int createdir(char *hostfilename); int createpath(char *path); void scandir(char *directory, char *wildcard); void scanfiles(char **cmdline); #endif #ifdef UNIX void createdir(char *hostfilename); #endif /***************************************************************************** * GLOBAL VARIABLES *****************************************************************************/ int RECURSE=0; /* flag variable for directory scanning */ int serport; /* serial port file descriptor */ char copyright[] = "EazyLink v0.97, (c) 1995-98 InterLogic, 1998 Garry Lancaster"; char z88dev = '1'; /* default Z88 device is :RAM.1 */ #ifdef MSDOS extern int _fmode = O_BINARY; /* default MSDOS file I/O mode is binary */ struct item *msdosnames = NULL; /* anchor to linked list of names */ unsigned int Ibaud = 9600; unsigned int Ibaud_prev= 9600; unsigned char Iport=1; unsigned char Idbits=8; unsigned char Isbits=1; unsigned char Iparity=0; #endif #ifdef QDOS long channelid; /* QDOS channelid for serialport */ int (*_cmdwildcard)() = cmdexpand; /* command line expansion */ char _prog_name[] = "EazyLink"; char _version[] = "0.97"; char _copyright[] = "(c) InterLogic 1995-98, Garry Lancaster 1998"; void consetup_title(); void (*_consetup) () = consetup_title; int (*_readkbd)(chanid_t, timeout_t, char *) = readkbd_move; #endif /***************************************************************************** * Main entry of Link *****************************************************************************/ int main(int argc, char *argv[]) { int link_established,done=0; openserialport(); if ( argc == 1 ) { /* No command line arguments specified, use interactive mode */ puts(copyright); link_established = helloz88(); if ( link_established == 1) puts("Z88 was connected and ready to communicate..."); else ioerror(); } else { ++argv; --argc; while( (*argv)[0] == '-' && argc != 0) { if (strcmp(*argv,"-r")==0) { RECURSE = 1; } if (memcmp(*argv, "-d", 2) == 0) { if ((*argv)[2] >= '0' && (*argv)[2]<='3') { z88dev = (*argv)[2]; } else printf("'%c' is an illegal Z88 RAM device number.\n", (*argv)[2]); } ++argv; --argc; } if (argc == 0) { puts("No file transfer arguments."); exit(-1); } /* parse command line arguments */ do { switch((*argv)[0]) { case 'h': devices_stdout(); break; case 'q': quitz88(); break; case 'd': directories_stdout(++(*argv)); break; case 'n': files_stdout(++(*argv)); break; case 'f': checkfile_stdout(++(*argv)); break; case 'u': getdate_stdout(++(*argv)); break; case 'U': setdate_stdout(argc, argv); done = 1; break; case 'x': filesize_stdout(++(*argv)); break; case 't': settranslation(++(*argv)); break; case 'c': setconversion(++(*argv)); break; case 'z': reloadtratable(); break; case 'v': getver_stdout(); break; case 'e': deletefile_stdout(++(*argv)); break; case 'w': renamefile_stdout(argc, argv); done = 1; break; case 'y': createdir_stdout(++(*argv)); break; case 'g': getdefaults_stdout(); break; case 'm': getfreemem_stdout(); break; case 'M': getfreememcard_stdout(++(*argv)); break; case 'i': getsystime_stdout(); break; case 'p': setclock_stdout(argc, argv); done = 1; break; case 'r': receivefiles(++(*argv)); break; case 's': sendfiles(argc, argv); done = 1; break; case 'b': backupfiles(++(*argv)); break; default: printf("Unknown option: %s\n", *argv); done = 1; break; } ++argv; --argc; /* get next command line argument */ } while( !done && (*argv != NULL) ); } closeserialport(); return 0; } /***************************************************************************** * EazyLink Server Commands *****************************************************************************/ /***************************************************************************** * Display Z88 devices to standard output *****************************************************************************/ void devices_stdout(void) { struct item *devices; devices = getdevices(); if (devices == NULL) noinfo(); else { displayitems(devices); releaselist(devices); } } /***************************************************************************** * Display Z88 directories to standard output *****************************************************************************/ void directories_stdout(char *path) { struct item *directories; directories = getdirectories(path); if (directories == NULL) noinfo(); else { displayitems(directories); releaselist(directories); } } /***************************************************************************** * Display Z88 file names to standard output *****************************************************************************/ void files_stdout(char *path) { struct item *files; files = getfilenames(path); if (files == NULL) noinfo(); else { displayitems(files); releaselist(files); } } /***************************************************************************** * EazyLink Server V4.4 * Send a 'hello' to the Z88 and return 1 if Yes, or 0 if No *****************************************************************************/ int helloz88(void) { char hello[] = { 27, 'a', 0 }; /* 'Hello' command */ char reply; printf("Activate the EazyLink popdown on the Z88 and press "); getenter(); if ( sendcommand(hello) != -1) { if ( (reply = getcommand()) == 'Y' ) return 1; else return reply; } else return -1; } /***************************************************************************** * EazyLink Server V4.4 * Send a 'quit' Server command to the Z88 *****************************************************************************/ void quitz88(void) { char quit[] = { 27, 'q', 0 }; /* 'quit' command */ if ( sendcommand(quit) != -1) { if ( getcommand() == 'Y' ) puts("EazyLink Server aborted"); else puts("EazyLink Server not connected"); } } /***************************************************************************** * EazyLink Server V4.4 * Get Z88 devices. *****************************************************************************/ struct item *getdevices() { char devices[] = { 27, 'h', 0 }; if ( sendcommand(devices) != -1) return collectitems(); else return NULL; } /***************************************************************************** * EazyLink Server V4.4 * Get directories in defined path, directories are returned in linked list *****************************************************************************/ struct item *getdirectories(char *path) { char flnmcmd[] = { 27, 'd', 0 }; char escz[] = { 27, 'Z', 0 }; if ( sendcommand(flnmcmd) != -1) { writeserport( path, strlen(path)); writeserport( escz, strlen(escz)); return collectitems(); } else return NULL; } /***************************************************************************** * EazyLink Server V4.4 * Get filenames in defined path, filenames are returned in linked list *****************************************************************************/ struct item *getfilenames(char *path) { char flnmcmd[] = { 27, 'n', 0 }; char escz[] = { 27, 'Z', 0 }; if ( sendcommand(flnmcmd) != -1) { writeserport( path, strlen(path)); writeserport( escz, strlen(escz)); return collectitems(); } else return NULL; } /***************************************************************************** * EazyLink Server V4.4 * Define translation mode during file transfer *****************************************************************************/ void settranslation(char *cmd) { char transon[] = { 27, 't', 0 }; char transoff[] = { 27, 'T', 0 }; int sent=0; if ( *cmd++ == '=' ) { switch(*cmd) { case '0': sent = sendcommand(transoff); break; case '1': sent = sendcommand(transon); break; default: puts("illegal translation parameter"); } if ( sent == -1 ) ioerror(); } else { puts("parameter syntax error."); puts("syntax: t=0 | t=1"); } } /***************************************************************************** * EazyLink Server V4.4 * Define linefeed mode during file transfer *****************************************************************************/ void setconversion(char *cmd) { char convon[] = { 27, 'c', 0 }; char convoff[] = { 27, 'C', 0 }; int sent=0; if ( *cmd++ == '=' ) { switch(*cmd) { case '0': sent = sendcommand(convoff); break; case '1': sent = sendcommand(convon); break; default: puts("illegal linefeed conversion parameter"); } if ( sent == -1 ) ioerror(); } else { puts("parameter syntax error."); puts("syntax: c=0 | c=1"); } } /***************************************************************************** * EazyLink Server V4.5 * Display 'Yes' to stdout if file exists on Z88, othwise 'No' . *****************************************************************************/ void checkfile_stdout(char *filename) { char chkfile[] = { 27, 'f', 0 }; char endofcmd[] = { 27, 'Z', 0 }; char f[256]; if (filename == NULL) { puts("No file name specified"); return; } strcpy(f, chkfile); strcat(f, filename); strcat(f, endofcmd); if ( sendcommand(f) != -1) { if ( getcommand() == 'Y' ) { puts("Yes"); } else { puts("No"); } } } /***************************************************************************** * EazyLink Server V4.5 * Get create and update date stamp of Z88 file and display to stdout. *****************************************************************************/ void getdate_stdout(char *filename) { char getdate[] = { 27, 'u', 0 }; char endofcmd[] = { 27, 'Z', 0 }; char f[256]; struct item *datestr; if (filename == NULL) { puts("No file name specified"); return; } strcpy(f, getdate); strcat(f, filename); strcat(f, endofcmd); if ( sendcommand(f) != -1) { datestr = collectitems(); if (datestr == NULL) noinfo(); else { displayitems(datestr); releaselist(datestr); } } } /***************************************************************************** * EazyLink Server V4.5 * Get size of Z88 file (in bytes) and display to stdout. *****************************************************************************/ void filesize_stdout(char *filename) { char getsize[] = { 27, 'x', 0 }; char endofcmd[] = { 27, 'Z', 0 }; char f[256]; struct item *sizestr; if (filename == NULL) { puts("No file name specified"); return; } strcpy(f, getsize); strcat(f, filename); strcat(f, endofcmd); if ( sendcommand(f) != -1) { sizestr = collectitems(); if (sizestr == NULL) noinfo(); else { displayitems(sizestr); releaselist(sizestr); } } } /***************************************************************************** * EazyLink Server V4.5 * Set create and update date stamp of Z88 file *****************************************************************************/ void setdate_stdout(int arguments, char **cmdline) { char setdate[] = { 27, 'U', 0 }; char datesep[] = { 27, 'N', 0 }; char endofcmd[] = { 27, 'Z', 0 }; char f[256]; if ( arguments < 3 ) { puts("Date stamp arguments no properly specified"); return; } ++(*cmdline); /* point at first char of filename */ strcpy(f, setdate); /* ESC U */ strcat(f, *cmdline); /* filename */ strcat(f, datesep); /* ESC N */ ++cmdline; strcat(f, *cmdline); /* Create Date stamp */ strcat(f, datesep); /* ESC N */ ++cmdline; strcat(f, *cmdline); /* Update Date stamp */ strcat(f, endofcmd); /* ESC Z */ if ( sendcommand(f) != -1) { if ( getcommand() == 'Y' ) { puts("Date Stamp updated"); } else { puts("Date Stamp not set"); } } } /***************************************************************************** * EazyLink Server V4.5 * Get EazyLink Server (main) Version and protocol level *****************************************************************************/ void getver_stdout(void) { char getver[] = { 27, 'v', 0 }; struct item *verstr; if ( sendcommand(getver) != -1) { verstr = collectitems(); if (verstr == NULL) noinfo(); else { displayitems(verstr); releaselist(verstr); } } } /***************************************************************************** * EazyLink Server V4.6 * Delete file/dir on Z88. *****************************************************************************/ void deletefile_stdout(char *filename) { char delfile[] = { 27, 'r', 0 }; char endofcmd[] = { 27, 'Z', 0 }; char f[256]; if (filename == NULL) { puts("No file name specified"); return; } strcpy(f, delfile); strcat(f, filename); strcat(f, endofcmd); if ( sendcommand(f) != -1) { if ( getcommand() == 'Y' ) { puts("File/directory deleted."); } else { puts("File/Directory not found or in use."); } } } /***************************************************************************** * EazyLink Server V4.6 * Remote updating of translation table * (reload and install translation table from Z88 filing system) *****************************************************************************/ void reloadtratable() { char reltratbl[] = { 27, 'z', 0 }; sendcommand(reltratbl); } /***************************************************************************** * EazyLink Server V4.7 * Create directory path on Z88. *****************************************************************************/ void createdir_stdout(char *pathname) { char creatdir[] = { 27, 'y', 0 }; char endofcmd[] = { 27, 'Z', 0 }; char f[256]; if (pathname == NULL) { puts("No directory path specified"); return; } strcpy(f, creatdir); strcat(f, pathname); strcat(f, endofcmd); if ( sendcommand(f) != -1) { if ( getcommand() == 'Y' ) { puts("Directory created."); } else { puts("Directory couldn't be created."); } } } /***************************************************************************** * EazyLink Server V4.7 * Rename file/directory on Z88. *****************************************************************************/ void renamefile_stdout(int arguments, char **cmdline) { char renmfile[] = { 27, 'w', 0 }; char sep[] = { 27, 'N', 0 }; char endofcmd[] = { 27, 'Z', 0 }; char f[256]; if ( arguments < 2 ) { puts("Filename/directory arguments not properly specified"); return; } ++(*cmdline); /* point at first char of filename */ strcpy(f, renmfile); /* ESC w */ strcat(f, *cmdline); /* filename (with explicit path) */ strcat(f, sep); /* ESC N */ ++cmdline; strcat(f, *cmdline); /* short filename (12+3, without path) */ strcat(f, endofcmd); /* ESC Z */ if ( sendcommand(f) != -1) { if ( getcommand() == 'Y' ) { puts("File/directory renamed."); } else { puts("File/directory not found or in use."); } } } /***************************************************************************** * EazyLink Server V4.7 * Get RAM defaults and display to std. output. *****************************************************************************/ void getdefaults_stdout() { char ramdef[] = { 27, 'g', 0 }; struct item *defaults; if ( sendcommand(ramdef) != -1) { defaults = collectitems(); if (defaults == NULL) noinfo(); else { displayitems(defaults); releaselist(defaults); } } } /***************************************************************************** * EazyLink Server V4.8 * Get Z88 system Date/Time (Clock) *****************************************************************************/ void getsystime_stdout() { char systime[] = { 27, 'e', 0 }; struct item *z88time; if ( sendcommand(systime) != -1) { z88time = collectitems(); if (z88time == NULL) noinfo(); else { displayitems(z88time); releaselist(z88time); } } } /***************************************************************************** * EazyLink Server V4.8 * Get free memory for all RAM cards *****************************************************************************/ void getfreemem_stdout() { char freemem[] = { 27, 'm', 0 }; struct item *membytes; if ( sendcommand(freemem) != -1) { membytes = collectitems(); if (membytes == NULL) noinfo(); else { displayitems(membytes); releaselist(membytes); } } } /***************************************************************************** * EazyLink Server V4.8 * Set Z88 System Clock *****************************************************************************/ void setclock_stdout(int arguments, char **cmdline) { char setclock[] = { 27, 'p', 0 }; char sep[] = { 27, 'N', 0 }; char endofcmd[] = { 27, 'Z', 0 }; char f[256]; if ( arguments < 2 ) { puts("Clock arguments not properly specified"); return; } ++cmdline; /* point at date string */ strcpy(f, setclock); /* ESC p */ strcat(f, *cmdline); /* date string */ strcat(f, sep); /* ESC N */ ++cmdline; strcat(f, *cmdline); /* time string */ strcat(f, endofcmd); /* ESC Z */ if ( sendcommand(f) != -1) { if ( getcommand() == 'Y' ) { puts("Z88 Clock updated"); } else { puts("Z88 NOT updated."); } } } /***************************************************************************** * EazyLink Server V5.0 * Get free memory for specific RAM card ("0", "1", "2", "3" or "-") *****************************************************************************/ void getfreememcard_stdout(char *devnum) { char freemem[] = { 27, 'M', 0 }; char endofcmd[] = { 27, 'Z', 0 }; struct item *membytes; char f[256]; strcpy(f, freemem); /* ESC M */ strcat(f, devnum); strcat(f, endofcmd); if ( sendcommand(f) != -1) { membytes = collectitems(); if (membytes == NULL) noinfo(); else { displayitems(membytes); releaselist(membytes); } } } /***************************************************************************** * Make a list of filenames from single spec (UNIX) *****************************************************************************/ #ifdef UMUSTBEJOKING /* NOT ACTUALLY DONE YET! */ struct dirent **makefilelist(char *filespec) { struct dirent **filelist; int n; n=scandir(filespec, &filelist, 0, alphasort); if (n<0) printf("Just a single file..."); return(filelist); } #endif /***************************************************************************** * Send file(s) to Z88 *****************************************************************************/ #ifdef UNIX void sendfiles(int arguments, char **cmdline) { char batchsend[] = { 27, 'b', 0 }; char endoffiles[] = { 27, 'Z', 0 }; char *z88spec, *z88flnm; char filename[256]; DIR *hostdirectory; if ( arguments == 1 ) { puts("No host filename specified"); return; } if ( sendcommand(batchsend) == -1 ) { ioerror(); return; } z88spec = strchr(*cmdline,'='); if (z88spec == NULL ) { /* no Z88 path or z88 filename, convert complete host filename as Z88 filename */ ++cmdline; /* point at first host filename */ while(*cmdline != NULL) { if ((hostdirectory=opendir(*cmdline)) != NULL) { closedir(hostdirectory); } else { strcpy(filename, *cmdline); /* copy filename to buffer */ z88flnm = convhostflnmpath(filename); /* convert to Z88 filename format */ transferfile(*cmdline, z88flnm); } ++cmdline; /* next host filename, if any */ } } else { ++z88spec; /* point at first char of z88 filename */ switch(arguments) { case 1: break; /* no host filenames specified */ case 2: ++cmdline; if ((hostdirectory=opendir(*cmdline)) != NULL) { closedir(hostdirectory); } else { transferfile(*cmdline, z88spec); /* transfer single host file to Z88 */ } break; default: ++cmdline; /* point at first host filename */ while(*cmdline != NULL) { if ((hostdirectory=opendir(*cmdline)) != NULL) { closedir(hostdirectory); } else { strcpy(filename, *cmdline); /* copy filename to buffer */ z88flnm = convhostflnm(filename, z88spec); /* convert to Z88 filename */ transferfile(*cmdline, z88flnm); } ++cmdline; /* next host filename, if any */ } } } writeserport(endoffiles, strlen(endoffiles)); /* signal End of files */ } #endif #ifdef QDOS void sendfiles(int arguments, char **cmdline) { char batchsend[] = { 27, 'b', 0 }; char endoffiles[] = { 27, 'Z', 0 }; char *z88spec, *z88flnm; char filename[256]; if ( arguments == 1 ) { puts("No host filename specified"); return; } if ( sendcommand(batchsend) == -1 ) { ioerror(); return; } z88spec = strchr(*cmdline,'='); if (z88spec == NULL ) { /* no Z88 path or z88 filename, convert complete host filename as Z88 filename */ ++cmdline; /* point at first host filename */ while(*cmdline != NULL) { strcpy(filename, *cmdline); /* copy filename to buffer */ z88flnm = convhostflnmpath(filename); /* convert to Z88 filename format */ transferfile(*cmdline, z88flnm); ++cmdline; /* next host filename, if any */ } } else { ++z88spec; /* point at first char of z88 filename */ switch(arguments) { case 1: break; /* no host filenames specified */ case 2: transferfile(*++cmdline, z88spec); /* transfer single host file to Z88 */ break; default: ++cmdline; /* point at first host filename */ while(*cmdline != NULL) { strcpy(filename, *cmdline); /* copy filename to buffer */ z88flnm = convhostflnm(filename, z88spec); /* convert to Z88 filename */ transferfile(*cmdline, z88flnm); ++cmdline; /* next host filename, if any */ } } } writeserport(endoffiles, strlen(endoffiles)); /* signal End of files */ } #endif #ifdef MSDOS void sendfiles(int arguments, char **cmdline) { char batchsend[] = { 27, 'b', 0 }; char endoffiles[] = { 27, 'Z', 0 }; char *z88spec, *z88flnm; char filename[_MAX_PATH], searchpath[_MAX_PATH], *endpath; struct item *fileitem; if ( arguments == 1 ) { puts("No host filename specified"); return; } if ( sendcommand(batchsend) == -1 ) { ioerror(); return; } z88spec = strchr(*cmdline,'='); if (z88spec == NULL ) { /* no Z88 path or z88 filename, convert complete host filename as Z88 filename */ ++cmdline; /* point at first host filename */ expandpath(searchpath, *cmdline); endpath = strrchr(searchpath, '\\'); scanfiles(cmdline); /* put MSDOS filenames in linked list */ fileitem = msdosnames; /* point at first filename */ while(fileitem != NULL) { strcpy(filename, fileitem->itemname); /* copy filename to buffer */ strcpy(filename, (filename + (endpath-searchpath))); /* remove searchpath */ z88flnm = convhostflnmpath(filename); /* convert to Z88 filename format */ transferfile(fileitem->itemname, z88flnm); fileitem = fileitem->nextitem; /* next host filename, if any */ } releaselist(msdosnames); /* remove collected filenames */ } else { ++z88spec; /* point at first char of z88 filename */ if (arguments>1) { ++cmdline; /* point at first host filename */ scanfiles(cmdline); /* put MSDOS filenames in linked list */ fileitem = msdosnames; /* point at first filename */ if (fileitem!=NULL) { /* filenames were found */ if (fileitem->nextitem==NULL) transferfile(fileitem->itemname, z88spec); /* transfer single host file to Z88 */ else { while(fileitem != NULL) { strcpy(filename, fileitem->itemname); /* copy filename to buffer */ z88flnm = convhostflnm(filename, z88spec); /* convert to Z88 filename */ transferfile(fileitem->itemname, z88flnm); fileitem = fileitem->nextitem; /* next host filename, if any */ } } releaselist(msdosnames); /* remove collected filenames */ } } } writeserport(endoffiles, strlen(endoffiles)); /* signal End of files */ } #endif /***************************************************************************** * Transfer file contents to Z88 *****************************************************************************/ int transferfile(char *hostfile, char *z88flnm) { char startfilename[] = { 27, 'N', 0 }; /* Beginning of Z88 filename */ char startfile[] = { 27, 'F', 0 }; /* Beginning of file contents */ char endoffile[] = { 27, 'E', 0 }; /* End of this file */ char escbyte[] = { 27, 27, 0 }; /* Send an ESC byte */ int fd, bytesread=0; unsigned char *buffer = NULL, *bufptr; printf("Sending '%s' file\n\tto '%s' ...\n", hostfile, z88flnm); fd = open(hostfile, O_RDONLY | O_BINARY, 0); if (fd == EOF) { printf("file '%s' couldn't be opened\n", hostfile); return -1; /* host file couldn't be opened */ } writeserport( startfilename, strlen(startfilename)); /* ESC N, filename header */ writeserport( z88flnm, strlen(z88flnm)); /* send Z88 filename */ writeserport( startfile, strlen(startfile)); /* ESC F, beginning of file */ buffer = malloc(BUFSIZE); if (buffer == NULL) { memerror(); return -1; } else { do { bytesread = read(fd, buffer, BUFSIZE); if(bytesread) { bufptr = buffer; while(bytesread--) { if (*bufptr == 27) writeserport( escbyte, strlen(escbyte)); else writeserport( (char *) bufptr, 1U); ++bufptr; } } } while(bytesread); } writeserport( endoffile, strlen(endoffile)); /* ESC E, signal End Of File */ if (buffer != NULL) free(buffer); /* release file transfer buffer */ close(fd); /* close hostfile */ return 1; } /***************************************************************************** * Receive files from Z88, defined by wildcard parameter *****************************************************************************/ void receivefiles(char *wildcard) { char sendfiles[] = { 27, 's', 0 }; /* Receive files from Z88 */ char endofwc[] = { 27, 'Z', 0 }; /* End of wildcard */ char z88filename[256]; /* buffer for received filename */ char *hostpath; short iostatus, byte; if ( sendcommand(sendfiles) == -1 ) { ioerror(); return; } hostpath = strchr(wildcard,'='); if (hostpath != NULL) { *hostpath = '\0'; ++hostpath; /* point at first char of host pathname */ } writeserport( wildcard, strlen(wildcard)); /* filename wildcard */ writeserport( endofwc, strlen(endofwc)); /* terminate wildcard */ for(;;) { iostatus = receivefilename(z88filename); switch(iostatus) { case 0: return; /* ESC Z received, end of files */ case -1: ioerror(); return; case 1: if (hostpath != NULL) receivefile(z88filename, hostpath); else receivefile_stdout(); break; } } } /***************************************************************************** * Receive backup files from Z88, defined by wildcard parameter *****************************************************************************/ void backupfiles(char *wildcard) { char sendfiles[] = { 27, 'k', 0 }; /* Receive files from Z88 */ char endofwc[] = { 27, 'Z', 0 }; /* End of wildcard */ char z88filename[256]; /* buffer for received filename */ char *hostpath; short iostatus, byte; hostpath = strchr(wildcard,'='); if (hostpath != NULL) { *hostpath = '\0'; ++hostpath; /* point at first char of host pathname */ } else { puts("Syntax error: host path is missing"); return; } if ( sendcommand(sendfiles) == -1 ) { ioerror(); return; } writeserport( wildcard, strlen(wildcard)); /* filename wildcard */ writeserport( endofwc, strlen(endofwc)); /* terminate wildcard */ for(;;) { iostatus = receivefilename(z88filename); switch(iostatus) { case 0: return; /* ESC Z received, end of files */ case -1: ioerror(); return; case 1: receivefile(z88filename, hostpath); break; } } } /***************************************************************************** * Receive Z88 filename or ESC Z (end of files) *****************************************************************************/ int receivefilename(char *z88filename) { short byte=0, timeout=0; for(;;) { switch(getbyte()) { case -1: if (timeout++ == 10) return -1; else break; case 27: switch(getbyte()) { case -1: return -1; case 'Z': return 0; /* End of files */ case 'N': while(byte != 27) { byte = getbyte(); if (byte == 27) { getbyte(); *z88filename = '\0'; } else *z88filename++ = byte; } return 1; } } } } /***************************************************************************** * Receive z88 file and store it at *****************************************************************************/ void receivefile(char *z88filename, char *hostpath) { char *hostfilename; printf("Receiving '%s' file\n", z88filename); if (*hostpath=='\0' || *hostpath=='.') hostfilename = convz88flnm(z88filename); /* convert to short host filename */ else hostfilename = convz88flnmpath(z88filename, hostpath); /* convert z88 filename and preceed with specified host path */ printf("\tto '%s' ...\n", hostfilename); receive(hostfilename); } /***************************************************************************** * Receive z88 file to host *****************************************************************************/ void receive(char *hostfilename) { int hostfile, dirpath, byteread; short byte; char *buffer; #ifdef UNIX createdir(hostfilename); hostfile = creat(hostfilename, 0644); #endif #ifdef MSDOS dirpath = createdir(hostfilename); /* create path of hostfilename */ if (dirpath == 1) hostfile = creat(hostfilename, S_IREAD | S_IWRITE); else hostfile = EOF; #endif #ifdef QDOS hostfile = creat(hostfilename, 0); #endif if (hostfile == EOF) { printf("'%s' couldn't be created.\ntransfer to void...\n", hostfilename); for(;;) { if (getbyte() == 27) { switch(getbyte()) { case 'E': return; /* End of file */ case 27: break; /* ignore ESC byte */ case -1: return; } } } } else { buffer = malloc(BUFSIZE); if (buffer == NULL) { memerror(); close(hostfile); remove(hostfilename); /* delete empty file */ } else { byteread = 0; byte = 0; while(byte != EOF) { if (byteread == BUFSIZE) { write(hostfile, buffer, BUFSIZE); /* flush buffer */ byteread = 0; } if ((byte = getbyte()) == 27) { switch(getbyte()) { case 'E': byte = EOF; break; /* End of file */ case 27: buffer[byteread++] = 27; /* ESC byte */ break; default: byte = EOF; } } else buffer[byteread++] = byte; } if (byteread) write(hostfile, buffer, byteread); /* flush buffer */ close(hostfile); free(buffer); } } } #ifdef UNIX void createdir(char *hostfilename) { char *hostpathptr,*segptr; hostpathptr=hostfilename; while ((segptr=strchr(hostpathptr,'/')) != NULL) { *segptr='\0'; mkdir(hostfilename, 0775); *segptr='/'; hostpathptr=++segptr; } } #endif #ifdef MSDOS int createdir(char *hostfilename) { char drive[_MAX_DRIVE]; char dir[_MAX_DIR]; char file[_MAX_FNAME]; char ext[_MAX_EXT]; char dirpath[_MAX_PATH]; if (expandpath(dirpath, hostfilename) == NULL) return 0; _splitpath(dirpath, drive, dir, file, ext); /* split the string to separate elems */ strcpy(dirpath, drive); strcat(dirpath, dir); /* now, the buffer contains only drive and directory path */ dirpath[strlen(dirpath)-1] = '\0'; /* remove end '\' of path */ return createpath(dirpath); } int createpath(char *path) { char tmppath[_MAX_PATH], *parentdir; DIR *dir; strcpy(tmppath, path); /* get a copy of the current path */ if ((dir = opendir(tmppath)) == NULL) { parentdir = strrchr(tmppath, '\\'); /* get pointer to beginning of parent dir */ if (parentdir == NULL) return 1; /* reached drive identifier, create root dir */ else { *parentdir = '\0'; if ( createpath(tmppath) == 1) { /* parent directory exists or created */ if (mkdir(path) == 0) return 1; /* current directory created */ else return 0; } else return 0; /* parent directory couldn't be created */ } } else { closedir(dir); return 1; /* this directory path exist, return */ } } #endif /***************************************************************************** * Receive z88 file to standard output *****************************************************************************/ void receivefile_stdout(void) { short byte; for(;;) { byte = getbyte(); if (byte == 27) { switch(getbyte()) { case 'E': return; /* End of file */ case 'B': break; /* ignore ESC byte */ } } else putchar(byte); } } /***************************************************************************** * Convert z88 filename to short host file name *****************************************************************************/ #ifdef UNIX char *convz88flnm(char *filename) { short i; for (i=strlen(filename)-1; filename[i] != '/'; i--); return(filename+i+1); } #endif #ifdef QDOS char *convz88flnm(char *filename) { short i; char *extptr; /* i will index beginning of short filename */ for(i=strlen(filename)-1; filename[i] != '/'; i--); ++i; /* index first char of filename */ extptr = strchr(filename+i, '.'); /* point at extension separator */ if (extptr != NULL) *extptr = EXTEN; /* convert extension separator */ return (filename+i); } #endif #ifdef MSDOS char *convz88flnm(char *filename) { short i; char *extptr, *shortname; /* i will index beginning of short filename */ for(i=strlen(filename)-1; filename[i] != '/'; i--); shortname = (filename+i+1); /* point at first char of short filname */ extptr = strchr(shortname, '.'); /* point at extension separator */ if (extptr != NULL) { if (extptr-shortname > 8) /* short filename > 8 */ strcpy((shortname+8),extptr); /* truncate with extension */ } else if (strlen(shortname) > 8) /* filename > 8 characters */ shortname[8] = '\0'; /* truncated. */ return shortname; } #endif /***************************************************************************** * Convert UNIX filename segment to standard Z88 12.3 format *****************************************************************************/ #ifdef UNIX char *convhostsegment(char *hostsegment) { char shortsegment[256]; int i; char *extptr; strcpy(shortsegment,hostsegment); if (strchr(shortsegment,'.') == NULL) { /* if no extensions */ shortsegment[12]='\0'; /* ensure filename is max 12 chars */ } else { /* at least one extension exists */ for (i=0; hostsegment[i] != '.'; i++); if (i>12) { /* if name part is larger than 12 chars */ strcpy(shortsegment+12,hostsegment+i); /* move ext up */ i=12; } if ((extptr=strchr(shortsegment+i+1,'.')) != NULL) *extptr='\0'; shortsegment[i+4]='\0'; /* ensure ext is max 3 chars */ } strcpy(hostsegment,shortsegment); return hostsegment; } #endif /***************************************************************************** * Convert host filename to short z88 file name, preceeded with Z88 path *****************************************************************************/ #ifdef UNIX char *convhostflnm(char *hostfilename, char *z88path) { int i; char z88filename[256]; strcpy(z88filename,z88path); for (i=strlen(hostfilename)-1; (i>=0) && (hostfilename[i] != '/'); i--); strcat(z88filename,convhostsegment(hostfilename+i+1)); strcpy(hostfilename,z88filename); return hostfilename; } #endif #ifdef QDOS char *convhostflnm(char *hostfilename, char *z88path) { int index; char z88filename[256]; strcpy(z88filename, z88path); /* first preceed with z88 device and path */ /* in QDOS '_' is used freely. An extension doesn't really exist */ for(index = strlen(hostfilename)-1; (index>=0) && (hostfilename[index]!='_'); index--); if (index != 0) { if ( (strlen(hostfilename)-index) <= 4 ) { hostfilename[index] = '.'; /* emulate an Z88 extension */ /* get next separator, if any, that is start of short filename */ for(--index; (index>=0) && (hostfilename[index]!='_'); index--); } } strcat(z88filename, (hostfilename+index+1)); /* add short filename */ strcpy(hostfilename, z88filename); /* overwrite host filename with Z88 filename */ return hostfilename; } #endif #ifdef MSDOS char *convhostflnm(char *hostfilename, char *z88path) { int index; char z88filename[256]; strcpy(z88filename, z88path); /* first preceed with z88 device and path */ for(index=strlen(hostfilename)-1; hostfilename[index] != '\\'; index--); strcat(z88filename, (hostfilename+index+1)); /* add short filename */ strcpy(hostfilename, z88filename); /* overwrite host filename with Z88 filename */ return hostfilename; } #endif /***************************************************************************** * Convert host filename to z88 file name *****************************************************************************/ #ifdef UNIX char *convhostflnmpath(char *hostfilename) { char hostpath[256],convertedpath[256]; char *hostpathptr,*segptr; strcpy(hostpath,hostfilename); strcpy(convertedpath,""); hostpathptr=hostpath; while ((segptr=strchr(hostpathptr,'/')) != NULL) { *segptr='\0'; strcat(convertedpath,convhostsegment(hostpathptr)); strcat(convertedpath,"/"); hostpathptr=++segptr; } strcat(convertedpath,convhostsegment(hostpathptr)); strcpy(hostfilename, ":RAM.x/"); hostfilename[5] = z88dev; /* define device number */ strcat(hostfilename, convertedpath); /* add argument filename */ return hostfilename; } #endif #ifdef QDOS char *convhostflnmpath(char *hostfilename) { short index; char *idptr; /* remove device name and path, if any, and replace with explicit Z88 device */ hostfilename = removedevice(hostfilename); /* convert extension identifier, assume only one from end of filename */ for(index=strlen(hostfilename)-1; index--;) { if ( (hostfilename[index] == '_') && ((strlen(hostfilename)-index) <= 4 )) { hostfilename[index] = '.'; break; } } /* convert path identifiers */ while((idptr = strchr(hostfilename, '_')) != NULL) *idptr = '/'; if (hostfilename[0] != '/') { for(index=strlen(hostfilename)+1; index>=0; index--) /* move path one character rightward */ hostfilename[index+1] = hostfilename[index]; hostfilename[0] = '/'; } return hostfilename; } #endif #ifdef MSDOS char *convhostflnmpath(char *hostfilename) { short index; char *idptr; /* remove device name and path, if any, and replace with explicit Z88 device */ hostfilename = removedevice(hostfilename); /* convert path identifiers */ while((idptr = strchr(hostfilename, '\\')) != NULL) *idptr = '/'; return hostfilename; } #endif #ifdef MSDOS char *expandpath(char *buffer, char *wildcard) { return _fullpath(buffer, wildcard, _MAX_PATH); } #endif #ifdef MSDOS /* get command line wildcard argument, extend it to absolute path, * and parse filing system for matching files. * All files are put into a linked list, anchored by the * global variable */ void scanfiles(char **cmdline) { int i; char buf[128], wildcard[32]; expandpath(buf, *cmdline); /* get full path of command line parameter */ /* i will index beginning of short filename */ for(i=strlen(buf)-1; buf[i] != '\\'; i--); strcpy(wildcard, (buf+i+1)); /* get wildcard */ buf[i+1] = '\0'; /* path is isolated from wildcard */ msdosnames = NULL; /* initiate anchor to linked list */ scandir(buf, wildcard); /* create list of filenames */ } #endif #ifdef MSDOS /* scan specified directory by wildcard, * and put all found names in linked list */ void scandir(char *directory, char *wildcard) { struct ffblk ff; int done; char buf[_MAX_PATH], allfiles[] = "*.*"; strcpy(buf, directory); strcat(buf, wildcard); /* clone wildcard for this directory */ done = findfirst(buf, &ff, FA_NORMAL); /* first search for normal files */ while (!done) { strcpy(buf, directory); strcat(buf, ff.ff_name); /* new filename */ newitem(buf, &msdosnames); /* added to linked list */ done = findnext(&ff); } strcpy(buf, directory); strcat(buf, allfiles); /* then search for directories in this directory */ if (RECURSE) { done = findfirst(buf, &ff, FA_DIREC); while (!done) { if ( ff.ff_attrib & FA_DIREC ) { /* found a directory */ if ( strcmp(ff.ff_name,".")!=0 && strcmp(ff.ff_name,"..")!=0 ) { strcpy(buf, directory); strcat(buf, ff.ff_name); /* new search path */ strcat(buf, "\\"); scandir(buf, wildcard); /* find new files in sub-directory */ } } done = findnext(&ff); } } } #endif /***************************************************************************** * Remove device name from host filename path, if present *****************************************************************************/ #ifdef QDOS char *removedevice(char *path) { char dev[4],tmppath[256]; int index; memcpy(dev, path, 3); dev[3] = '\0'; for(index=2; index>=0; index--) dev[index] = tolower(dev[index]); /* lower case */ if( memcmp(dev,"ram",3)!=0 && memcmp(dev,"flp",3)!=0 && memcmp(dev,"win",3)!=0 && memcmp(dev,"dev",3)!=0 ) ; else { if ( isdigit(path[3]) && (path[4]=='_')) { strcpy(path, path+5); /* skip 3 letter device name, drive number and '_' */ } } strcpy(tmppath, ":RAM.x/"); tmppath[5] = z88dev; /* define device number */ strcat(tmppath, path); /* add argument filename */ strcpy(path, tmppath); /* overwrite old filename with new */ return path; } #endif #ifdef MSDOS /* remove MSDOS device name */ char *removedevice(char *path) { char dev[4], tmppath[_MAX_PATH]; int index; if (isalpha(path[0]) && path[1]==':' && path[2]=='\\') strcpy(path, path+2); /* skip 2 letter device name, e.g. C: */ strcpy(tmppath, ":RAM.x"); tmppath[5] = z88dev; /* define device number */ strcat(tmppath, path); /* add argument filename */ strcpy(path, tmppath); /* overwrite old filename with new */ return path; /* return new filename */ } #endif /***************************************************************************** * Convert z88 filename to host file name with path *****************************************************************************/ #ifdef UNIX char *convz88flnmpath(char *z88filename, char *hostpath) { char hostfilename[256]; strcpy(hostfilename,hostpath); strcat(hostfilename,z88filename+7); return strcpy(z88filename,hostfilename); } #endif #ifdef QDOS char *convz88flnmpath(char *z88filename, char *hostpath) { char hostfilename[256]; char *idptr; /* convert extension identifiers */ while((idptr = strchr(z88filename, '.')) != NULL) *idptr = EXTEN; /* convert path identifiers */ while((idptr = strchr(z88filename, '/')) != NULL) *idptr = PATHSEP; strcpy(hostfilename, hostpath); /* preceed with host path */ strcat(hostfilename, z88filename+7); /* then add new filename without :RAM.#/ */ /* overwrite old Z88 filename with new host filename */ return strcpy(z88filename, hostfilename); } #endif #ifdef MSDOS char *convz88flnmpath(char *z88filename, char *hostpath) { char hostfilename[256]; char *idptr; /* convert path identifiers */ while((idptr = strchr(z88filename, '/')) != NULL) *idptr = PATHSEP; strcpy(hostfilename, hostpath); /* preceed with host path */ strcat(hostfilename, z88filename+7); /* then add new filename without :RAM.#/ */ /* overwrite old Z88 filename with new host filename */ return strcpy(z88filename, hostfilename); } #endif /***************************************************************************** * Open the serial port *****************************************************************************/ #ifdef UNIX void openserialport() { struct termios serios; short i; char *envpar; envpar=getenv("EAZYLINK_COMPORT"); if (envpar == NULL) envpar=SERDEVICE; if ((serport=open(envpar, O_RDWR, 0))<0) { printf("Couldn't open %s\n",envpar); exit (-1); } tcgetattr(serport, &serios)<0; serios.c_cflag = CREAD | CS8 | CLOCAL | CRTSCTS; serios.c_oflag = 0; serios.c_iflag = IGNPAR; serios.c_lflag = 0; for (i=0; iitemname = malloc(strlen(name)+1); if (n->itemname == NULL) { puts("Insufficient memory to run Link"); exit(-1); } else strcpy(n->itemname, name); n->nextitem = NULL; } return n; } /***************************************************************************** * Add new collected item to the end of list (or the first in the list) *****************************************************************************/ void newitem(char *name, struct item **list) { struct item *itemptr; if (strlen(name) == 0) return; /* ignore empty names */ if (*list == NULL) *list = allocitem(name); /* first name in list */ else { itemptr = *list; while( itemptr->nextitem != NULL ) itemptr = itemptr->nextitem; itemptr->nextitem = allocitem(name); /* new name added to list */ } } /***************************************************************************** * Display all collected items from the linked list *****************************************************************************/ void displayitems(struct item *list) { while (list != NULL) { puts(list->itemname); list = list->nextitem; } } /***************************************************************************** * Release the linked list of collected items (allocated memory) *****************************************************************************/ void releaselist(struct item *list) { struct item *itemptr; while( list != NULL ) { itemptr = list; list = list->nextitem; free(itemptr->itemname); free(itemptr); } } /***************************************************************************** * Display "No information received" error message *****************************************************************************/ void noinfo(void) { puts("No information received!"); } /***************************************************************************** * Display "Z88 is not responding" error message *****************************************************************************/ void ioerror() { puts("Z88 is not responding!"); } /***************************************************************************** * Display "Insuffient memory to run Link" error message *****************************************************************************/ void memerror() { puts("Insufficient memory to run Link!"); }