home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 3 Comm / 03-Comm.zip / CKPM5X_S.ZIP / CKOFIO.C < prev    next >
C/C++ Source or Header  |  1990-03-04  |  23KB  |  697 lines

  1. char *ckzv = "OS/2 file support, 30 Nov 88";
  2.  
  3. /* C K O F I O  --  Kermit file system support for OS/2 systems */
  4.  
  5. /*
  6.  Author: Chris Adie (C.Adie@uk.ac.edinburgh)
  7.  Copyright (C) 1988 Edinburgh University Computing Service
  8.  Permission is granted to any individual or institution to use, copy, or
  9.  redistribute this software so long as it is not sold for profit, provided this
  10.  copyright notice is retained.
  11. */
  12.  
  13. /*
  14. 26-Jan-90 C.P.Armstrong zsout, zsoutl and zsoutx modified to filter writes to 
  15.                         stdout.  This enables the strings to be written to the
  16.                         PM screen.
  17. */
  18.  
  19. #define INCL_BASE   /* This is needed to pull in the stuff from os2.h */
  20. #define INCL_AVIO
  21. #include <os2.h>            /* This pulls in a whole load of stuff */
  22.  
  23. /* Includes */
  24.  
  25. #include "ckcker.h"         /* Kermit definitions */
  26. #include <ctype.h>          /* Character types */
  27. #include <stdio.h>          /* Standard i/o */
  28. #include <fcntl.h>
  29. #include <io.h>             /* File io function declarations */
  30. #include <process.h>            /* Process-control function declarations */
  31. #include <string.h>         /* String manipulation declarations */
  32. #include <stdlib.h>         /* Standard library declarations */
  33. #include <sys\types.h>
  34. #include <sys\stat.h>
  35. #include <errno.h>          /* errno values */
  36. #include <direct.h>         /* Directory function declarations */
  37. #include "ckofns.h"
  38. #include "ckcdeb.h"         /* Typedefs, debug formats, etc */
  39. /* Defines */
  40.  
  41. #define MAXNAMLEN   255
  42. #define R_OK        4
  43. #define W_OK        2
  44. #define PIPESZ      16384
  45.                     /* Size of pipe for ZXCMD */
  46. #define STDOUT      1
  47.                     /* The handle, not the stream */
  48.  
  49. /* Some definitions */
  50.  
  51. extern int binary;
  52.  
  53. char *ckzsys = " OS/2";         /* Identify the OS */
  54.  
  55. char *DELCMD = "del ";          /* For file deletion */
  56. char *PWDCMD = "cd ";           /* For saying where I am */
  57. char *TYPCMD = "type ";         /* For typing a file */
  58. char *DIRCMD = "dir ";          /* For directory listing */
  59. char *WHOCMD = "";          /* Who's there? */
  60. char *SPACMD = "chkdsk ";       /* For space on disk */
  61. char *SPACM2 = "chkdsk ";       /* For space on disk */
  62.  
  63. /* Declarations */
  64.  
  65. FILE *fp[ZNFILS] = {            /* File pointers */
  66.     NULL, NULL, NULL, NULL, NULL, NULL, NULL };
  67.  
  68. #ifdef MAXPATHLEN
  69. #define CWDBL MAXPATHLEN
  70. #else
  71. #define CWDBL 100
  72. #endif
  73. #define MAXWLD  50
  74.  
  75. static long iflen = -1;         /* [fdc] Input file length */
  76. static long oflen = -1;         /* [fdc] Output file length */
  77.  
  78. /* (PWP) external def. of things used in buffered file input and output */
  79. extern CHAR zinbuffer[], zoutbuffer[];
  80. extern CHAR *zinptr, *zoutptr;
  81. extern int zincnt, zoutcnt;
  82.  
  83. static char cwdbuf[CWDBL+1];        /* Buffer for the current directory */
  84. static char nambuf[MAXNAMLEN+2];    /* Buffer for a filename */
  85. static char finddir[MAXNAMLEN+1];   /* Buffer for path of expanded files */
  86. static FILEFINDBUF findbuf[ MAXWLD ];   /* For list of files */
  87. static USHORT fcount;           /* Number of files in wild group */
  88. static PFILEFINDBUF findptr;
  89.  
  90. static RESULTCODES res;         /* For child process pid and result */
  91.  
  92.  
  93. /*
  94.   Functions (n is one of the predefined file numbers from ckcker.h):
  95.  
  96.    zopeni(n,name)   -- Opens an existing file for input.
  97.    zopeno(n,name)   -- Opens a new file for output.
  98.    zclose(n)        -- Closes a file.
  99.    zchdsk(c)        -- Change current disk.
  100.    zchin(n,&c)      -- Gets the next character from an input file.
  101.    zsout(n,s)       -- Write a null-terminated string to output file, buffered.
  102.    zsoutl(n,s)      -- Like zsout, but appends a line terminator.
  103.    zsoutx(n,s,x)    -- Write x characters to output file, unbuffered.
  104.    zchout(n,c)      -- Add a character to an output file, unbuffered.
  105.    zchki(name)      -- Check if named file exists and is readable, return size.
  106.    zchko(name)      -- Check if named file can be created.
  107.    znewn(name,s)    -- Make a new unique file name based on the given name.
  108.    zdelet(name)     -- Delete the named file.
  109.    zxpand(string)   -- Expands the given wildcard string into a list of files.
  110.    znext(string)    -- Returns the next file from the list in "string".
  111.    zxcmd(cmd)       -- Execute the command in a lower fork.
  112.    zclosf()         -- Close input file associated with zxcmd()'s lower fork.
  113.    zrtol(n1,n2)     -- Convert remote filename into local form.
  114.    zltor(n1,n2)     -- Convert local filename into remote form.
  115.    zchdir(dirnam)   -- Change working directory.
  116.    zfindfile(name)  -- Look down PATH for given file name.
  117.    zkself()         -- Kill self, log out own job.
  118.    zsattr(struc zattr *) -- Return attributes for file which is being sent.
  119.  */
  120.  
  121. /*  Z K S E L F  --  Kill Self  */
  122. void zkself() {              /* For "bye", but no guarantee! */
  123.     exit(0);            /* Kill all threads */
  124. }
  125.  
  126. /*  Z O P E N I  --  Open an existing file for input. */
  127. zopeni(n,name) int n; char *name; {
  128.     debug(F111," zopeni",name,n);
  129.     debug(F101,"  fp","",(int) fp[n]);
  130.     if (chkfn(n) != 0) return(0);
  131.     zincnt = 0;             /* (PWP) reset input buffer */
  132.     if (n == ZSYSFN) {          /* Input from a system function? */
  133.         debug(F110," invoking zxcmd",name,0);
  134.     return(zxcmd(name));        /* Try to fork the command */
  135.     }
  136.     if (n == ZSTDIO) {          /* Standard input? */
  137.     if (isatty(0)) {
  138.         ermsg("Terminal input not allowed");
  139.         debug(F110,"zopeni: attempts input from unredirected stdin","",0);
  140.         return(0);
  141.     }
  142.     fp[ZIFILE]=stdin;
  143.     setmode(fileno(stdin),O_BINARY);
  144.     return(1);
  145.     }
  146.     if (n == ZIFILE) fp[n] = fopen(name,"rb");      /* Binary mode */
  147.         else fp[n] = fopen(name,"r");           /* Text mode */
  148.     debug(F111," zopeni", name, (int) fp[n]);
  149.     if (fp[n] == NULL) perror("zopeni");
  150.     return((fp[n] != NULL) ? 1 : 0);
  151. }
  152.  
  153. /*  Z O P E N O  --  Open a new file for output.  */
  154. zopeno(n,name) int n; char *name; {
  155.     debug(F111," zopeno",name,n);
  156.     if (chkfn(n) != 0) return(0);
  157.     if ((n == ZCTERM) || (n == ZSTDIO)) {   /* Terminal or standard output */
  158.     fp[ZOFILE] = stdout;
  159.     debug(F101," fp[]=stdout", "", (int) fp[n]);
  160.     zoutcnt = 0;
  161.     zoutptr = zoutbuffer;
  162.     return(1);
  163.     }
  164.     if (n == ZOFILE) fp[n] = fopen(name,"wb");      /* Binary mode */
  165.         else fp[n] = fopen(name,"w");           /* Text mode */
  166.     if (fp[n] == NULL) {
  167.         perror("zopeno can't open");
  168.     }
  169.     zoutcnt = 0;        /* (PWP) reset output buffer */
  170.     zoutptr = zoutbuffer;
  171.     debug(F101, " fp[n]", "", (int) fp[n]);
  172.     return((fp[n] != NULL) ? 1 : 0);
  173. }
  174.  
  175. /*  Z C L O S E  --  Close the given file.  */
  176. /*  Returns 0 if arg out of range, 1 if successful, -1 if close failed.  */
  177. zclose(n) int n; {
  178.     int x, x2;
  179.     if (chkfn(n) < 1) return(0);    /* Check range of n */
  180.  
  181.     if ((n == ZOFILE) && (zoutcnt > 0)) /* (PWP) output leftovers */
  182.     x2 = zoutdump();
  183.  
  184.     if ((n == ZIFILE) && fp[ZSYSFN]) {  /* If system function */
  185.         x = zclosf();           /* do it specially */
  186.     } else {
  187.         if ((fp[n] != stdout) && (fp[n] != stdin)) x = fclose(fp[n]);
  188.     fp[n] = NULL;
  189.     }
  190.     iflen = -1;             /* Invalidate file length */
  191.     if (x == EOF)       /* if we got a close error */
  192.     return (-1);
  193.     else if (x2 < 0)        /* or an error flushing the last buffer */
  194.     return (-1);        /* then return an error */
  195.     else
  196.     return (1);
  197. }
  198.  
  199. /*  Z C H I N  --  Get a character from the input file.  */
  200. /*  Returns -1 if EOF, 0 otherwise with character returned in argument  */
  201. zchin(n,c) int n; char *c; {
  202.     int a;
  203.     /* (PWP) Just in case this gets called when it shoudn't */
  204.     if (n == ZIFILE)
  205.     return (zminchar());
  206.     /* if (chkfn(n) < 1) return(-1); */
  207.     a = getc(fp[n]);
  208.     if (a == EOF) return(-1);        /* Real end of file */
  209.     if (!binary && a==0x1A) return(-1);  /* Ctrl-Z marks eof for text mode*/
  210.     *c = a & 0377;
  211.     return(0);
  212. }
  213.  
  214. /*  Z C H D S K  --  Change currently selected disk */
  215. /* Returns -1 if error, otherwise 0 */
  216. zchdsk(c) char c; {
  217.     USHORT i = toupper(c) - 64;
  218.     return( DosSelectDisk(i) ? 0 : -1 );
  219. }
  220.  
  221. /*
  222.  * (PWP) (re)fill the buffered input buffer with data.  All file input
  223.  * should go through this routine, usually by calling the zminchar()
  224.  * macro (in ckcker.h).
  225.  */
  226.  
  227. zinfill() {
  228.     zincnt = fread(zinbuffer, sizeof (char), INBUFSIZE, fp[ZIFILE]);
  229.     if (zincnt == 0) return (-1); /* end of file */
  230.     zinptr = zinbuffer;    /* set pointer to beginning, (== &zinbuffer[0]) */
  231.     zincnt--;           /* one less char in buffer */
  232.     return((int)(*zinptr++) & 0377); /* because we return the first */
  233. }
  234.  
  235. /*  Z S O U T  --  Write a string to the given file, buffered.  */
  236. zsout(n,s) int n; char *s; {
  237.     /* if (chkfn(n) < 1) return(-1); */
  238.     if(fp[n]==stdout)
  239.         puts(s);
  240.     else
  241.         fputs(s,fp[n]);
  242.     return(0);
  243. }
  244.  
  245. /*  Z S O U T L  --  Write string to file, with line terminator, buffered  */
  246. zsoutl(n,s) int n; char *s; {
  247.     /* if (chkfn(n) < 1) return(-1); */
  248.     if(fp[n]==stdout)
  249.         {
  250.         puts(s);
  251.         puts("\r\n");
  252.         }
  253.     else
  254.         {
  255.         fputs(s,fp[n]);
  256.         fputs("\r\n",fp[n]);
  257.         }
  258.     return(0);
  259. }
  260.  
  261. /*  Z S O U T X  --  Write x characters to file, unbuffered.  */
  262. zsoutx(n,s,x) int n, x; char *s; 
  263.     {
  264.     /* if (chkfn(n) < 1) return(-1); */
  265.     if(fp[n]==stdout)
  266.         return(write_buf(s,x));
  267.     else
  268.         return(write(fileno(fp[n]),s,x));
  269.     }
  270.  
  271.  
  272. /*  Z C H O U T  --  Add a character to the given file.  */
  273. /*  Should return 0 or greater on success, -1 on failure (e.g. disk full)  */
  274. zchout(n,c) int n; char c; {
  275.     /* if (chkfn(n) < 1) return(-1); */
  276.     if (n == ZSFILE)
  277.         {
  278.         if(fp[n]==stdout)
  279.             return(write_buf(&c,1));
  280.         else
  281.             return(write(fileno(fp[n]),&c,1)); /* Use unbuffered for */
  282.         }                                      /* session log */
  283.     else 
  284.         {                               /* Buffered for everything else */
  285.         if (putc(c,fp[n]) == EOF)       /* If true, maybe there was an error */
  286.             return(ferror(fp[n])?-1:0); /* Check to make sure */
  287.         else                            /* Otherwise... */
  288.             return(0);                  /* There was no error. */
  289.         }
  290. }
  291.  
  292. /* (PWP) buffered character output routine to speed up file IO */
  293. zoutdump()
  294. {
  295.     if (zoutcnt <= 0) return (0); /* nothing to output */
  296.  
  297.     /* Debug message */
  298.     if(fp[ZOFILE]==stdout)
  299.         {
  300.         write_buf(zoutbuffer,zoutcnt);
  301.         zoutcnt = 0;        /* reset output buffer */
  302.         zoutptr = zoutbuffer;
  303.         return(0);
  304.         }
  305.     else
  306.         {
  307.         if (fwrite (zoutbuffer, 1, zoutcnt, fp[ZOFILE])) 
  308.             {
  309.             zoutcnt = 0;        /* reset output buffer */
  310.             zoutptr = zoutbuffer;
  311.             return(0);      /* things worked OK */
  312.             } 
  313.         else 
  314.             {
  315.             return(ferror(fp[ZOFILE])?-1:0); /* Check to make sure */
  316.             }
  317.         }
  318.     }
  319.  
  320. /*  C H K F N  --  Internal function to verify file number is ok  */
  321. /*
  322.  Returns:
  323.   -1: File number n is out of range
  324.    0: n is in range, but file is not open
  325.    1: n in range and file is open
  326. */
  327. chkfn(n) int n; {
  328.     switch (n) {
  329.     case ZCTERM:
  330.     case ZSTDIO:
  331.     case ZIFILE:
  332.     case ZOFILE:
  333.     case ZDFILE:
  334.     case ZTFILE:
  335.     case ZPFILE:
  336.     case ZSFILE:
  337.     case ZSYSFN: break;
  338.     default:
  339.         debug(F101,"chkfn: file number out of range","",n);
  340.         fprintf(stderr,"?File number out of range - %d\n",n);
  341.         return(-1);
  342.     }
  343.     return( (fp[n] == NULL) ? 0 : 1 );
  344. }
  345.  
  346. /*  Z C H K I  --  Check if input file exists and is readable  */
  347. /*
  348.   Returns:
  349.    >= 0 if the file can be read (returns the size).
  350.      -1 if file doesn't exist or can't be accessed,
  351.      -2 if file exists but is not readable (e.g. a directory file).
  352.      -3 if file exists but protected against read access.
  353. */
  354. long
  355. zchki(name) char *name; {
  356.     struct stat buf;
  357.     int x; long y;
  358.     x = stat(name,&buf);
  359.     if (x < 0) {
  360.     debug(F111,"zchki stat fails",name,errno);
  361.     return(-1);
  362.     }
  363.     x = buf.st_mode & S_IFMT;       /* Isolate file format field */
  364.     if ((x != 0) && (x != S_IFREG)) {
  365.     debug(F111,"zchki skipping:",name,x);
  366.     return(-2);
  367.     }
  368.     debug(F111,"zchki stat ok:",name,x);
  369.     if ((x = access(name,R_OK)) < 0) {  /* Is the file accessible? */
  370.     debug(F111," access failed:",name,x); /* No */
  371.         return(-3);         
  372.     } else {
  373.     iflen = buf.st_size;
  374.     debug(F111," access ok:",name,(int) iflen); /* Yes */
  375.     return( (iflen > -1) ? iflen : 0 );
  376.     }
  377. }
  378.  
  379. /*  Z C H K O  --  Check if output file can be created  */
  380. /*
  381.  Returns -1 if write permission for the file would be denied, 0 otherwise.
  382. */
  383. zchko(name) char *name; {
  384.     int x;
  385.     if (name[0]=='\0') return(-1);      /* If no filename, fail. */
  386.     x = access(name,W_OK);
  387.     if (x < 0  &&  errno==EACCES) {
  388.         debug(F111,"zchko access failed:",name,errno);
  389.     return(-1);
  390.     } else {
  391.     debug(F111,"zchko access ok:",name,x);
  392.     return(0);
  393.     }
  394. }
  395.  
  396. /*  Z D E L E T  --  Delete the named file.  */
  397. void zdelet(name) char *name; {
  398.     unlink(name);
  399. }
  400.  
  401. /*  Z R T O L  --  Convert remote filename into local form  */
  402. void zrtol(name,name2) char *name, *name2; {
  403. char *s,*r;
  404. int i;
  405.     i = 0;
  406.     s = name;
  407.     r = name2;
  408.     while ( *s && *s!='.' && i<8 ) {
  409.         *r++ = *s++;
  410.         i++;
  411.     }
  412.     *r++='.';
  413.     if (*s && *s!='.') {        /* Name too long */
  414.         s++;
  415.         while (*s && *s!='.') s++;
  416.     }
  417.     if (*s=='.') {
  418.         s++;
  419.         i = 0;
  420.         while (*s && i<3) {
  421.             *r++=*s++;
  422.             i++;
  423.         }
  424.     }
  425.     *r++='\0';
  426. }
  427.  
  428. /*  Z L T O R  --  Local TO Remote */
  429. /*  Convert filename from local format to common (remote) form.  */
  430. void zltor(name,name2) char *name, *name2; {
  431.     char work[100], *cp, *pp;
  432.     debug(F110,"zltor",name,0);
  433.     pp = work;
  434.     for (cp = name; *cp != '\0'; cp++) {    /* strip path name */
  435.         if ((*cp == '\\') || (*cp == ':')) pp = work;
  436.     else if (islower(*cp)) *pp++ = toupper(*cp); /* Uppercase letters */
  437.     else if (isupper(*cp) || isdigit(*cp) || (*cp == '.')) *pp++ = *cp;
  438.     else *pp++='X';
  439.     }
  440.     *pp = '\0';             /* Tie it off. */
  441.     strcpy(name2,work);
  442.     debug(F110," name2",name2,0);
  443. }
  444.  
  445. /*  Z C H D I R  --  Change directory  */
  446. zchdir(dirnam) char *dirnam; {
  447.     return((chdir(dirnam) == 0) ? 1 : 0);
  448. }
  449.  
  450. /*  Z G T D I R  --  Return pointer to user's current directory  */
  451. char *
  452. zgtdir() {
  453.     return(getcwd(cwdbuf,CWDBL));
  454. }
  455.  
  456. /*  Z X C M D -- Run a system command so its output can be read like a file */
  457. zxcmd(cmnd) char *cmnd; {
  458.     HFILE newstdout, childout;
  459.     HFILE piperdhdl, pipewrthdl;
  460.     char failname[80], command[255], name[14];
  461.     PCH env;
  462.     USHORT selenv;
  463.     USHORT junkoffset;
  464.     char *p1, *p2;
  465.     int i;
  466.     
  467.     if (cmnd == WHOCMD) return(0);  /* Won't do WHO command */
  468.     debug(F110,"zxcmd",cmnd,0);
  469.     /* Create the pipe */
  470.     if (i=DosMakePipe(&piperdhdl,&pipewrthdl,PIPESZ)) { /* Failed */
  471.         debug(F101,"DosMakePipe error ","",i);
  472.         return(0);
  473.     }
  474.     newstdout = 0xFFFF;
  475.         /* New handle for our standard output */
  476.     if (i=DosDupHandle(STDOUT,&newstdout)) {
  477.         debug(F101,"DosDupHandle error ","",i);
  478.         return(0);
  479.     }
  480.     /* Close the old one */
  481.     if (i=DosClose(STDOUT)) {
  482.         debug(F101,"DosClose error ","",i);
  483.         return(0);
  484.     }
  485.         /* Make stdout a duplicate of pipe write handle */
  486.     childout = STDOUT;
  487.     if (i=DosDupHandle(pipewrthdl,&childout)) {
  488.         debug(F101,"DosDupHandle error ","",i);
  489.         return(0);
  490.     }
  491.     /* Close the old one */
  492.     if (i=DosClose(pipewrthdl)) {
  493.         debug(F101,"DosClose error ","",i);
  494.         return(0);
  495.     }
  496. /* Prepare to call DosExecProg */
  497.     DosGetEnv(&selenv,&junkoffset);
  498.     env = MAKEP(selenv,0);
  499.     strcpy(name,"CMD.EXE");
  500.     strcpy(command,name);
  501.     p1=command+strlen(command)+1;
  502.     strcpy(p1,"/c ");
  503.     p1+=3;
  504.     p2=cmnd;
  505.     while ((*p1++ = *p2++) != '\0') ;
  506.     *p1++ = '\0';
  507.     *p1++ = '\0';           /* Must end with double 0 */
  508.     if (i=DosExecPgm(failname,80,EXEC_ASYNC,command,env,&res,name)) {
  509.         debug(F101,"DosExecPgm error ","",i);
  510.         return(0);
  511.     }
  512.     /* Close duplicate pipe write handle */
  513.     if (i=DosClose(STDOUT)) {
  514.         debug(F101,"DosClose error ","",i);
  515.         return(0);
  516.     }
  517. /* Restore stdout to standard output */
  518.     childout = STDOUT;
  519.     if (i=DosDupHandle(newstdout,&childout)) {
  520.         debug(F101,"DosDupHandle error ","",i);
  521.         return(0);
  522.     }
  523.     if (i=DosClose(newstdout)) {
  524.         debug(F101,"DosClose error ","",i);
  525.         return(0);
  526.     }
  527.     fp[ZIFILE] = fdopen(piperdhdl,"rb");
  528.     fp[ZSYSFN] = fp[ZIFILE];
  529.     return(1);
  530. }
  531.  
  532. /*  Z C L O S F  - wait for child process to terminate and close the pipe. */
  533. zclosf() {
  534.     USHORT pid;
  535.     int i;
  536.     
  537.     DosCwait(DCWA_PROCESSTREE,DCWW_WAIT,&res,&pid,res.codeTerminate);
  538.     fclose(fp[ZIFILE]);         /* Delete the pipe */
  539.     fp[ZIFILE] = fp[ZSYSFN] = NULL;
  540.     return(1);
  541. }
  542.  
  543. /*  Z X P A N D  --  Expand a wildcard string into an array of strings  */
  544. /*
  545.   Returns the number of files that match fn1, with data structures set up
  546.   so that first file (if any) will be returned by the next znext() call.
  547.   Returns -1 if insufficient room in the array.
  548. */
  549. zxpand(fn) char *fn; {
  550.     char *p, *q;
  551.     HDIR dirhdl = 1;
  552.  
  553.     fcount = MAXWLD;
  554.     findptr=findbuf;
  555.     if (DosFindFirst(fn, &dirhdl, 0, findbuf,
  556.         MAXWLD*sizeof(FILEFINDBUF), &fcount, 0L)) fcount=0;
  557.     if (fcount == MAXWLD) return(-1);   /* Insufficient space in array */
  558.     strcpy(finddir,fn);
  559.     p=q=finddir;
  560.     while (*p) {
  561.         *p = toupper(*p);   /* Make it upper case */
  562.         if (*p == ':') q=p+1;
  563.         else if (*p == '\\') q=p+1; /* Get path into finddir */
  564.         p++;
  565.     }
  566.     *q='\0';
  567.     return(fcount);
  568. }
  569.  
  570.  
  571. /*  Z N E X T  --  Get name of next file from list created by zxpand(). */
  572. /*
  573.  Returns >0 if there's another file, with its name copied into the arg string,
  574.  or 0 if no more files in list.  The name returned includes a path.
  575. */
  576. znext(fn) char *fn; {
  577.     strcpy(fn,finddir);
  578.     if (fcount-- > 0) strcat(fn,findptr->achName);
  579.     else *fn = '\0';
  580.     (char *) findptr += 24+strlen(findptr->achName);
  581.     debug(F111,"znext",fn,fcount+1);
  582.     return(fcount+1);
  583. }
  584.  
  585.  
  586. /*  Z N E W N  --  Make a new name for the given file  */
  587.  
  588. void znewn(fn,s) char *fn, **s; {
  589.     static char buf[MAXNAMLEN];
  590.     char *bp, *xp, *yp, *zp, ch, temp[14];
  591.     int d, i, n;
  592.     xp = bp = buf;
  593.     while (*fn) {           /* Copy name into buf */
  594.     ch = *bp++ = *fn++;
  595.     if ((ch == '\\') || (ch == ':')) xp=bp;
  596.     }
  597.     *bp = '\0';
  598.     yp = xp;
  599.     i = 1;
  600.     while (*yp && (*yp != '.')) {
  601.     yp++;
  602.     if (++i<=6) zp=yp;
  603.     }
  604.     /* zp points to the sixth character in the name, or yp, which ever occurs
  605.        first.  */
  606.     strcpy(temp,yp);            /* Copy extension, if any */
  607.     while (zp != xp+8) {
  608.         if ( zp < xp+5 ) *zp++='0';
  609.         else *zp++='?';         /* Pad out with wild cards */
  610.     }
  611.     strcpy(zp,temp);            /* Get the extension back */
  612.     n = zxpand(buf);            /* Expand the resulting wild name */
  613.     d = 0;              /* Index number */
  614.     while (znext(temp)) {
  615.         i = atoi(temp+5);
  616.         if (i > d) d = i;
  617.     }
  618.     sprintf(temp,"%03d",d+1);       /* get the number into a string */
  619.     xp[5]=temp[0];
  620.     xp[6]=temp[1];
  621.     xp[7]=temp[2];
  622.     *s = buf;
  623. }
  624.  
  625. /*  Z F I N D F I L E  --  Look down the PATH for a file */
  626.  
  627. char *zfindfile(name) char *name; {
  628. static char fname[255];
  629.  
  630.     if (DosSearchPath(3,"PATH",name,fname,255)) *fname = '\0';
  631.     return(fname);
  632. }
  633.  
  634. /*  Z S A T T R */
  635. /*
  636.  Fills in a Kermit file attribute structure for the file which is to be sent.
  637.  Returns 0 on success with the structure filled in, or -1 on failure.
  638.  If any string member is null, then it should be ignored.
  639.  If any numeric member is -1, then it should be ignored.
  640.  
  641.  NOTE - This function is just a dummy, and should be filled in by someone who
  642.  knows OS/2.
  643. */
  644. zsattr(xx) struct zattr *xx; {
  645.     long k;
  646.  
  647.     k = iflen % 1024L;          /* File length in K */
  648.     if (k != 0L) k = 1L;
  649.     xx->lengthk = (iflen / 1024L) + k;
  650.     xx->type.len = 0;           /* File type can't be filled in here */
  651.     xx->type.val = "";
  652.     xx->date.len = 0;           /* File creation date */
  653.     xx->date.val = "";
  654.     xx->creator.len = 0;        /* File creator */
  655.     xx->creator.val = "";
  656.     xx->account.len = 0;        /* File account */
  657.     xx->account.val = "";
  658.     xx->area.len = 0;           /* File area */
  659.     xx->area.val = "";
  660.     xx->passwd.len = 0;         /* Area password */
  661.     xx->passwd.val = "";
  662.     xx->blksize = -1L;          /* File blocksize */
  663.     xx->access.len = 0;         /* File access */
  664.     xx->access.val = "";
  665.     xx->encoding.len = 0;       /* Transfer syntax */
  666.     xx->encoding.val = 0;
  667.     xx->disp.len = 0;           /* Disposition upon arrival */
  668.     xx->disp.val = "";
  669.     xx->lprotect.len = 0;       /* Local protection */
  670.     xx->lprotect.val = "";
  671.     xx->gprotect.len = 0;       /* Generic protection */
  672.     xx->gprotect.val = "";
  673.     xx->systemid.len = 2;       /* System ID */
  674.     xx->systemid.val = "UO";        /* UO = OS/2 */
  675.     xx->recfm.len = 0;          /* Record format */
  676.     xx->recfm.val = "";
  677.     xx->sysparam.len = 0;       /* System-dependent parameters */
  678.     xx->sysparam.val = "";
  679.     xx->length = iflen;         /* Length */
  680.     return(0);
  681. }
  682.  
  683. /* Find initialization file. */
  684.  
  685. zkermini() {
  686. /*  nothing yet...  this function added for benefit of VMS Kermit.  */
  687.     return(0);
  688. }
  689.  
  690. zmail(p,f) char *p; char *f; {      /* Send file f as mail to address p */
  691.     return(0);
  692. }
  693.  
  694. zprint(p,f) char *p; char *f; {     /* Print file f with options p */
  695.     return(0);
  696. }
  697.