/* XSEND - Generates command files for MS-DOS Kermit, ftp, and other PC file transfer programs, to send and replicate tree-structured file systems. Mon, 4 Mar 91 - Frank da Cruz, Columbia University Minor corrections to syntax of constructed Kermit commands. Fri, 21 Apr 89 - Vace Kundakci, Columbia University Version 0.5V add tftp (and other) support and parse switches on the arg line Thu, 20 Apr 89 - Vace Kundakci, Columbia University Version 0.4V eliminate full path specification to server and add cd .. Program created by, and all previous edits by, Mark Zinzow: Wednesday, March 30, 1988 Version 0.4 added blank lines for server cwd password Saturday, November 21, 1987 Version 0.3 added kludged turbo dir functions for IBM & Microsoft C Version 0.2 attempt to do above with far pointers to ffblk failed. Version 0.1 by Mark S. Zinzow (MARKZ@UIUCVMD.BITNET or markz@vmd.cso.uiud.edu) Program to generate TAKE (script) files for MS-DOS Kermit to allow it to send files and directories to a server over entire tree branches or disks. Change directory to the desired directory in which you wish all files and subdirectories copied. Then run XSEND redirecting the output with the dos redirection symbol ">". (e.g. C:>XSEND >takeme) Then establish a connection to the remote system with kermit and put the remote system in server mode. Then just take the take file on the local system. If you wish to avoid the password prompt on the remote cwd commands use MS-Kermit 2.30/A or later and redirect the takeme file into it. (For example KERMIT #ifdef __TURBOC__ #include #endif #include #include #ifndef __TURBOC__ /* from Turbo errno.h */ #define ENOENT 2 /* No such file or directory */ #define ENMFILE 18 /* No more files */ extern int errno; /* From turbo dir.h */ struct ffblk { char ff_reserved[21]; char ff_attrib; unsigned ff_ftime; unsigned ff_fdate; long ff_fsize; char ff_name[13]; }; /* From Turbo dos.h */ #define FA_RDONLY 0x01 /* Read only attribute */ #define FA_HIDDEN 0x02 /* Hidden file */ #define FA_SYSTEM 0x04 /* System file */ #define FA_LABEL 0x08 /* Volume label */ #define FA_DIREC 0x10 /* Directory */ #define FA_ARCH 0x20 /* Archive */ #endif #define FILEALL 0xF7 #define FILENONE 0x16 #define MAXDIRLEN 84 /* maximum string length for path strings */ /* the dos maximum is 64 bytes */ #ifdef __TURBOC__ int ls (char *twd); #endif char *comm; char *move; char *md; char *cd; char opc; char hn[64]; char fn[13]; int vflag; int cwdlen; main (argc,argv) int argc; char *argv[]; { int i; char cwd[MAXDIRLEN]; /* string to hold Current Working Directory */ char pn[MAXDIRLEN]; char c[MAXDIRLEN]; opc = 'k'; strcpy(hn,""); strcpy(fn,"*.*"); strcpy(pn,""); md = "mkdir"; cd = "cd"; comm = "rem"; vflag = 0; for (i = 1; i < argc; i++) { strcpy(c,argv[i]); if (c[0] == '-') { switch(c[1]) { case 'g': case 'p': case 'm': case 'z': case 'l': case 'c': case 'k': opc = c[1]; strcpy(pn,&c[2]); break; case 'h': strcpy(hn,&c[2]); break; case 'v': vflag = 1; break; case 'f': strcpy(fn,&c[2]); break; default: printf("xsend switches: ckmgpzlvf\n"); exit(0); } } else { printf("usage: xsend switches\n"); printf(" -k[path]: kermit commands (default)\n"); printf(" -c[path]: copy commands\n"); printf(" -m[path]: mkdir commands\n"); printf(" -z[path]: del and rmdir commands\n"); printf(" -l[path]: list full names\n"); printf(" -g[path]: tftp get commands\n"); printf(" -p[path]: tftp put commands\n"); printf(" -h: tftp to/from host\n"); printf(" -f: select files with name\n"); printf(" -v: verbose (applies for -cklz)\n"); exit(0); } } switch(opc) { case 'm': vflag = 0; break; case 'z': move = "del"; break; case 'c': move = "copy"; break; case 'l': move = "f"; break; case 'g': case 'p': if (hn[0] == '\0') { printf("no hostname"); exit(0); } move = "tftp"; vflag = 1; break; case 'k': md = "remote host mkdir"; cd = "remote cd"; move = "send"; comm = "echo"; break; } printf("%s XSEND Version 0.5V\n",comm); if (pn[0] == '\0') getcwd(cwd,MAXDIRLEN); else strcpy(cwd,pn); i = strlen(cwd) - 1; if (i >= 0 && cwd[i] == '\\') cwd[i] = '\0'; /* chop ending \ */ cwdlen = strlen(cwd); ls(cwd); } ls(twd) char twd[]; { char xwd[MAXDIRLEN]; char far *p; struct ffblk ffblk; int done; strcpy(xwd,twd); strcat(xwd,"\\"); strcat(xwd,fn); p = &xwd[0]; if (!vflag && (opc != 'm') && (opc != 'l')) printf("%s %s\n",move,xwd); done = findfirst(p,&ffblk,FILEALL) || !vflag; while (!done) { if (!(ffblk.ff_attrib & FILENONE)) { switch (opc) { case 'p': if (cwdlen == strlen(twd)) printf("tftp -p %s\\%s %s %s image\n", twd,ffblk.ff_name,hn,ffblk.ff_name); else printf("tftp -p %s\\%s %s %s\\%s image\n", twd,ffblk.ff_name,hn,&twd[cwdlen + 1], ffblk.ff_name); break; case 'g': printf("tftp -g %s\\%s %s %s image\n", twd,ffblk.ff_name,hn,ffblk.ff_name); break; case 'z': case 'c': case 'l': case 'k': printf("%s %s\\%s\n",move,twd,ffblk.ff_name); } } done = findnext(&ffblk); } strcpy(xwd,twd); strcat(xwd,"\\*.*"); p = &xwd[0]; done = findfirst(p,&ffblk,FILEALL); /* &ffblk seems to be near */ while (!done) { if ((ffblk.ff_attrib & FA_DIREC) && (ffblk.ff_name[0] != '.' )) { strcpy(xwd,twd); strcat(xwd,"\\"); strcat(xwd,ffblk.ff_name); if ((opc != 'l') && (opc != 'p') && (opc != 'z')) printf("%s %s\n",md,ffblk.ff_name); if (opc != 'l') printf("%s %s\n\n",cd,ffblk.ff_name); else if (!vflag) printf ("d %s\n",xwd); ls(xwd); if (opc != 'l') printf("%s ..\n",cd); if (opc == 'z') printf("rmdir %s\n",ffblk.ff_name); } done = findnext(&ffblk); } return; } # ifndef __TURBOC__ /* function written from description in Turbo reference and dos manual without turbo source for compatibility with other compiler(s?). I added far to the declarations as I can't figure out how to do this near and far as a general case. Perhaps some clever use of sizeof? */ findfirst(pathname, ffblk, attrib) char far *pathname; struct ffblk *ffblk; int attrib; { struct SREGS sregs; union REGS inregs, outregs; int result; char far *p; extern int errno; /* Set Disk Transfer Area to ffblk structure passed */ segread(&sregs); /* Set DTA wants DS:DX to point to */ inregs.x.dx = FP_OFF(ffblk); /* the disk transfer area to be set */ inregs.h.ah = 0x1a; /* Set Disk Transfer Area */ result = int86x(0x21,&inregs,&outregs,&sregs); sregs.ds = FP_SEG(pathname); /* FindFirst wants DS:DX to point */ inregs.x.dx = FP_OFF(pathname); /* to an ASCIIZ string */ inregs.x.cx = attrib; inregs.h.ah = 0x4e; /* FindFirst */ errno = int86x(0x21,&inregs,&outregs,&sregs); if (errno == ENOENT || errno == ENMFILE) return(-1); return(0); } int findnext(ffblk) struct ffblk far *ffblk; { struct SREGS sregs; union REGS inregs, outregs; int result; extern int errno; /* I use the current DS register as I can't figure out how to get a far address to a structure declared and passed, so I'm assuming near. My appologies for this brute force and ignorance (trial and error) solution. Please send me the more elegant method if you can get the compiler to do it! When declaring far *ffblk FP_SEG returned attrib! - mz */ /* Set Disk Transfer Area to ffblk structure passed */ segread(&sregs); inregs.x.dx = FP_OFF(ffblk); /* the disk transfer area to be set */ inregs.h.ah = 0x1a; /* Set Disk Transfer Area */ result = int86x(0x21,&inregs,&outregs,&sregs); inregs.h.ah = 0x4f; /* FindNext */ errno = int86x(0x21,&inregs,&outregs,&sregs); if (errno == ENMFILE) return(-1); return(0); } #endif