char *ckzv = "AMIGA file support, 1.0(000)+0, 30 Mar 1986";
char *ckzsys = " Commodore AMIGA";

/* C K I F I O  --  Kermit file system support for Commodore AMIGA */

/*
 * Copyright (C) 1986, Trustees of Columbia University in the City of
 * New York.  Permission is granted to any individual or institution to
 * use, copy, or redistribute this software, so long as it is not sold
 * for profit, provided this copyright notice is retained.
 */

/* Edit history
 * 28 Feb 1986 - Davide P. Cervone - wrote it.  Based on CKVFIO.C
 *  still have to work out wildcard file names
 */

/* Definitions of some AMIGA system commands */

char *DIRCMD = "DIRECTORY ";      /* For directory listing */
char *DELCMD = "DELETE ";         /* For file deletion */
char *TYPCMD = "TYPE ";           /* For typing a file */
char *SPACMD = "INFO ";           /* Space/quota of current directory */
char *SPACM2 = "LIST ";           /* Space/quota of current directory */
char *WHOCMD = "STATUS ";         /* For seeing who's logged in */



/*
  Functions (n is one of the predefined file numbers from ckcker.h):

   zopeni(n,name)   -- Opens an existing file for input.
   zopeno(n,name)   -- Opens a new file for output.
   zclose(n)        -- Closes a file.
   zchin(n)         -- Gets the next character from an input file.
   zsout(n,s)       -- Write a null-terminated string to output file, buffered.
   zsoutl(n,s)      -- Like zsout, but appends a line terminator.
   zsoutx(n,s,x)    -- Write x characters to output file, unbuffered.
   zchout(n,c)      -- Add a character to an output file, unbuffered.
   zchki(name)      -- Check if named file exists and is readable, return size.
   zchko(name)      -- Check if named file can be created.
   znewn(name,s)    -- Make a new unique file name based on the given name.
   zdelet(name)     -- Delete the named file.
   zxpand(string)   -- Expands the given wildcard string into a list of files.
   znext(string)    -- Returns the next file from the list in "string".
   zxcmd(cmd)       -- Execute the command in a lower fork.
   zclosf()         -- Close input file associated with zxcmd()'s lower fork.
   zrtol(n1,n2)     -- Convert remote filename into local form.
   zltor(n1,n2)     -- Convert local filename into remote form.
   zchdir(dirnam)   -- Change working directory.
   zhome()          -- Return pointer to home directory name string.
   zkself()         -- Log self out
 */

/* Includes */

#include <stdio.h>
#include <ctype.h>
#include "ckcker.h"
#include "ckcdeb.h"

#define MAXWLD 50         /* Maximum wildcard filenames */


/* Declarations */

FILE *fp[ZNFILS] = {            /* File pointers */
    NULL, NULL, NULL, NULL, NULL, NULL, NULL };

static int fcount;              /* Number of files in wild group */
char *getenv(), *strcpy();      /* For finding home directory */

static char *mtchs[MAXWLD],     /* Matches found for filename */
     **mtchptr;                 /* Pointer to current match */



/***  Z K S E L F --  Log self out  ***/

zkself() {
   doexit(0);
}


/*  Z O P E N I  --  Open an existing file for input. */

zopeni(n,name) int n; char *name; {
    debug(F111," zopeni",name,n);
    debug(F101,"  fp","",(int) fp[n]);
    if (chkfn(n) != 0) return(0);
    if (n == ZSYSFN) {           /* Input from a system function? */
       return(zxcmd(name));      /* Try to fork the command */
    }
    if (n == ZSTDIO) {           /* Standard input? */
       fp[ZIFILE] = stdin;
       return(1);
    }
    fp[n] = fopen(name,"r");      /* Real file. */
    if (fp[n] == NULL) perror(name);
    debug(F111," zopeni", name, (int) fp[n]);
    return((fp[n] != NULL) ? 1 : 0);
}

/*  Z O P E N O  --  Open a new file for output.  */

zopeno(n,name) int n; char *name; {
    debug(F111," zopeno",name,n);
    if (chkfn(n) != 0) return(0);
    if ((n == ZCTERM) || (n == ZSTDIO)) {   /* Terminal or standard output */
       fp[ZOFILE] = stdout;
       debug(F101," fp[]=stdout", "", (int) fp[n]);
       return(1);
    }
    fp[n] = fopen(name, "w");
    if (fp[n] == NULL) perror(name);
    if (n == ZDFILE)
       setnbf(fp[n]);                  /* Make debugging file unbuffered */
    debug(F101, " fp[n]", "", (int) fp[n]);
    return((fp[n] != NULL) ? 1 : 0);
}

/*  Z C L O S E  --  Close the given file.  */

zclose(n) int n; {
    if (chkfn(n) < 1) return(0);
    if ((fp[n] != stdout) && (fp[n] != stdin)) fclose(fp[n]);
    fp[n] = NULL;
    return(1);
}

/*  Z C H I N  --  Get a character from the input file.  */

zchin(n,c) int n; char *c; {
    int a;
    if (chkfn(n) < 1) return(-1);
    a = getc(fp[n]);
    if (a == EOF) return(-1);
    *c = (a & 0377);
    return(0);
}


/*  Z S O U T  --  Write a string to the given file, buffered.  */

zsout(n,s) int n; char *s; {
    if (chkfn(n) < 1) return(-1);
    fputs(s, fp[n]);         /* Don't use fprintf here MM */
    return(0);
}

/*  Z S O U T L  --  Write string to file, with line terminator, buffered  */

zsoutl(n,s) int n; char *s; {
    if (chkfn(n) < 1) return(-1);
    fputs(s, fp[n]);         /* Don't use fprintf MM */
    putc('\n', fp[n]);
    return(0);
}

/*  Z S O U T X  --  Write x characters to file, unbuffered.  */

zsoutx(n,s,x) int n, x; char *s; {
    if (chkfn(n) < 1) return(-1);
    return(write(fp[n]->_file,s,x));
}


/*  Z C H O U T  --  Add a character to the given file.  */

zchout(n,c) int n; char c; {
    if (chkfn(n) < 1) return(-1);
    if (n == ZSFILE)
       return(write(fp[n]->_file,&c,1)); /* Use unbuffered for session log */
    else {
       if (putc(c,fp[n]) == EOF)   /* If true, maybe there was an error */
          return(ferror(fp[n]));   /* Check to make sure */
       else                        /* Otherwise... */
          return(0);               /* There was no error. */
    }
}



/*  C H K F N  --  Internal function to verify file number is ok  */

/*
 Returns:
  -1: File number n is out of range
   0: n is in range, but file is not open
   1: n in range and file is open
*/
chkfn(n) int n; {
    switch (n) {
   case ZCTERM:
   case ZSTDIO:
   case ZIFILE:
   case ZOFILE:
   case ZDFILE:
   case ZTFILE:
   case ZPFILE:
   case ZSFILE: break;
   default:
       debug(F101,"chkfn: file number out of range","",n);
       printf2("?File number out of range - %d\n",n);
       return(-1);
    }
    return( (fp[n] == NULL) ? 0 : 1 );
}



/*  Z C H K I  --  Check if input file exists and is readable  */

/*
  Returns:
   >= 0 if the file can be read (returns the size).
     -1 if file doesn't exist or can't be accessed,
     -2 if file exists but is not readable (e.g. a directory file).
     -3 if file exists but protected against read access.
*/
/*
 For Berkeley Unix, a file must be of type "regular" to be readable.
 Directory files, special files, and symbolic links are not readable.
*/
long
zchki(name) char *name; {
    int x; long pos;

    x = open(name, 0);
    if (x < 0) {
       debug(F111,"zchki stat fails",name,errno);
       return(-1);
    }
    pos = lseek(x, 0L, 2);
    close(x);
    return(pos);
}



/*  Z C H K O  --  Check if output file can be created  */

/*
 Returns -1 if write permission for the file would be denied, 0 otherwise.
*/
zchko(name) char *name; {
    return(0);       /* don't know how to check */
}



/*  Z D E L E T  --  Delete the named file.  */

zdelet(name) char *name; {
    return(unlink(name));
}


/*  Z R T O L  --  Convert remote filename into local form  */

/*  For AMIGA, we convert : and / to .  */

zrtol(name,name2) char *name, *name2; {

   for (; *name != '\0'; name++, name2++)
      *name2 = (*name == ':' || *name == '/') ? '.' : *name;
   *name2 = '\0';
}


/*  Z L T O R  --  Convert filename from local format to common form.   */

/* remove all special characters, and any path names */

zltor(name,name2) char *name, *name2; {
   char *oldname2;

   oldname2 = name2;
   for (; *name != '\0'; name++)
   {
      if (*name == '/' || *name == ':')
         name2 = oldname2;
      else
      {
         *name2 = (isalnum(*name)) ? toupper(*name) : 'X';
         name2++;
      }
   }
   *name2 = '\0';
}


/*  Z C H D I R  --  Change directory  */

zchdir(dirnam) char *dirnam; {
    char *hd;
    if (*dirnam == '\0') hd = ":";
    else hd = dirnam;
    return((chdir(hd) == 0) ? 1 : 0);
}


/*  Z H O M E  --  Return pointer to user's home directory  */

char *
zhome() {
    return(":");
}



/*  Z X C M D -- Run a system command so its output can be read like a file */

zxcmd(comand) char *comand; {
    return(0);    /* for now, say we can't do it */
}

/*  Z C L O S F  - close the subprocess output file.  */

zclosf() {
}

/*  Z K I L L F  - kill the subprocess used for host commands  */
/*  The return value is 1 if the subprocess was killed successfully. */
/*         -1 if there was no subprocess to kill. */

zkillf() {
   return(1);    /* always successful, since never any subprocesses, yet */
}



/*  Z X P A N D  --  Expand a wildcard string into an array of strings  */
/*
  Returns the number of files that match fn1, with data structures set up
  so that first file (if any) will be returned by the next znext() call.
*/
zxpand(fn) char *fn; {
    fcount = fgen(fn,mtchs,MAXWLD);   /* Look up the file. */
    if (fcount > 0) {
       mtchptr = mtchs;      /* Save pointer for next. */
    }
    debug(F111,"zxpand",mtchs[0],fcount);
    return(fcount);
}


/*  Z N E X T  --  Get name of next file from list created by zxpand(). */
/*
 Returns >0 if there's another file, with its name copied into the arg string,
 or 0 if no more files in list.
*/
znext(fn) char *fn; {
    if (fcount-- > 0) strcpy(fn,*mtchptr++);
    else *fn = '\0';
    debug(F111,"znext",fn,fcount+1);
    return(fcount+1);
}


/*  Z N E W N  --  Make a new name for the given file  */

znewn(fn,s) char *fn, **s; {
    static char buf[100];
    int i;

    strcpy(buf, fn);
    i = strlen(buf);
    buf[i+1] = '.';
    buf [i+2] = '\0';
    *s = buf;
}



fgen(pat,resarry,len)
char *pat,*resarry[];
int len;
{
    resarry[0] = (char *) malloc(strlen(pat)+1);
    strcpy(resarry[0], pat);
    return(1);
}

system(s)  char *s;  {

    zxcmd(s);
}
