ckcfn3.c
资源名称:cku197.tar.Z [点击查看]
上传用户:dufan58
上传日期:2007-01-05
资源大小:3407k
文件大小:71k
源码类别:
通讯/手机编程
开发平台:
Windows_Unix
- /* C K C F N 3 -- Packet buffer management for C-Kermit */
- /* (plus assorted functions tacked on at the end) */
- /*
- Author: Frank da Cruz <fdc@columbia.edu>,
- Columbia University Academic Information Systems, New York City.
- Copyright (C) 1985, 2000,
- Trustees of Columbia University in the City of New York.
- All rights reserved. See the C-Kermit COPYING.TXT file or the
- copyright text in the ckcmai.c module for disclaimer and permissions.
- */
- /*
- Note -- if you change this file, please amend the version number and date at
- the top of ckcfns.c accordingly.
- */
- #include "ckcsym.h"
- #include "ckcdeb.h"
- #include "ckcasc.h"
- #include "ckcker.h"
- #include "ckcxla.h"
- /* C K M K D I R -- Create a directory */
- /*
- Call with:
- int fc = 0 to create, nonzero to remove, a directory.
- char * s = pointer to name of directory to create or remove.
- char ** r = address of pointer to return name or message.
- int m = 1 to print error messages, 0 to be silent.
- int cvt = 1 means convert s from standard format to local format;
- 0 means use s as is.
- Returns:
- 0 on success (directory was created or removed).
- -1 when attempt to create the directory failed.
- -2 on internal error (e.g. no code for creating directories).
- On success, the name is pointed to by p.
- On failure, the reason is pointed to by p.
- */
- #ifdef CK_MKDIR
- static char ckmkdbuf[CKMAXPATH+1];
- #else
- #ifdef datageneral
- static char ckmkdbuf[CKMAXPATH+1];
- #endif /* datageneral */
- #endif /* CK_MKDIR */
- #ifdef CK_MKDIR
- int
- ckmkdir(fc,s,r,m,cvt) int fc; char * s; char ** r; int m; int cvt; {
- int x, rc = -2;
- char tmpbuf[CKMAXPATH+1];
- char buf2[CKMAXPATH+1];
- if (!s) s = "";
- debug(F110,"ckmkdir 1 fc",s,fc);
- if (!*s) {
- sprintf(ckmkdbuf,"%s: no name given", (fc == 0) ? "mkdir" : "rmdir");
- *r = ckmkdbuf;
- return(-2);
- }
- #ifdef datageneral
- /* Come back and make this nicer later */
- if (fc == 0) { /* mkdir */
- rc = createdir(s,0);
- } else { /* rmdir */
- sprintf(tmpbuf,"delete %s",s); /* AOS/VS rmdir() is a no-op. */
- debug(F110,"ckmkdir 2",tmpbuf,0);
- rc = system(tmpbuf);
- }
- *r = NULL;
- #else /* not datageneral */
- /* First make sure the name has an acceptable directory-name format */
- #ifdef VMS
- {
- char *p = s;
- int lb = 0, rb = 0, sl = 0;
- while (*p) {
- if (*p == '[' || *p == '<') lb++; /* Count brackets */
- else if (*p == ']' || *p == '>') rb++;
- else if (*p == '/') sl++; /* and slashes */
- p++;
- }
- if (lb != 1 && rb != 1 && sl == 0 && p > s && *(p-1) != ':') {
- /* Probably just a word - convert to VMS format */
- sprintf(buf2,"[%s%s]", (*s == '.') ? "" : ".", s);
- s = buf2;
- } else if (lb == 0 && rb == 0 && sl != 0 && p > s && *(p-1) != ':') {
- int flag = 0;
- /* Seems to be in UNIX format */
- x = strlen(s);
- if (x > 0 && s[x-1] != '/')
- flag = 1;
- sprintf(buf2,"%s%s",s,flag ? "/" : "");
- s = buf2;
- }
- if (s == buf2) {
- ckstrncpy(tmpbuf,s,CKMAXPATH+1);
- s = tmpbuf;
- }
- debug(F110,"ckmkdir 2+VMS",s,0);
- }
- #else
- #ifdef UNIXOROSK
- #ifdef DTILDE
- s = tilde_expand(s);
- #endif /* DTILDE */
- ckstrncpy(tmpbuf,s,CKMAXPATH+1);
- s = tmpbuf;
- x = strlen(s);
- if (x > 0 && s[x-1] != '/') { /* Must end in "/" for zmkdir() */
- s[x] = '/';
- s[x+1] = NUL;
- debug(F110,"ckmkdir 2+UNIXOROSK",s,0);
- }
- #else /* UNIXOROSK */
- #ifdef OS2
- ckstrncpy(tmpbuf,s,CKMAXPATH+1);
- s = tmpbuf;
- x = strlen(s);
- if (x > 0 && s[x-1] != '/') { /* Must end in "/" for zmkdir() */
- s[x] = '/';
- s[x+1] = NUL;
- debug(F110,"ckmkdir 2+OS2",s,0);
- }
- #endif /* OS2 */
- #endif /* UNIXOROSK */
- #endif /* VMS */
- #ifdef NZLTOR
- /* Server is calling us, so convert to local format if necessary */
- if (cvt) {
- nzrtol(s,(char *)buf2,1,PATH_ABS,CKMAXPATH);
- s = buf2;
- debug(F110,"ckmkdir 3",s,0);
- }
- #endif /* NZLTOR */
- debug(F110,"ckmkdir 4",s,0);
- if (fc == 0) { /* Making */
- #ifdef CK_MKDIR
- rc = zmkdir(s);
- #else
- #ifdef NT
- rc = _mkdir(s);
- #else
- rc = mkdir(s,0777);
- #endif /* NT */
- #endif /* CK_MKDIR */
- } else { /* Removing */
- #ifdef ZRMDIR
- rc = zrmdir(s);
- #else
- #ifdef NT
- rc = _rmdir(s);
- #else
- #ifdef OSK
- rc = -2;
- #else
- rc = rmdir(s);
- #endif /* OSK */
- #endif /* NT */
- #endif /* ZRMDIR */
- }
- #endif /* datageneral */
- debug(F101,"ckmkdir rc","",rc);
- if (rc == -2) {
- sprintf(ckmkdbuf,
- "Directory %s not implemented in this version of C-Kermit",
- (fc == 0) ? "creation" : "removal"
- );
- *r = ckmkdbuf;
- if (m) printf("%sn",*r);
- } else if (rc < 0) {
- if (m) perror(s);
- sprintf(ckmkdbuf,"%s: %s",s,ck_errstr());
- *r = ckmkdbuf;
- } else if (fc == 0 && zfnqfp(s,CKMAXPATH,ckmkdbuf)) {
- *r = ckmkdbuf;
- } else if (fc != 0) {
- sprintf(ckmkdbuf,"%s: removed",s);
- *r = ckmkdbuf;
- }
- return(rc);
- }
- #endif /* CK_MKDIR */
- #ifndef NOXFER /* Rest of this file... */
- #ifndef NODISPO
- #ifdef pdp11
- #define NODISPO
- #endif /* pdpd11 */
- #endif /* NODISPO */
- #ifdef PIPESEND
- int pipesend = 0;
- #endif /* PIPESEND */
- extern int unkcs, wmax, wcur, discard, bctu, bctl, local, fdispla, what,
- sendmode, opnerr, dest, epktrcvd, epktsent, filestatus, eofmethod;
- extern long sendstart, calibrate, fncnv, fnrpath;
- extern char * ofn2, * rfspec, * sfspec;
- extern char ofn1[];
- extern int ofn1x;
- extern char * ofperms;
- #ifdef VMS
- extern int batch;
- #else
- extern int backgrd;
- #endif /* VMS */
- extern int xflg, remfile, remappd;
- extern CHAR *data;
- extern char filnam[];
- #ifndef NOFRILLS
- extern int rprintf, rmailf; /* REMOTE MAIL, PRINT */
- char optbuf[100]; /* Options for MAIL or REMOTE PRINT */
- #endif /* NOFRILLS */
- extern int wslots;
- extern int fblksiz, frecl, forg, frecfm, fncact, fncsav, fcctrl, lf_opts;
- extern CHAR * srvcmd;
- extern int binary, spsiz;
- extern int pktnum, cxseen, czseen, nfils, stdinf;
- extern int memstr, stdouf, keep, sndsrc, hcflg;
- extern int server, en_cwd, en_mai, en_pri;
- /* Attributes in/out enabled flags */
- extern int
- atenci, atenco, atdati, atdato, atleni, atleno, atblki, atblko,
- attypi, attypo, atsidi, atsido, atsysi, atsyso, atdisi, atdiso;
- #ifdef CK_PERMS
- extern int atlpri, atlpro, atgpri, atgpro;
- #endif /* CK_PERMS */
- #ifdef STRATUS
- extern int atfrmi, atfrmo, atcrei, atcreo, atacti, atacto;
- #endif /* STRATUS */
- #ifdef datageneral
- extern int quiet;
- #endif /* datageneral */
- extern long fsize, filcnt, ffc, tfc;
- #ifndef NOCSETS
- _PROTOTYP (VOID setxlate, (void));
- extern int tcharset, fcharset;
- extern int ntcsets, xlatype;
- extern struct csinfo tcsinfo[], fcsinfo[];
- #endif /* NOCSETS */
- /* Variables global to Kermit that are defined in this module */
- #ifdef CKXXCHAR /* DOUBLE / IGNORE char table */
- int dblflag = 0;
- int ignflag = 0;
- short dblt[256] = {
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
- };
- #endif /* CKXXCHAR */
- int winlo; /* packet number at low window edge */
- int sbufnum; /* number of free buffers */
- int dum001 = 1234; /* protection... */
- int sbufuse[MAXWS]; /* buffer in-use flag */
- int dum003 = 1111;
- int rbufnum; /* number of free buffers */
- int dum002 = 4321; /* more protection */
- int rbufuse[MAXWS]; /* buffer in-use flag */
- int sseqtbl[64]; /* sequence # to buffer # table */
- int rseqtbl[64]; /* sequence # to buffer # table */
- int sacktbl[64]; /* sequence # ack table */
- int o_isopen = 0, i_isopen = 0; /* Input & output files are open */
- #ifdef DYNAMIC
- struct pktinfo *s_pkt = NULL; /* array of pktinfo structures */
- struct pktinfo *r_pkt = NULL; /* array of pktinfo structures */
- #else
- struct pktinfo s_pkt[MAXWS]; /* array of pktinfo structures */
- struct pktinfo r_pkt[MAXWS]; /* array of pktinfo structures */
- #endif /* DYNAMIC */
- #ifdef DEBUG
- char xbuf[200]; /* For debug logging */
- #endif /* DEBUG */
- #ifdef DYNAMIC
- CHAR *bigsbuf = NULL, *bigrbuf = NULL;
- #else
- char bigsbt[8]; /* Protection (shouldn't need this). */
- /* BUT DON'T REMOVE IT! */
- CHAR bigsbuf[SBSIZ + 5]; /* Send-packet buffer area */
- char bigrbt[8]; /* Safety padding */
- CHAR bigrbuf[RBSIZ + 5]; /* Receive-packet area */
- #endif
- int bigsbsiz = SBSIZ; /* Sizes of big send & rcv buffers. */
- int bigrbsiz = RBSIZ;
- #ifdef VMS
- int zchkpath(char *s);
- #endif /* VMS */
- /* FUNCTIONS */
- VOID
- dofast() {
- long maxbufsiz = RBSIZ; /* Configuration parameters */
- int maxpktsiz = MAXSP;
- extern int spsizf, /* For bug in IRIX Telnet server */
- rpsiz, urpsiz, spsizr, spmax, wslotr;
- extern struct ck_p ptab[];
- if (maxpktsiz < 40) /* Long packet length */
- maxpktsiz = 40;
- else if (maxpktsiz > 4000)
- maxpktsiz = 4000;
- wslotr = maxbufsiz / maxpktsiz;
- if (wslotr > MAXWS) /* Window slots */
- wslotr = MAXWS;
- if (wslotr > 30)
- wslotr = 30;
- else if (wslotr < 1)
- wslotr = 1;
- urpsiz = adjpkl(maxpktsiz,wslotr,maxbufsiz);
- ptab[PROTO_K].rpktlen = urpsiz;
- rpsiz = (urpsiz > 94) ? 94 : urpsiz; /* Max non-long packet length */
- debug(F111,"dofast","uprsiz",urpsiz);
- #ifdef IRIX
- #ifndef IRIX65
- /* IRIX Telnet server chops off writes longer than 4K */
- spsiz = spmax = spsizr = urpsiz;
- debug(F101,"doarg Q IRIX spsiz","",spsiz);
- spsizf = 1;
- #endif /* IRIX65 */
- #endif /* IRIX */
- #ifdef CK_SPEED
- setprefix(PX_CAU); /* Cautious unprefixing */
- #endif /* CK_SPEED */
- }
- /* For sanity, use "i" for buffer slots, "n" for packet numbers. */
- /* I N I B U F S */
- /*
- Allocates the big send and receive buffers.
- Call with size for big send buffer (s) and receive buffer (r).
- These sizes can be different.
- Attempts to allocate buffers of the requested size, but if it can't,
- it will allocate smaller ones.
- Sets global variables bigsbsiz and bigrbsiz to the actual sizes,
- and bigsbuf and bigrbuf pointing to the actual buffers.
- Designed to be called more than once.
- Returns 0 on success, -1 on failure.
- */
- CHAR *bigbufp = NULL;
- int
- inibufs(s,r) int s, r; {
- #ifdef DYNAMIC
- unsigned
- int size;
- #ifdef OS2
- unsigned /* Don't you wish everybody had unsigned long... */
- #endif /* OS2 */
- long z;
- int x;
- debug(F101,"inibufs s","",s);
- debug(F101,"inibufs r","",r);
- if (s < 80 || r < 80) return(-1); /* Validate arguments. */
- if (!s_pkt) { /* Allocate packet info structures */
- if (!(s_pkt = (struct pktinfo *) malloc(sizeof(struct pktinfo)*MAXWS)))
- fatal("ini_pkts: no memory for s_pkt");
- }
- for (x = 0; x < MAXWS; x++)
- s_pkt[x].pk_adr = NULL; /* Initialize addresses */
- if (!r_pkt) {
- if (!(r_pkt = (struct pktinfo *) malloc(sizeof(struct pktinfo)*MAXWS)))
- fatal("ini_pkts: no memory for s_pkt");
- }
- for (x = 0; x < MAXWS; x++)
- r_pkt[x].pk_adr = NULL; /* Initialize addresses */
- if (!srvcmd) { /* Allocate srvcmd buffer */
- srvcmd = (CHAR *) malloc(r + 100);
- if (!srvcmd) return(-1);
- *srvcmd = NUL;
- }
- if (bigbufp) { /* Free previous buffers, if any. */
- free(bigbufp);
- bigbufp = NULL;
- }
- size = s + r + 40; /* Combined requested size + padding */
- z = (unsigned) s + (unsigned) r + 40;
- debug(F101,"inibufs size 1","",size);
- debug(F101,"inibufs size z","",z);
- if ((long) size != z) {
- debug(F100,"inibufs overflow","",0);
- size = 65535;
- }
- /* Try to get the space. If malloc fails, try to get a little less. */
- /* (Obviously, this algorithm can be refined.) */
- while (!(bigbufp = (CHAR *) malloc(size))) {
- debug(F101,"inibufs bigbuf malloc failed","",size);
- size = (size * 2) / 3; /* Failed, cut size by 1/3. */
- if (size < 200) /* Try again until too small. */
- return(-1);
- }
- debug(F101,"inibufs size 2","",size); /* OK, we got some space. */
- /*
- Now divide the allocated space between the send and receive buffers in the
- requested proportion. The natural formula would be (s / (s + r)) * size
- (for the send buffer), but that doesn't work with integer arithmetic and we
- can't use floating point because some machines don't have it. This can be
- rearranged as (s * size) / (s + r). But (s * size) can be VERY large, too
- large for 32 bits. So let's do it this way. This arithmetic works for
- buffer sizes up to about 5,000,000.
- */
- #define FACTOR 20L
- z = ( (long) s * FACTOR ) / ( (long) s + (long) r );
- x = ( z * ( (long) size / FACTOR ) );
- if (x < 0) return(-1); /* Catch overflow */
- bigsbsiz = x - 5; /* Size of send buffer */
- bigsbuf = bigbufp; /* Address of send buffer */
- debug(F101,"inibufs bigsbsiz","",bigsbsiz);
- bigrbsiz = size - x - 5; /* Size of receive buffer */
- bigrbuf = bigbufp + x; /* Addresss of receive buffer */
- debug(F101,"inibufs bigrbsiz","",bigrbsiz);
- return(0); /* Success */
- #else /* No dynamic allocation */
- bigsbsiz = SBSIZ; /* Just use the symbols */
- bigrbsiz = RBSIZ; /* ... */
- return(0); /* Success. */
- #endif /* DYNAMIC */
- }
- /* M A K E B U F -- Makes and clears a new buffers. */
- /* Call with: */
- /* slots: number of buffer slots to make, 1 to 32 */
- /* bufsiz: size of the big buffer */
- /* buf: address of the big buffer */
- /* xx: pointer to array of pktinfo structures for these buffers */
- /* Subdivides the big buffer into "slots" buffers. */
- /* Returns: */
- /* -1 if too many or too few slots requested, */
- /* -2 if slots would be too small. */
- /* n (positive) on success = size of one buffer. */
- /* with pktinfo structure initialized for this set of buffers. */
- int
- makebuf(slots,bufsiz,buf,xx)
- /* makebuf */ int slots, bufsiz; CHAR buf[]; struct pktinfo *xx; {
- CHAR *a;
- int i, size;
- debug(F101,"makebuf","",slots);
- debug(F101,"makebuf bufsiz","",bufsiz);
- debug(F101,"makebuf MAXWS","",MAXWS);
- if (slots > MAXWS || slots < 1) return(-1);
- if (bufsiz < slots * 10 ) return(-2);
- size = bufsiz / slots; /* Divide up the big buffer. */
- a = buf; /* Address of first piece. */
- for (i = 0; i < slots; i++) {
- struct pktinfo *x = &xx[i];
- x->bf_adr = a; /* Address of this buffer */
- x->bf_len = size; /* Length of this buffer */
- x->pk_len = 0; /* Length of data field */
- x->pk_typ = ' '; /* packet type */
- x->pk_seq = -1; /* packet sequence number */
- x->pk_rtr = 0; /* retransmissions */
- *a = ' '; /* Clear the buffer */
- a += size; /* Position to next buffer slot */
- }
- return(size);
- }
- /* M A K S B U F -- Makes the send-packet buffer */
- int
- mksbuf(slots) int slots; {
- int i, x;
- sbufnum = 0;
- if ((x = makebuf(slots,bigsbsiz,bigsbuf,s_pkt)) < 0) {
- debug(F101,"mksbuf makebuf return","",x);
- return(x);
- }
- debug(F101,"mksbuf makebuf return","",x);
- for (i = 0; i < 64; i++) { /* Initialize sequence-number- */
- sseqtbl[i] = -1; /* to-buffer-number table. */
- sacktbl[i] = 0;
- }
- for (i = 0; i < MAXWS; i++)
- sbufuse[i] = 0; /* Mark each buffer as free */
- sbufnum = slots;
- wcur = 0;
- return(x);
- }
- /* M A K R B U F -- Makes the receive-packet buffer */
- int
- mkrbuf(slots) int slots; {
- int i, x;
- rbufnum = 0;
- if ((x = makebuf(slots,bigrbsiz,bigrbuf,r_pkt)) < 0) {
- debug(F101,"mkrbuf makebuf return","",x);
- return(x);
- }
- debug(F101,"mkrbuf makebuf return","",x);
- for (i = 0; i < 64; i++) { /* Initialize sequence-number- */
- rseqtbl[i] = -1; /* to-buffer-number table. */
- }
- for (i = 0; i < MAXWS; i++)
- rbufuse[i] = 0; /* Mark each buffer as free */
- rbufnum = slots;
- wcur = 0;
- return(x);
- }
- /* W I N D O W -- Resize the window to n */
- int
- window(n) int n; {
- debug(F101,"window","",n);
- if (n < 1 || n > MAXWS) return(-1);
- if (mksbuf(n) < 0) return(-1);
- if (mkrbuf(n) < 0) return(-1);
- wslots = n;
- #ifdef DEBUG
- if (deblog) dumpsbuf();
- if (deblog) dumprbuf();
- #endif /* DEBUG */
- return(0);
- }
- /* G E T S B U F -- Allocate a send-buffer. */
- /* Call with packet sequence number to allocate buffer for. */
- /* Returns: */
- /* -4 if argument is invalid (negative, or greater than 63) */
- /* -3 if buffers were thought to be available but really weren't (bug!) */
- /* -2 if the number of free buffers is negative (bug!) */
- /* -1 if no free buffers. */
- /* 0 or positive, packet sequence number, with buffer allocated for it. */
- int
- getsbuf(n) int n; { /* Allocate a send-buffer */
- int i;
- CHAR * p = NULL;
- if (n < 0 || n > 63) {
- debug(F101,"getsbuf bad arg","",n);
- return(-4); /* Bad argument */
- }
- debug(F101,"getsbuf packet","",n);
- /* debug(F101,"getsbuf, sbufnum","",sbufnum); */
- if (sbufnum == 0) return(-1); /* No free buffers. */
- if (sbufnum < 0) return(-2); /* Shouldn't happen. */
- for (i = 0; i < wslots; i++) /* Find the first one not in use. */
- if (sbufuse[i] == 0) { /* Got one? */
- sbufuse[i] = 1; /* Mark it as in use. */
- sbufnum--; /* One less free buffer. */
- *s_pkt[i].bf_adr = ' '; /* Zero the buffer data field */
- s_pkt[i].pk_seq = n; /* Put in the sequence number */
- sseqtbl[n] = i; /* Back pointer from sequence number */
- sacktbl[n] = 0; /* ACK flag */
- s_pkt[i].pk_len = 0; /* Data field length now zero. */
- s_pkt[i].pk_typ = ' '; /* Blank the packet type too. */
- s_pkt[i].pk_rtr = 0; /* Zero the retransmission count */
- p = s_pkt[i].bf_adr + 7; /* Set global "data" address. */
- debug(F101,"getsbuf p","",0);
- data = p;
- if (!data) {
- debug(F100,"getsbuf data == NULL","",0);
- return(-3);
- }
- if ((what & (W_SEND|W_REMO)) && (++wcur > wmax))
- wmax = wcur; /* For statistics. */
- /* debug(F101,"getsbuf wcur","",wcur); */
- return(n); /* Return its index. */
- }
- sbufnum = 0; /* Didn't find one. */
- return(-3); /* Shouldn't happen! */
- }
- int
- getrbuf() { /* Allocate a receive buffer */
- int i;
- #ifdef COMMENT
- /* This code is pretty stable by now... */
- debug(F101,"getrbuf rbufnum","",rbufnum);
- debug(F101,"getrbuf wslots","",wslots);
- debug(F101,"getrbuf dum002","",dum002);
- debug(F101,"getrbuf dum003","",dum003);
- #endif /* COMMENT */
- if (rbufnum == 0) return(-1); /* No free buffers. */
- if (rbufnum < 0) return(-2); /* Shouldn't happen. */
- for (i = 0; i < wslots; i++) /* Find the first one not in use. */
- if (rbufuse[i] == 0) { /* Got one? */
- rbufuse[i] = 1; /* Mark it as in use. */
- *r_pkt[i].bf_adr = ' '; /* Zero the buffer data field */
- rbufnum--; /* One less free buffer. */
- debug(F101,"getrbuf new rbufnum","",rbufnum);
- if ((what & W_RECV) && (++wcur > wmax))
- wmax = wcur; /* For statistics. */
- /* debug(F101,"getrbuf wcur","",wcur); */
- return(i); /* Return its index. */
- }
- /* debug(F101,"getrbuf foulup","",i); */
- rbufnum = 0; /* Didn't find one. */
- return(-3); /* Shouldn't happen! */
- }
- /* F R E E S B U F -- Free send-buffer for given packet sequence number */
- /* Returns: */
- /* 1 upon success */
- /* -1 if specified buffer does not exist */
- int
- freesbuf(n) int n; { /* Release send-buffer for packet n. */
- int i;
- debug(F101,"freesbuf","",n);
- if (n < 0 || n > 63) /* No such packet. */
- return(-1);
- i = sseqtbl[n]; /* Get the window slot number. */
- if (i > -1 && i <= wslots) {
- sseqtbl[n] = -1; /* If valid, remove from seqtbl */
- sbufnum++; /* and count one more free buffer */
- sbufuse[i] = 0; /* and mark it as free, */
- if (what & (W_SEND|W_REMO)) /* decrement active slots */
- wcur--; /* for statistics and display. */
- } else {
- debug(F101," sseqtbl[n]","",sseqtbl[n]);
- return(-1);
- }
- /* The following is done only so dumped buffers will look right. */
- if (1) {
- *s_pkt[i].bf_adr = ' '; /* Zero the buffer data field */
- s_pkt[i].pk_seq = -1; /* Invalidate the sequence number */
- s_pkt[i].pk_len = 0; /* Data field length now zero. */
- s_pkt[i].pk_typ = ' '; /* Blank the packet type too. */
- s_pkt[i].pk_rtr = 0; /* And the retries field. */
- }
- return(1);
- }
- int
- freerbuf(i) int i; { /* Release receive-buffer slot "i". */
- int n;
- /* NOTE !! Currently, this function frees the indicated buffer, but */
- /* does NOT erase the data. The program counts on this. Will find a */
- /* better way later.... */
- /* debug(F101,"freerbuf, slot","",i); */
- if (i < 0 || i >= wslots) { /* No such slot. */
- debug(F101,"freerbuf no such slot","",i);
- return(-1);
- }
- n = r_pkt[i].pk_seq; /* Get the packet sequence number */
- debug(F101,"freerbuf packet","",n);
- if (n > -1 && n < 64) /* If valid, remove from seqtbl */
- rseqtbl[n] = -1;
- if (rbufuse[i] != 0) { /* If really allocated, */
- rbufuse[i] = 0; /* mark it as free, */
- rbufnum++; /* and count one more free buffer. */
- if (what & W_RECV) /* Keep track of current slots */
- wcur--; /* for statistics and display */
- debug(F101,"freerbuf rbufnum","",rbufnum);
- }
- /* The following is done only so dumped buffers will look right. */
- if (1) {
- /* *r_pkt[i].bf_adr = ' '; */ /* Zero the buffer data field */
- r_pkt[i].pk_seq = -1; /* And from packet list */
- r_pkt[i].pk_len = 0; /* Data field length now zero. */
- r_pkt[i].pk_typ = ' '; /* Blank the packet type too. */
- r_pkt[i].pk_rtr = 0; /* And the retries field. */
- }
- return(1);
- }
- /* This is like freerbuf, except it's called with a packet sequence number */
- /* rather than a packet buffer index. */
- VOID
- freerpkt(seq) int seq; {
- int k;
- debug(F101,"freerpkt seq","",seq);
- k = rseqtbl[seq];
- /* debug(F101,"freerpkt k","",k); */
- if (k > -1) {
- k = freerbuf(k);
- /* debug(F101,"freerpkt freerbuf","",k); */
- }
- }
- /* C H K W I N -- Check if packet n is in window. */
- /* Returns: */
- /* 0 if it is in the current window, */
- /* +1 if it would have been in previous window (e.g. if ack was lost), */
- /* -1 if it is outside any window (protocol error), */
- /* -2 if either of the argument packet numbers is out of range. */
- /* Call with packet number to check (n), lowest packet number in window */
- /* (bottom), and number of slots in window (slots). */
- int
- chkwin(n,bottom,slots) int n, bottom, slots; {
- int top, prev;
- debug(F101,"chkwin packet","",n);
- debug(F101,"chkwin winlo","",bottom);
- debug(F101,"chkwin slots","",slots);
- /* First do the easy and common cases, where the windows are not split. */
- if (n < 0 || n > 63 || bottom < 0 || bottom > 63)
- return(-2);
- if (n == bottom) return(0); /* In a perfect world... */
- top = bottom + slots; /* Calculate window top. */
- if (top < 64 && n < top && n >= bottom)
- return(0); /* In current window. */
- prev = bottom - slots; /* Bottom of previous window. */
- if (prev > -1 && n < bottom && n > prev)
- return(1); /* In previous. */
- /* Now consider the case where the current window is split. */
- if (top > 63) { /* Wraparound... */
- top -= 64; /* Get modulo-64 sequence number */
- if (n < top || n >= bottom) {
- return(0); /* In current window. */
- } else { /* Not in current window. */
- if (n < bottom && n >= prev) /* Previous window can't be split. */
- return(1); /* In previous window. */
- else
- return(-1); /* Not in previous window. */
- }
- }
- /* Now the case where current window not split, but previous window is. */
- if (prev < 0) { /* Is previous window split? */
- prev += 64; /* Yes. */
- if (n < bottom || n >= prev)
- return(1); /* In previous window. */
- } else { /* Previous window not split. */
- if (n < bottom && n >= prev)
- return(1); /* In previous window. */
- }
- /* It's not in the current window, and not in the previous window... */
- return(-1); /* So it's not in any window. */
- }
- int
- dumpsbuf() { /* Dump send-buffers */
- #ifdef DEBUG
- int j, x; /* to debug log. */
- if (! deblog) return(0);
- x = zsoutl(ZDFILE,"SEND BUFFERS:");
- if (x < 0) {
- deblog = 0;
- return(0);
- }
- x=zsoutl(ZDFILE,"buffer inuse address length data type seq flag retries");
- if (x < 0) {
- deblog = 0;
- return(0);
- }
- for ( j = 0; j < wslots; j++ ) {
- sprintf(xbuf,
- "%4d%6d%10d%5d%6d%4c%5d%6dn",
- j,
- sbufuse[j],
- (int) s_pkt[j].bf_adr,
- s_pkt[j].bf_len,
- s_pkt[j].pk_len,
- s_pkt[j].pk_typ,
- s_pkt[j].pk_seq,
- s_pkt[j].pk_rtr
- );
- if (zsout(ZDFILE,xbuf) < 0) {
- deblog = 0;
- return(0);
- }
- if (s_pkt[j].pk_adr) {
- x = (int)strlen((char *) s_pkt[j].pk_adr);
- if (x)
- sprintf(xbuf,"[%.72s%s]n",s_pkt[j].pk_adr, x > 72 ? "..." : "");
- else
- sprintf(xbuf,"[(empty string)]n");
- } else {
- sprintf(xbuf,"[(null pointer)]n");
- }
- if (zsout(ZDFILE,xbuf) < 0) {
- deblog = 0;
- return(0);
- }
- }
- sprintf(xbuf,"free: %d, winlo: %dn", sbufnum, winlo);
- if (zsout(ZDFILE,xbuf) < 0) {
- deblog = 0;
- return(0);
- }
- #endif /* DEBUG */
- return(0);
- }
- int
- dumprbuf() { /* Dump receive-buffers */
- #ifdef DEBUG
- int j, x;
- if (! deblog) return(0);
- if (zsoutl(ZDFILE,"RECEIVE BUFFERS:") < 0) {
- deblog = 0;
- return(0);
- }
- x=zsoutl(ZDFILE,"buffer inuse address length data type seq flag retries");
- if (x < 0) {
- deblog = 0;
- return(0);
- }
- for ( j = 0; j < wslots; j++ ) {
- sprintf(xbuf,
- "%4d%6d%10d%5d%6d%4c%5d%6dn",
- j,
- rbufuse[j],
- (int) r_pkt[j].bf_adr,
- r_pkt[j].bf_len,
- r_pkt[j].pk_len,
- r_pkt[j].pk_typ,
- r_pkt[j].pk_seq,
- r_pkt[j].pk_rtr
- );
- if (zsout(ZDFILE,xbuf) < 0) {
- deblog = 0;
- return(0);
- }
- x = (int)strlen((char *)r_pkt[j].bf_adr);
- sprintf(xbuf,"[%.72s%s]n",r_pkt[j].bf_adr, x > 72 ? "..." : "");
- if (zsout(ZDFILE,xbuf) < 0) {
- deblog = 0;
- return(0);
- }
- }
- sprintf(xbuf,"free: %d, winlo: %dn", rbufnum, winlo);
- if (zsout(ZDFILE,xbuf) < 0) {
- deblog = 0;
- return(0);
- }
- #endif /* DEBUG */
- return(0);
- }
- /* S A T T R -- Send an Attribute Packet */
- /*
- Sends attribute packet(s) for the current file. If the info will not
- fit into one packet, it can be called repeatedly until all the fields
- that will fit are sent.
- Call with:
- xp == 0 if we're sending a real file (F packet), or:
- xp != 0 for screen data (X packet).
- And:
- flag == 1 for first A packet
- flag == 0 for subsequent A packets.
- Returns:
- 1 or greater if an A packet was sent, or:
- 0 if an S-packet was not sent because there was no data to send or
- there was no data left that was short enough to send, or:
- -1 on any kind of error.
- */
- /* (don't) #define TSOFORMAT */
- /* which was only for making C-Kermit send TSO-Kermit-like A packets */
- /* to try to track down a problem somebody reported... */
- int
- sattr(xp, flag) int xp, flag; { /* Send Attributes */
- static int max; /* Maximum length for Attributes */
- static short done[95]; /* Field-complete array */
- static struct zattr x; /* File attribute struct */
- /* Some extra flags are used because the "done" array is sparse */
- int i, j, rc, aln, left = 0, numset = 0, xbin = 0; /* Workers */
- char *tp, c;
- debug(F101,"sattr flag","",flag);
- if (!flag) /* No more attributes to send */
- if (done[xunchar('@')])
- return(0);
- /* Initialize Attribute mechanism */
- if (flag) { /* First time here for this file? */
- for (j = 0; j < 95; j++) /* Init array of completed fields */
- done[j] = 0;
- max = maxdata(); /* Get maximum data field length */
- rc = zsattr(&x); /* Get attributes for this file */
- debug(F101,"sattr zsattr","",rc);
- if (rc < 0) /* Can't get 'em so don't send 'em */
- return(0);
- debug(F101,"sattr init max","",max);
- }
- #ifdef CALIBRATE
- if (calibrate) {
- x.lengthk = calibrate / 1024L;
- x.length = calibrate;
- }
- #endif /* CALIBRATE */
- if (nxtpkt() < 0) /* Got 'em, get next packet number */
- return(-1); /* Bad news if we can't */
- i = 0; /* Init data field character number */
- /* Do each attribute using first-fit method, marking as we go */
- /* This is rather long and repititious - could be done more cleverly */
- if (atsido && !done[xunchar(c = '.')]) { /* System type */
- if (max - i >= x.systemid.len + 2) { /* Enough space ? */
- data[i++] = c; /* Yes, add parameter */
- data[i++] = tochar(x.systemid.len); /* Add length */
- for (j = 0; j < x.systemid.len; j++) /* Add data */
- data[i++] = x.systemid.val[j];
- numset++; /* Count that we did at least one */
- done[xunchar(c)] = 1; /* Mark this attribute as done */
- } else /* No */
- left++; /* so mark this one left to do */
- }
- #ifdef STRATUS
- if (atcreo && !done[xunchar(c = '$')]) { /* Creator */
- if (max - i >= x.creator.len + 2) { /* Enough space ? */
- data[i++] = c;
- data[i++] = tochar(x.creator.len);
- for (j = 0; j < x.creator.len; j++)
- data[i++] = x.creator.val[j];
- numset++;
- done[xunchar(c)] = 1;
- } else
- left++;
- }
- if (atacto && !done[xunchar(c = '%')]) { /* File account */
- if (max - i >= x.account.len + 2) {
- data[i++] = c;
- data[i++] = tochar(x.account.len);
- for (j = 0; j < x.account.len; j++)
- data[i++] = x.account.val[j];
- numset++;
- done[xunchar(c)] = 1;
- } else
- left++;
- }
- if (atfrmo && !done[xunchar(c = '/')]) { /* Packet data format */
- if (max - i >= x.recfm.len + 2) {
- data[i++] = c;
- data[i++] = tochar(x.recfm.len); /* Copy from attr structure */
- for (j = 0; j < x.recfm.len; j++)
- data[i++] = x.recfm.val[j];
- numset++;
- done[xunchar(c)] = 1;
- } else
- left++;
- }
- #endif /* STRATUS */
- xbin = /* Is the transfer in binary mode? */
- #ifdef VMS
- binary == XYFT_I || binary == XYFT_L || /* IMAGE or LABELED */
- !strncmp(x.recfm.val,"F",1) /* or RECFM=Fxxxxxx */
- #else
- binary /* User said SET FILE TYPE BINARY */
- #endif /* VMS */
- ;
- if (attypo && !done[xunchar(c = '"')]) { /* File type */
- if (max - i >= 5) { /* Max length for this field */
- data[i++] = c;
- if (xbin) { /* Binary */
- data[i++] = tochar(2); /* Two characters */
- data[i++] = 'B'; /* B for Binary */
- data[i++] = '8'; /* 8-bit bytes (note assumption...) */
- #ifdef CK_LABELED
- if (binary != XYFT_L
- #ifdef VMS
- && binary != XYFT_I
- #endif /* VMS */
- )
- binary = XYFT_B;
- #endif /* CK_LABELED */
- } else { /* Text */
- #ifdef TSOFORMAT
- data[i++] = tochar(1); /* One character */
- data[i++] = 'A'; /* A = (extended) ASCII with CRLFs */
- #else
- data[i++] = tochar(3); /* Three characters */
- data[i++] = 'A'; /* A = (extended) ASCII with CRLFs */
- data[i++] = 'M'; /* M for carriage return */
- data[i++] = 'J'; /* J for linefeed */
- #endif /* TSOFORMAT */
- #ifdef VMS
- binary = XYFT_T; /* We automatically detected text */
- #endif /* VMS */
- }
- numset++;
- done[xunchar(c)] = 1;
- } else
- left++;
- }
- #ifdef TSOFORMAT
- if (attypo && !xbin && !done[xunchar(c = '/')]) { /* Record format */
- if (max - i >= 5) {
- data[i++] = c;
- data[i++] = tochar(3); /* Three characters */
- data[i++] = 'A'; /* A = variable with CRLFs */
- data[i++] = 'M'; /* M for carriage return */
- data[i++] = 'J'; /* J for linefeed */
- }
- }
- #endif /* TSOFORMAT */
- if (attypo && !xbin && !done[xunchar(c = '*')]) { /* Text encoding */
- #ifdef NOCSETS
- if (max - i >= 3) {
- data[i++] = c;
- data[i++] = tochar(1); /* Length of value is 1 */
- data[i++] = 'A'; /* A for ASCII */
- numset++;
- done[xunchar(c)] = 1;
- } else
- left++;
- #else
- if (tcharset == TC_TRANSP) { /* Transfer character set */
- if (max - i >= 3) {
- data[i++] = c; /* Encoding */
- data[i++] = tochar(1); /* Length of value is 1 */
- data[i++] = 'A'; /* A for ASCII */
- numset++;
- done[xunchar(c)] = 1;
- } else
- left++;
- } else {
- tp = tcsinfo[tcharset].designator;
- if (!tp) tp = "";
- aln = strlen(tp);
- if (aln > 0) {
- if (max - i >= aln + 2) {
- data[i++] = c; /* Encoding */
- data[i++] = tochar(aln+1); /* Length of designator. */
- data[i++] = 'C'; /* Text in specified charset. */
- for (j = 0; j < aln; j++) /* Copy designator */
- data[i++] = *tp++; /* Example: *&I6/100 */
- numset++;
- done[xunchar(c)] = 1;
- } else
- left++;
- } else
- done[xunchar(c)] = 1;
- }
- #endif /* NOCSETS */
- }
- if ((xp == 0 || calibrate) && (x.length > -1L)) { /* If it's a real file */
- if (atdato && !calibrate && /* Creation date, if any */
- !done[xunchar(c = '#')] &&
- (aln = x.date.len) > 0) {
- if (max - i >= aln + 2) {
- data[i++] = c;
- data[i++] = tochar(aln);
- for (j = 0; j < aln; j++)
- data[i++] = x.date.val[j];
- numset++;
- done[xunchar(c)] = 1;
- } else
- left++;
- }
- if (atleno && !done[xunchar(c = '!')]) { /* File length in K */
- sprintf((char *) &data[i+2],"%ld",x.lengthk);
- aln = (int)strlen((char *)(data+i+2));
- if (max - i >= aln + 2) {
- data[i] = c;
- data[i+1] = tochar(aln);
- i += aln + 2;
- numset++;
- done[xunchar(c)] = 1;
- } else {
- data[i] = NUL;
- left++;
- }
- }
- if (atleno && !done[xunchar(c = '1')]) { /* File length in bytes */
- sprintf((char *) &data[i+2],"%ld",x.length);
- aln = (int)strlen((char *)(data+i+2));
- if (max - i >= aln + 2) {
- data[i] = c;
- data[i+1] = tochar(aln);
- i += aln + 2;
- numset++;
- done[xunchar(c)] = 1;
- } else {
- data[i] = NUL;
- left++;
- }
- }
- #ifdef CK_PERMS
- if (atlpro && !done[xunchar(c = ',')] && /* Local protection */
- (aln = x.lprotect.len) > 0 && !calibrate) {
- if (max - i >= aln + 2) {
- data[i++] = c;
- data[i++] = tochar(aln);
- for (j = 0; j < aln; j++)
- data[i++] = x.lprotect.val[j];
- numset++;
- done[xunchar(c)] = 1;
- } else
- left++;
- }
- if (atgpro && !done[xunchar(c = '-')] && /* Generic protection */
- (aln = x.gprotect.len) > 0 && !calibrate) {
- if (max - i >= aln + 2) {
- data[i++] = c;
- data[i++] = tochar(aln);
- for (j = 0; j < aln; j++)
- data[i++] = x.gprotect.val[j];
- numset++;
- done[xunchar(c)] = 1;
- } else
- left++;
- }
- #endif /* CK_PERMS */
- if (atblko && fblksiz && !done[xunchar(c = '(')] &&
- !calibrate) { /* Blocksize */
- sprintf((char *) &data[i+2],"%d",fblksiz);
- aln = (int)strlen((char *)(data+i+2));
- if (max - i >= aln + 2) {
- data[i] = c;
- data[i+1] = tochar(aln);
- i += aln + 2;
- numset++;
- done[xunchar(c)] = 1;
- } else {
- data[i] = NUL;
- left++;
- }
- }
- }
- #ifndef NOFRILLS
- if ((rprintf || rmailf) && atdiso && /* MAIL, or REMOTE PRINT? */
- !done[xunchar(c = '+')]) {
- aln = (int) strlen(optbuf) + 1; /* Options, if any */
- if (max - i >= aln + 2) {
- data[i++] = c; /* Disposition */
- data[i++] = tochar(aln); /* Options, if any */
- if (rprintf)
- data[i++] = 'P'; /* P for Print */
- else
- data[i++] = 'M'; /* M for Mail */
- for (j = 0; optbuf[j]; j++) /* Copy any options */
- data[i++] = optbuf[j];
- numset++;
- done[xunchar(c)] = 1;
- } else {
- data[i] = NUL;
- left++;
- }
- }
- #endif /* NOFRILLS */
- #ifdef CK_RESEND
- if (sendmode == SM_RESEND && !done[xunchar(c = '+')]) {
- if (max - i >= 3) {
- data[i++] = c; /* Disposition */
- data[i++] = tochar(1);
- data[i++] = 'R'; /* is RESEND */
- numset++;
- done[xunchar(c)] = 1;
- } else
- left++;
- }
- #endif /* CK_RESEND */
- /* End of Attributes -- to be sent only after sending all others */
- debug(F111,"sattr","@",i);
- debug(F101,"sattr numset","",numset);
- debug(F101,"sattr left","",left);
- if ((left == 0 || numset == 0) && !done[xunchar(c = '@')]) {
- if (max - i >= 3) {
- data[i++] = c; /* End of Attributes */
- data[i++] = SP; /* Length 0 */
- data[i] = NUL; /* Make sure it's null-terminated */
- numset++;
- done[xunchar(c)] = 1;
- }
- }
- /* Finished - send the packet off if we have anything in it */
- if (numset) {
- data[i] = NUL; /* Terminate last good field */
- debug(F111,"sattr sending",data,left);
- aln = (int)strlen((char *)data); /* Get overall length of attributes */
- return(spack('A',pktnum,aln,data)); /* Send it */
- } else
- return(0);
- }
- static char *refused = "";
- static char *reason[] = {
- "size", "type", "date", "creator", "account", "area", "password",
- "blocksize", "access", "encoding", "disposition", "protection",
- "protection", "origin", "format",
- "sys-dependent", /* 0 */
- "size", /* 1 */
- "2", /* 2 */
- "3", /* 3 */
- "4", /* 4 */
- "5", /* 5 */
- "6", /* 6 */
- "7", /* 7 */
- "8", /* 8 */
- "9", /* 9 */
- ":", /* : */
- ";", /* ; */
- "<", /* < */
- "=", /* = */
- ">", /* > */
- "name", /* ? */
- "@"
- };
- static int nreason = sizeof(reason) / sizeof(char *);
- int rejection = -1;
- char *
- getreason(s) char *s; { /* Decode attribute refusal reason */
- char c, *p;
- if (rejection == 1) /* Kludge for SET FIL COLL DISCARD */
- return("name"); /* when other Kermit doesn't... */
- p = s;
- if (*p++ != 'N') return(""); /* Should start with N */
- else if ((c = *p) > SP) { /* get reason, */
- rejection = c; /* remember it, */
- c -= '!'; /* get offset */
- p = ((unsigned int) ((CHAR) c) <= nreason) ? reason[c] : "unknown";
- }
- return(p);
- }
- int
- rsattr(s) CHAR *s; { /* Read response to attribute packet */
- debug(F111,"rsattr",s,*s);
- if (*s == 'N') { /* If it's 'N' followed by anything, */
- refused = getreason((char *)s); /* they are refusing, get reason. */
- debug(F110,"rsattr refused",refused,0);
- tlog(F110," refused:",refused,0L);
- return(-1);
- }
- #ifdef CK_RESEND
- if (sendmode == SM_RESEND && *s == '1') { /* RESEND length */
- int n; long z; CHAR *p;
- p = s + 1;
- n = xunchar(*p++);
- debug(F101,"rsattr RESEND n","",n);
- z = 0L;
- while (n-- > 0) /* We assume the format is good. */
- z = 10L * z + (long) (*p++ - '0');
- debug(F101,"rsattr RESEND z","",z);
- if (z > 0L) sendstart = z;
- debug(F101,"rsattr RESEND sendstart","",sendstart);
- if (sendstart > 0L)
- if (zfseek(sendstart) < 0) /* Input file is already open. */
- return(0);
- #ifdef CK_CURSES
- if (fdispla == XYFD_C)
- xxscreen(SCR_FS,0,fsize,""); /* Refresh file transfer display */
- #endif /* CK_CURSES */
- }
- #endif /* CK_RESEND */
- refused = "";
- return(0);
- }
- long rs_len = 0L; /* Length of file being resent to */
- /*
- Get attributes from incoming A packet. Returns:
- 0 on success, file is to be accepted
- -1 on failure, file is to be refused
- */
- int
- gattr(s, yy) CHAR *s; struct zattr *yy; { /* Read incoming attribute packet */
- char c, d;
- char *ff;
- int aln, i;
- #ifndef NOCSETS
- extern int r_cset, axcset[];
- #endif /* NOCSETS */
- #define ABUFL 40 /* Temporary buffer for conversions */
- char abuf[ABUFL+1];
- #define RFBUFL 10 /* Record-format buffer */
- static char rfbuf[RFBUFL+1];
- #define FTBUFL 10 /* File type buffer */
- static char ftbuf[FTBUFL+1];
- #define DTBUFL 40 /* File creation date */
- static char dtbuf[DTBUFL+1];
- #define TSBUFL 10 /* Transfer syntax */
- static char tsbuf[TSBUFL+1];
- #define IDBUFL 10 /* System ID */
- static char idbuf[IDBUFL+1];
- #ifndef DYNAMIC
- #define DSBUFL 100 /* Disposition */
- static char dsbuf[DSBUFL+1];
- #define SPBUFL 512 /* System-dependent parameters */
- static char spbuf[SPBUFL+1];
- #else
- #define DSBUFL 100 /* Disposition */
- static char *dsbuf = NULL;
- #define SPBUFL 512 /* System-dependent parameters */
- static char *spbuf = NULL;
- #endif /* DYNAMIC */
- #define RPBUFL 20 /* Attribute reply */
- static char rpbuf[RPBUFL+1];
- #ifdef CK_PERMS
- static char lprmbuf[CK_PERMLEN+1];
- static char gprmbuf[2];
- #endif /* CK_PERMS */
- char *rp; /* Pointer to reply buffer */
- int retcode; /* Return code */
- d = SP; /* Initialize disposition */
- ff = filnam; /* Filename returned by rcvfil */
- if (fncact == XYFX_R && ofn1x && ofn1[0]) /* But watch out for FC=RENAME */
- ff = ofn1; /* because we haven't renamed it yet */
- /* Fill in the attributes we have received */
- rp = rpbuf; /* Initialize reply buffer */
- *rp++ = 'N'; /* for negative reply. */
- *rp = NUL;
- retcode = 0; /* Initialize return code. */
- if (dest == DEST_P) { /* SET DESTINATION PRINTER */
- #ifdef DYNAMIC
- if (!dsbuf)
- if ((dsbuf = malloc(DSBUFL+1)) == NULL)
- fatal("gtattr: no memory for dsbuf");
- #endif /* DYNAMIC */
- dsbuf[0] = 'P';
- dsbuf[1] = ' ';
- yy->disp.val = dsbuf;
- yy->disp.len = 1;
- }
- while (c = *s++) { /* Get attribute tag */
- aln = xunchar(*s++); /* Length of attribute string */
- switch (c) {
- case '!': /* File length in K */
- for (i = 0; (i < aln) && (i < ABUFL); i++) /* Copy it */
- abuf[i] = *s++;
- abuf[i] = ' '; /* Terminate with null */
- if (i < aln) s += (aln - i); /* If field was too long for buffer */
- yy->lengthk = atol(abuf); /* Convert to number */
- break;
- case '/': /* Record format */
- rfbuf[1] = NUL;
- rfbuf[2] = NUL;
- for (i = 0; (i < aln) && (i < RFBUFL); i++) /* Copy it */
- rfbuf[i] = *s++;
- rfbuf[i] = NUL; /* Terminate with null */
- yy->recfm.val = rfbuf; /* Pointer to string */
- yy->recfm.len = i; /* Length of string */
- if ((rfbuf[0] != 'A') ||
- (rfbuf[1] && rfbuf[1] != 'M') ||
- (rfbuf[2] && rfbuf[2] != 'J')) {
- debug(F110,"gattr bad recfm",rfbuf,0);
- *rp++ = c;
- retcode = -1;
- }
- break;
- case '"': /* File type (text, binary, ...) */
- for (i = 0; (i < aln) && (i < FTBUFL); i++)
- ftbuf[i] = *s++; /* Copy it into a static string */
- ftbuf[i] = ' ';
- if (i < aln) s += (aln - i);
- /* TYPE attribute is enabled? */
- if (attypi) {
- yy->type.val = ftbuf; /* Pointer to string */
- yy->type.len = i; /* Length of string */
- debug(F111,"gattr file type", ftbuf, i);
- debug(F101,"gattr binary 1","",binary);
- /* Unknown type? */
- if ((*ftbuf != 'A' && *ftbuf != 'B' && *ftbuf != 'I')
- #ifdef CK_LABELED
- /* ... Or our FILE TYPE is LABELED and the incoming file is text... */
- || (binary == XYFT_L && *ftbuf == 'A' && !xflg)
- #endif /* CK_LABELED */
- ) {
- retcode = -1; /* Reject the file */
- *rp++ = c;
- if (!opnerr) tlog(F100," refused: type","",0);
- break;
- }
- /*
- The following code moved here from opena() so we set binary mode
- as soon as requested by the attribute packet. That way when the first
- data packet comes, the mode of transfer can be displayed correctly
- before opena() is called.
- */
- if (yy->type.val[0] == 'A') { /* Check received attributes. */
- #ifdef VMS
- if (binary != XYFT_I) /* VMS IMAGE overrides this */
- #endif /* VMS */
- binary = XYFT_T; /* Set current type to Text. */
- debug(F101,"gattr attribute A=text","",binary);
- } else if (yy->type.val[0] == 'B') {
- #ifdef CK_LABELED
- if (binary != XYFT_L
- #ifdef VMS
- && binary != XYFT_U /* VMS special case */
- #endif /* VMS */
- )
- #endif /* CK_LABELED */
- #ifdef MAC
- if (binary != XYFT_M) /* If not MacBinary... */
- #endif /* MAC */
- binary = XYFT_B;
- debug(F101,"gattr binary 2","",binary);
- }
- }
- break;
- case '#': /* File creation date */
- for (i = 0; (i < aln) && (i < DTBUFL); i++)
- dtbuf[i] = *s++; /* Copy it into a static string */
- if (i < aln) s += (aln - i);
- dtbuf[i] = ' ';
- if (atdati) {
- yy->date.val = dtbuf; /* Pointer to string */
- yy->date.len = i; /* Length of string */
- if (fncact == XYFX_U) { /* Receiving in update mode? */
- if (zstime(ff,yy,1) > 0) { /* Compare dates */
- *rp++ = c; /* Discard if older, reason = date. */
- if (!opnerr) tlog(F100," refused: date","",0);
- retcode = -1; /* Rejection notice. */
- }
- }
- }
- break;
- case '(': /* File Block Size */
- for (i = 0; (i < aln) && (i < ABUFL); i++) /* Copy it */
- abuf[i] = *s++;
- abuf[i] = ' '; /* Terminate with null */
- if (i < aln) s += (aln - i);
- if (atblki)
- yy->blksize = atol(abuf); /* Convert to number */
- break;
- case '*': /* Encoding (transfer syntax) */
- for (i = 0; (i < aln) && (i < TSBUFL); i++)
- tsbuf[i] = *s++; /* Copy it into a static string */
- if (i < aln) s += (aln - i);
- tsbuf[i] = ' ';
- #ifndef NOCSETS
- xlatype = XLA_NONE; /* Assume no translation */
- #endif /* NOCSETS */
- if (atenci) {
- char * ss;
- yy->encoding.val = tsbuf; /* Pointer to string */
- yy->encoding.len = i; /* Length of string */
- debug(F101,"gattr encoding",tsbuf,i);
- ss = tsbuf+1;
- switch (*tsbuf) {
- #ifndef NOCSETS
- case 'A': /* Normal, nothing special */
- tcharset = TC_TRANSP; /* Transparent chars untranslated */
- break;
- case 'C': /* Specified character set */
- #ifdef UNICODE
- if (!strcmp("I196",ss)) /* Treat I196 (UTF-8 no level) */
- ss = "I190"; /* as I190 (UTF-8 Level 1) */
- #endif /* UNICODE */
- if (!strcmp("I6/204",ss)) /* Treat "Latin-1 + Euro" */
- ss = "I6/100"; /* as I6/100 (regular Latin-1) */
- for (i = 0; i < ntcsets; i++) {
- if (!strcmp(tcsinfo[i].designator,ss))
- break;
- }
- debug(F101,"gattr xfer charset lookup","",i);
- if (i == ntcsets) { /* If unknown character set, */
- debug(F110,"gattr: xfer charset unknown",ss,0);
- if (!unkcs) { /* and SET UNKNOWN DISCARD, */
- retcode = -1; /* reject the file. */
- *rp++ = c;
- if (!opnerr)
- tlog(F100," refused: character set","",0);
- }
- } else {
- tcharset = tcsinfo[i].code; /* it's known, use it */
- debug(F101,"gattr switch tcharset","",tcharset);
- debug(F101,"gattr fcharset","",fcharset);
- if (r_cset == XMODE_A) { /* Automatic switching? */
- if (tcharset > -1 && tcharset <= MAXTCSETS) {
- int x;
- x = axcset[tcharset];
- if (x > 0 && x <= MAXFCSETS) {
- fcharset = x;
- debug(F101,"gattr switch fcharset","",x);
- }
- }
- }
- /* Set up translation type and function */
- setxlatype(tcharset,fcharset);
- }
- break;
- #endif /* NOCSETS */
- default: /* Something else. */
- debug(F110,"gattr unk encoding attribute",tsbuf,0);
- if (!unkcs) { /* If SET UNK DISC */
- retcode = -1;
- *rp++ = c;
- if (!opnerr) tlog(F100," refused: encoding","",0);
- }
- break;
- }
- }
- break;
- case '+': /* Disposition */
- #ifdef DYNAMIC
- if (!dsbuf)
- if ((dsbuf = malloc(DSBUFL+1)) == NULL)
- fatal("gtattr: no memory for dsbuf");
- #endif /* DYNAMIC */
- for (i = 0; (i < aln) && (i < DSBUFL); i++)
- dsbuf[i] = *s++; /* Copy it into a separate string */
- dsbuf[i] = ' ';
- if (i < aln) s += (aln - i);
- rs_len = 0;
- if (atdisi) { /* We are doing this attribute */
- /* Copy it into the attribute structure */
- yy->disp.val = dsbuf; /* Pointer to string */
- yy->disp.len = i; /* Length of string */
- d = *dsbuf;
- #ifndef NODISPO
- /*
- Define NODISPO to disable receipt of mail or print files and of RESEND.
- */
- if (
- #ifndef datageneral /* MAIL supported only for */
- #ifndef OS2 /* UNIX, VMS, and OS-9 */
- #ifndef MAC
- #ifndef GEMDOS
- #ifndef AMIGA
- d != 'M' && /* MAIL */
- #endif /* AMIGA */
- #endif /* GEMDOS */
- #endif /* MAC */
- #endif /* OS/2 */
- #endif /* datageneral */
- #ifdef CK_RESEND
- d != 'R' && /* RESEND */
- #endif /* CK_RESEND */
- d != 'P') { /* PRINT */
- retcode = -1; /* Unknown/unsupported disposition */
- *rp++ = c;
- if (!opnerr) tlog(F101," refused: bad disposition","",d);
- }
- #ifndef NOFRILLS
- if (d == 'M' && !en_mai) {
- retcode = -1;
- *rp++ = c;
- if (!opnerr) tlog(F100," refused: mail disabled","",0);
- } else
- #endif /* NOFRILLS */
- if (d == 'P' && !en_pri) {
- retcode = -1;
- *rp++ = c;
- if (!opnerr) tlog(F100," refused: print disabled","",0);
- } else if (d == 'R') { /* File is being resent */
- #ifdef CK_RESEND
- rs_len = zchki(ff); /* Get length of file */
- debug(F111,"gattr RESEND",ff,rs_len);
- #ifdef VMS
- rs_len &= (long) -512; /* Ensure block boundary if VMS */
- rs_len -= 512; /* In case last block not complete */
- debug(F111,"gattr rs_len",ff,rs_len);
- #endif /* VMS */
- if (rs_len < 0L)
- rs_len = 0L;
- /*
- Another possibility here (or later, really) would be to check if the two
- file lengths are the same, and if so, keep the prevailing collision action
- as is (note: rs_len == length of existing file; yy->length == fsize ==
- length of incoming file). This could be complicated, though, since
- (a) we might not have received the length attribute yet, and in fact it
- might even be in a subsequent A-packet, yet (b) we have to accept or reject
- the Recover attribute now. So better to leave as-is. Anyway, it's probably
- more useful this way.
- */
- if (rs_len > 0L) {
- fncsav = fncact; /* Save collision action */
- fncact = XYFX_A; /* Switch to APPEND */
- }
- #else
- retcode = -1; /* This shouldn't happen */
- *rp++ = c; /* 'cause it wasn't negotiated. */
- if (!opnerr) tlog(F100," refused: resend","",0);
- #endif /* CK_RESEND */
- }
- #else /* NODISPO */
- retcode = -1;
- *rp++ = c;
- if (!opnerr) tlog(F100," refused: NODISPO","",0);
- #endif /* NODISPO */
- }
- break;
- case '.': /* Sender's system ID */
- for (i = 0; (i < aln) && (i < IDBUFL); i++)
- idbuf[i] = *s++; /* Copy it into a static string */
- idbuf[i] = ' ';
- if (i < aln) s += (aln - i);
- if (atsidi) {
- yy->systemid.val = idbuf; /* Pointer to string */
- yy->systemid.len = i; /* Length of string */
- }
- break;
- case '0': /* System-dependent parameters */
- #ifdef DYNAMIC
- if (!spbuf && !(spbuf = malloc(SPBUFL)))
- fatal("gattr: no memory for spbuf");
- #endif /* DYNAMIC */
- for (i = 0; (i < aln) && (i < SPBUFL); i++)
- spbuf[i] = *s++; /* Copy it into a static string */
- spbuf[i] = ' ';
- if (i < aln) s += (aln - i);
- if (atsysi) {
- yy->sysparam.val = spbuf; /* Pointer to string */
- yy->sysparam.len = i; /* Length of string */
- }
- break;
- case '1': /* File length in bytes */
- for (i = 0; (i < aln) && (i < ABUFL); i++) /* Copy it */
- abuf[i] = *s++;
- abuf[i] = ' '; /* Terminate with null */
- if (i < aln) s += (aln - i);
- yy->length = atol(abuf); /* Convert to number */
- debug(F111,"gattr length",abuf,(int) yy->length);
- break;
- #ifdef CK_PERMS
- case ',': /* System-dependent protection code */
- for (i = 0; (i < aln) && (i < CK_PERMLEN); i++)
- lprmbuf[i] = *s++; /* Just copy it - decode later */
- lprmbuf[i] = ' '; /* Terminate with null */
- if (i < aln) s += (aln - i);
- if (atlpri) {
- yy->lprotect.val = (char *)lprmbuf;
- yy->lprotect.len = i;
- }
- break;
- case '-': /* Generic "world" protection code */
- gprmbuf[0] = NUL; /* Just 1 byte by definition */
- for (i = 0; i < aln; i++) /* But allow for more... */
- if (i == 0) gprmbuf[0] = *s++;
- gprmbuf[1] = NUL;
- if (atgpri) {
- yy->gprotect.val = (char *)gprmbuf;
- yy->gprotect.len = gprmbuf[0] ? 1 : 0;
- }
- break;
- #endif /* CK_PERMS */
- default: /* Unknown attribute */
- s += aln; /* Just skip past it */
- break;
- }
- }
- /* Check file length now, because we also need to know the file type */
- /* in case zchkspa() differentiates text and binary (VMS version does) */
- if (atleni) { /* Length attribute enabled? */
- if (yy->length > -1L) { /* Length-in-bytes attribute rec'd? */
- if (!zchkspa(ff,(yy->length))) { /* Check space */
- retcode = -1; /* Not enuf */
- *rp++ = '1';
- if (!opnerr) tlog(F100," refused: length bytes","",0);
- }
- } else if (yy->lengthk > -1L) { /* Length in K attribute rec'd? */
- if (!zchkspa(ff,(yy->lengthk * 1024))) {
- retcode = -1; /* Check space */
- *rp++ = '!';
- if (!opnerr) tlog(F100," refused: length K","",0);
- }
- }
- }
- if (yy->length > -1L) { /* Remember the file size */
- fsize = yy->length;
- } else if (yy->lengthk > -1L) {
- fsize = yy->lengthk * 1024L;
- } else fsize = -1L;
- #ifdef DEBUG
- if (deblog) {
- sprintf(abuf,"%ld",fsize);
- debug(F110,"gattr fsize",abuf,0);
- }
- #endif /* DEBUG */
- if (retcode == 0) rp = rpbuf; /* Null reply string if accepted */
- *rp = ' '; /* End of reply string */
- #ifdef CK_RESEND
- if (d == 'R') { /* Receiving a RESEND? */
- debug(F101,"gattr RESEND","",retcode);
- /* We ignore retcodes because this overrides */
- if (binary != XYFT_B) { /* Reject if not binary */
- retcode = -1; /* in case type field came */
- ckstrncpy(rpbuf,"N+",RPBUFL); /* after the disposition field */
- debug(F111,"gattr RESEND not binary",rpbuf,binary);
- } else { /* Binary mode */
- retcode = 0; /* Accept the file */
- discard = 0; /* If SET FILE COLLISION DISCARD */
- sprintf(rpbuf+2,"%ld",rs_len); /* Reply with length of file */
- rpbuf[0] = '1'; /* '1' means Length in Bytes */
- rpbuf[1] = tochar((int)strlen(rpbuf+2)); /* Length of length */
- debug(F111,"gattr RESEND OK",rpbuf,retcode);
- }
- }
- #endif /* CK_RESEND */
- if (retcode == 0 && discard != 0) { /* Do we still have a discard flag? */
- ckstrncpy(rpbuf,"N?",RPBUFL); /* Yes, must be filename collision */
- retcode = -1; /* "?" = name (reply-only code) */
- }
- yy->reply.val = rpbuf; /* Add it to attribute structure */
- yy->reply.len = (int)strlen(rpbuf);
- if (retcode < 0) { /* If we are rejecting */
- discard = 1; /* remember to discard the file */
- rejection = rpbuf[1]; /* and use the first reason given. */
- if (fncsav != -1) {
- fncact = fncsav;
- fncsav = -1;
- }
- }
- debug(F111,"gattr return",rpbuf,retcode);
- return(retcode);
- }
- /* I N I T A T T R -- Initialize file attribute structure */
- int
- initattr(yy) struct zattr *yy; {
- yy->lengthk = yy->length = -1L;
- yy->type.val = "";
- yy->type.len = 0;
- yy->date.val = "";
- yy->date.len = 0;
- yy->encoding.val = "";
- yy->encoding.len = 0;
- yy->disp.val = "";
- yy->disp.len = 0;
- yy->systemid.val = "";
- yy->systemid.len = 0;
- yy->sysparam.val = "";
- yy->sysparam.len = 0;
- yy->creator.val = "";
- yy->creator.len = 0;
- yy->account.val = "";
- yy->account.len = 0;
- yy->area.val = "";
- yy->area.len = 0;
- yy->password.val = "";
- yy->password.len = 0;
- yy->blksize = -1L;
- yy->xaccess.val = "";
- yy->xaccess.len = 0;
- #ifdef CK_PERMS
- if (!ofperms) ofperms = "";
- debug(F110,"initattr ofperms",ofperms,0);
- yy->lprotect.val = ofperms;
- yy->lprotect.len = 0 - strlen(ofperms); /* <-- NOTE! */
- /*
- A negative length indicates that we have a permissions string but it has
- been inherited from a previously existing file rather than picked up
- from an incoming A-packet.
- */
- #else
- yy->lprotect.val = "";
- yy->lprotect.len = 0;
- #endif /* CK_PERMS */
- yy->gprotect.val = "";
- yy->gprotect.len = 0;
- yy->recfm.val = "";
- yy->recfm.len = 0;
- yy->reply.val = "";
- yy->reply.len = 0;
- #ifdef OS2
- yy->longname.len = 0 ;
- yy->longname.val = "" ;
- #endif /* OS2 */
- return(0);
- }
- /* A D E B U -- Write attribute packet info to debug log */
- int
- adebu(f,zz) char *f; struct zattr *zz; {
- #ifdef DEBUG
- if (deblog == 0) return(0);
- debug(F110,"Attributes for incoming file ",f,0);
- debug(F101," length in K","",(int) zz->lengthk);
- debug(F111," file type",zz->type.val,zz->type.len);
- debug(F111," creation date",zz->date.val,zz->date.len);
- debug(F111," creator",zz->creator.val,zz->creator.len);
- debug(F111," account",zz->account.val,zz->account.len);
- debug(F111," area",zz->area.val,zz->area.len);
- debug(F111," password",zz->password.val,zz->password.len);
- debug(F101," blksize","",(int) zz->blksize);
- debug(F111," access",zz->xaccess.val,zz->xaccess.len);
- debug(F111," encoding",zz->encoding.val,zz->encoding.len);
- debug(F111," disposition",zz->disp.val,zz->disp.len);
- debug(F111," lprotection",zz->lprotect.val,zz->lprotect.len);
- debug(F111," gprotection",zz->gprotect.val,zz->gprotect.len);
- debug(F111," systemid",zz->systemid.val,zz->systemid.len);
- debug(F111," recfm",zz->recfm.val,zz->recfm.len);
- debug(F111," sysparam",zz->sysparam.val,zz->sysparam.len);
- debug(F101," length","",(int) zz->length);
- debug(F110," reply",zz->reply.val,0);
- #endif /* DEBUG */
- return(0);
- }
- /* O P E N A -- Open a file, with attributes. */
- /*
- This function tries to open a new file to put the arriving data in. The
- filename is the one in the srvcmd buffer. File collision actions are:
- OVERWRITE (the existing file is overwritten), RENAME (the new file is
- renamed), BACKUP (the existing file is renamed), DISCARD (the new file is
- refused), UPDATE (the incoming file replaces the existing file only if the
- incoming file has a newer creation date).
- Returns 0 on failure, nonzero on success.
- */
- extern char *rf_err;
- int
- opena(f,zz) char *f; struct zattr *zz; {
- int x, dispos = 0;
- static struct filinfo fcb; /* Must be static! */
- debug(F110,"opena f",f,0);
- debug(F101,"opena discard","",discard);
- adebu(f,zz); /* Write attributes to debug log */
- ffc = 0L; /* Init file-character counter */
- #ifdef PIPESEND
- if (pipesend) /* Receiving to a pipe - easy. */
- return(openo(f,zz,&fcb)); /* Just open the pipe. */
- #endif /* PIPESEND */
- /* Receiving to a file - set up file control structure */
- fcb.bs = fblksiz; /* Blocksize */
- #ifndef NOCSETS
- fcb.cs = fcharset; /* Character set */
- #else
- fcb.cs = 0; /* Character set */
- #endif /* NOCSETS */
- fcb.rl = frecl; /* Record Length */
- fcb.fmt = frecfm; /* Record Format */
- fcb.org = forg; /* Organization */
- fcb.cc = fcctrl; /* Carriage control */
- fcb.typ = binary; /* Type */
- debug(F101,"opena xflg","",xflg);
- debug(F101,"opena remfile","",remfile);
- debug(F101,"opena remappd","",remappd);
- if (xflg && remfile && remappd) /* REMOTE output redirected with >> */
- fcb.dsp = XYFZ_A;
- else
- fcb.dsp = (fncact == XYFX_A) ? XYFZ_A : XYFZ_N; /* Disposition */
- debug(F101,"opena disp","",fcb.dsp);
- fcb.os_specific = ' '; /* OS-specific info */
- #ifdef CK_LABELED
- fcb.lblopts = lf_opts; /* Labeled file options */
- #else
- fcb.lblopts = 0;
- #endif /* CK_LABELED */
- if (zz->disp.len > 0) { /* Incoming file has a disposition? */
- debug(F111,"open disposition",zz->disp.val,zz->disp.len);
- dispos = (int) (*(zz->disp.val));
- }
- if (!dispos && xflg && remfile && remappd) /* REMOTE redirect append ? */
- dispos = fcb.dsp;
- debug(F101,"opena dispos","",dispos);
- if (!dispos) { /* No special disposition? */
- if (fncact == XYFX_B && ofn1x && ofn2) { /* File collision = BACKUP? */
- if (zrename(ofn1,ofn2) < 0) { /* Rename existing file. */
- debug(F110,"opena rename fails",ofn1,0);
- rf_err = "Can't create backup file";
- return(0);
- } else debug(F110,"opena rename ok",ofn2,0);
- }
- } else if (dispos == 'R') { /* Receiving a RESEND */
- #ifdef COMMENT
- if (fncact == XYFX_R) /* and file collision = RENAME */
- if (ofn1x)
- #endif /* COMMENT */
- if (ofn1[0])
- f = ofn1; /* use original name. */
- if (fncact == XYFX_R) /* if file collision is RENAME */
- ckstrncpy(filnam,ofn1,CKMAXPATH+1); /* restore the real name */
- xxscreen(SCR_AN,0,0L,f); /* update name on screen */
- }
- debug(F111,"opena [file]=mode: ",f,fcb.dsp);
- if (x = openo(f,zz,&fcb)) { /* Try to open the file. */
- #ifdef pdp11
- tlog(F110," local name:",f,0L); /* OK, open, record local name. */
- makestr(&rfspec,f);
- #else
- #ifndef ZFNQFP
- tlog(F110," local name:",f,0L);
- makestr(&rfspec,f);
- #else
- { /* Log full local pathname */
- char *p = NULL, *q = f;
- if ((p = malloc(CKMAXPATH+1)))
- if (zfnqfp(filnam, CKMAXPATH, p))
- q = p;
- tlog(F110," local name:",q,0L);
- makestr(&rfspec,q);
- if (p) free(p);
- }
- #endif /* ZFNQFP */
- #endif /* pdp11 */
- if (binary) { /* Log file mode in transaction log */
- tlog(F101," mode: binary","",(long) binary);
- } else { /* If text mode, check character set */
- tlog(F100," mode: text","",0L);
- #ifndef NOCSETS
- if (fcharset > -1 && fcharset <= MAXFCSETS)
- tlog(F110," file character-set:",fcsinfo[fcharset].name,0L);
- if (tcharset > -1 && tcharset <= MAXTCSETS)
- tlog(F110," xfer character-set:",tcsinfo[tcharset].name,0L);
- #endif /* NOCSETS */
- debug(F111," opena charset",zz->encoding.val,zz->encoding.len);
- }
- if (fsize > -1L) xxscreen(SCR_FS,0,fsize,"");
- #ifdef datageneral
- /*
- Need to turn on multi-tasking console interrupt task here, since multiple
- files may be received (huh?) ...
- */
- if ((local) && (!quiet)) /* Only do this if local & not quiet */
- consta_mt(); /* Start the async read task */
- #endif /* datageneral */
- } else { /* Did not open file OK. */
- rf_err = ck_errstr(); /* Get system error message */
- if (*rf_err)
- xxscreen(SCR_EM,0,0l,rf_err);
- else
- xxscreen(SCR_EM,0,0l,"Can't open output file");
- tlog(F110,"Failure to open",f,0L);
- tlog(F110,"Error:",rf_err,0L);
- debug(F110,"opena error",rf_err,0);
- }
- return(x); /* Pass on return code from openo */
- }
- /* O P E N C -- Open a command (in place of a file) for output */
- int
- openc(n,s) int n; char * s; {
- int x;
- #ifndef NOPUSH
- x = zxcmd(n,s);
- #else
- x = 0;
- #endif /* NOPUSH */
- debug(F111,"openc zxcmd",s,x);
- o_isopen = (x > 0) ? 1 : 0;
- return(x);
- }
- /* C A N N E D -- Check if current file transfer cancelled */
- int
- canned(buf) CHAR *buf; {
- extern int interrupted;
- if (*buf == 'X') cxseen = 1;
- if (*buf == 'Z') czseen = 1;
- if (czseen || cxseen)
- interrupted = 1;
- debug(F101,"canned: cxseen","",cxseen);
- debug(F101," czseen","",czseen);
- return((czseen || cxseen) ? 1 : 0);
- }
- /* O P E N I -- Open an existing file for input */
- int
- openi(name) char *name; {
- #ifndef NOSERVER
- extern int fromgetpath;
- #endif /* NOSERVER */
- int x, filno;
- char *name2;
- extern CHAR *epktmsg;
- epktmsg[0] = NUL; /* Initialize error message */
- if (memstr || sndarray) { /* Just return if "file" is memory. */
- i_isopen = 1;
- return(1);
- }
- debug(F110,"openi name",name,0);
- debug(F101,"openi sndsrc","",sndsrc);
- filno = (sndsrc == 0) ? ZSTDIO : ZIFILE; /* ... */
- debug(F101,"openi file number","",filno);
- #ifndef NOSERVER
- /* If I'm a server and CWD is disabled and name is not from GET-PATH... */
- if (server && !en_cwd && !fromgetpath) {
- zstrip(name,&name2);
- if ( /* ... check if pathname included. */
- #ifdef VMS
- zchkpath(name)
- #else
- strcmp(name,name2)
- #endif /* VMS */
- ) {
- tlog(F110,name,"access denied",0L);
- debug(F110,"openi CD disabled",name,0);
- ckstrncpy((char *)epktmsg,"Access denied",PKTMSGLEN);
- return(0);
- } else name = name2;
- }
- #endif /* NOSERVER */
- #ifdef PIPESEND
- if (pipesend) {
- int x;
- #ifndef NOPUSH
- x = zxcmd(ZIFILE,name);
- #else
- x = 0;
- #endif /* NOPUSH */
- i_isopen = (x > 0) ? 1 : 0;
- if (!i_isopen)
- ckstrncpy((char *)epktmsg,"Command or pipe failure",PKTMSGLEN);
- debug(F111,"openi pipesend zxcmd",name,x);
- return(i_isopen);
- }
- #endif /* PIPESEND */
- #ifdef CALIBRATE
- if (calibrate) {
- i_isopen = 1;
- return(1);
- }
- #endif /* CALIBRATE */
- x = zopeni(filno,name); /* Otherwise, try to open it. */
- debug(F111,"openi zopeni 1",name,x);
- if (x) {
- i_isopen = 1;
- return(1);
- } else { /* If not found, */
- char xname[CKMAXPATH]; /* convert the name */
- #ifdef NZLTOR
- nzrtol(name,xname,fncnv,fnrpath,CKMAXPATH);
- #else
- zrtol(name,xname); /* to local form and then */
- #endif /* NZLTOR */
- x = zopeni(filno,xname); /* try opening it again. */
- debug(F101,"openi zopeni 2",xname,x);
- if (x) {
- i_isopen = 1;
- return(1); /* It worked. */
- } else {
- char * s;
- s = ck_errstr();
- if (s) if (!s) s = NULL;
- if (!s) s = "Can't open file";
- ckstrncpy((char *)epktmsg,s,PKTMSGLEN);
- tlog(F110,xname,s,0L);
- debug(F110,"openi failed",xname,0);
- debug(F110,"openi message",s,0);
- i_isopen = 0;
- return(0);
- }
- }
- }
- /* O P E N O -- Open a new file for output. */
- int
- openo(name,zz,fcb) char *name; struct zattr *zz; struct filinfo *fcb; {
- char *name2;
- #ifdef DTILDE
- char *dirp;
- #endif /* DTILDE */
- int channel, x;
- if (stdouf) { /* Receiving to stdout? */
- x = zopeno(ZSTDIO,"",zz,NULL);
- o_isopen = (x > 0);
- debug(F101,"openo stdouf zopeno","",x);
- return(x);
- }
- debug(F110,"openo: name",name,0);
- if (cxseen || czseen || discard) { /* If interrupted, get out before */
- debug(F100," open cancelled","",0); /* destroying existing file. */
- return(1); /* Pretend to succeed. */
- }
- channel = ZOFILE; /* SET DESTINATION DISK or PRINTER */
- #ifdef PIPESEND
- debug(F101,"openo pipesend","",pipesend);
- if (pipesend) {
- int x;
- #ifndef NOPUSH
- x = zxcmd(ZOFILE,(char *)srvcmd);
- #else
- x = 0;
- #endif /* NOPUSH */
- o_isopen = x > 0;
- debug(F101,"openo zxcmd","",x);
- return(x);
- }
- #endif /* PIPESEND */
- if (dest == DEST_S) { /* SET DEST SCREEN... */
- channel = ZCTERM;
- fcb = NULL;
- }
- #ifdef DTILDE
- if (*name == '~') {
- dirp = tilde_expand(name);
- if (*dirp) ckstrncpy(name,dirp,CKMAXPATH+1);
- }
- #endif /* DTILDE */
- if (server && !en_cwd) { /* If running as server */
- zstrip(name,&name2); /* and CWD is disabled, */
- if (strcmp(name,name2)) { /* check if pathname was included. */
- tlog(F110,name,"authorization failure",0L);
- debug(F110,"openo CD disabled",name,0);
- return(0);
- } else name = name2;
- }
- if (zopeno(channel,name,zz,fcb) <= 0) { /* Try to open the file */
- o_isopen = 0;
- debug(F110,"openo failed",name,0);
- /* tlog(F110,"Failure to open",name,0L); */
- return(0);
- } else {
- o_isopen = 1;
- debug(F110,"openo ok, name",name,0);
- return(1);
- }
- }
- /* O P E N T -- Open the terminal for output, in place of a file */
- int
- opent(zz) struct zattr *zz; {
- int x;
- ffc = tfc = 0L;
- x = zopeno(ZCTERM,"",zz,NULL);
- debug(F101,"opent zopeno","",x);
- if (x >= 0) {
- o_isopen = 1;
- binary = XYFT_T;
- } else
- return(0);
- return(x);
- }
- /* O P E N X -- Open nothing (incoming file to be accepted but ignored) */
- int
- ckopenx(zz) struct zattr *zz; {
- ffc = tfc = 0L; /* Reset counters */
- o_isopen = 1;
- debug(F101,"ckopenx fsize","",fsize);
- xxscreen(SCR_FS,0,fsize,""); /* Let screen display know the size */
- return(1);
- }
- /* C L S I F -- Close the current input file. */
- int
- clsif() {
- extern int xferstat, success;
- int x = 0;
- fcps(); /* Calculate CPS quickly */
- #ifdef datageneral
- if ((local) && (!quiet)) /* Only do this if local & not quiet */
- if (nfils < 1) /* More files to send ... leave it on! */
- connoi_mt();
- #endif /* datageneral */
- debug(F101,"clsif i_isopen","",i_isopen);
- if (i_isopen) { /* If input file is open... */
- if (memstr) { /* If input was memory string, */
- memstr = 0; /* indicate no more. */
- } else {
- x = zclose(ZIFILE); /* else close input file. */
- }
- #ifdef DEBUG
- if (deblog) {
- debug(F101,"clsif zclose","",x);
- debug(F101,"clsif success","",success);
- debug(F101,"clsif xferstat","",xferstat);
- debug(F101,"clsif fsize","",fsize);
- debug(F101,"clsif ffc","",ffc);
- debug(F101,"clsif cxseen","",cxseen);
- debug(F101,"clsif czseen","",czseen);
- debug(F101,"clsif discard","",czseen);
- }
- #endif /* DEBUG */
- if ((cxseen || czseen) && !epktsent) { /* If interrupted */
- xxscreen(SCR_ST,ST_INT,0l,""); /* say so */
- #ifdef TLOG
- if (tralog && !tlogfmt)
- doxlog(what,sfspec,fsize,binary,1,"Interrupted");
- #endif /* TLOG */
- } else if (discard && !epktsent) { /* If I'm refusing */
- xxscreen(SCR_ST,ST_REFU,0l,refused); /* say why */
- #ifdef TLOG
- if (tralog && !tlogfmt) {
- char buf[128];
- sprintf(buf,"Refused: %s",refused);
- doxlog(what,sfspec,fsize,binary,1,buf);
- }
- #endif /* TLOG */
- } else if (!epktrcvd && !epktsent && !cxseen && !czseen) {
- long zz;
- zz = ffc;
- #ifdef CK_RESEND
- if (sendmode == SM_RESEND || sendmode == SM_PSEND)
- zz += sendstart;
- #endif /* CK_RESEND */
- debug(F101,"clsif fstats","",zz);
- fstats(); /* Update statistics */
- if ( /* Was the whole file sent? */
- #ifdef VMS
- 0 /* Not a reliable check in VMS */
- #else
- #ifdef STRATUS
- 0 /* Probably not for VOS either */
- #else
- zz < fsize
- #ifdef CK_CTRLZ
- && ((eofmethod != XYEOF_Z && !binary) || binary)
- #endif /* CK_CTRLZ */
- #endif /* STRATUS */
- #endif /* VMS */
- ) {
- xxscreen(SCR_ST,ST_INT,0l,"");
- #ifdef TLOG
- if (tralog && !tlogfmt)
- doxlog(what,sfspec,fsize,binary,1,"Incomplete");
- #endif /* TLOG */
- } else {
- xxscreen(SCR_ST,ST_OK,0l,"");
- #ifdef TLOG
- if (tralog && !tlogfmt)
- doxlog(what,sfspec,fsize,binary,0,"");
- #endif /* #ifdef TLOG */
- }
- }
- }
- i_isopen = 0;
- hcflg = 0; /* Reset flags */
- sendstart = 0L; /* Don't do this again! */
- #ifdef COMMENT
- /*
- This prevents a subsequent call to clsof() from deleting the file
- when given the discard flag.
- */
- *filnam = ' '; /* and current file name */
- #endif /* COMMENT */
- return(x);
- }
- /* C L S O F -- Close an output file. */
- /* Call with disp != 0 if file is to be discarded. */
- /* Returns -1 upon failure to close, 0 or greater on success. */
- int
- clsof(disp) int disp; {
- int x = 0;
- extern int success;
- fcps(); /* Calculate CPS quickly */
- debug(F101,"clsof disp","",disp);
- debug(F101,"clsof cxseen","",cxseen);
- debug(F101,"clsof success","",success);
- debug(F101,"clsof o_isopen","",o_isopen);
- if (fncsav != -1) { /* Saved file collision action... */
- fncact = fncsav; /* Restore it. */
- fncsav = -1; /* Unsave it. */
- }
- #ifdef datageneral
- if ((local) && (!quiet)) /* Only do this if local & not quiet */
- connoi_mt();
- #endif /* datageneral */
- if (o_isopen && !calibrate) {
- if ((x = zclose(ZOFILE)) < 0) { /* Try to close the file */
- tlog(F100,"Failure to close",filnam,0L);
- xxscreen(SCR_ST,ST_ERR,0l,"Can't close file");
- #ifdef TLOG
- if (tralog && !tlogfmt)
- doxlog(what,rfspec,fsize,binary,1,"Can't close file");
- #endif /* TLOG */
- } else if (disp) { /* Interrupted or refused */
- if (keep == 0 || /* If not keeping incomplete files */
- (keep == SET_AUTO && binary == XYFT_T)
- ) {
- if (*filnam && (what & W_RECV)) /* AND we're receiving */
- zdelet(filnam); /* ONLY THEN, delete it */
- if (what != W_NOTHING && what != W_INIT) {
- debug(F100,"clsof incomplete discarded","",0);
- tlog(F100," incomplete: discarded","",0L);
- if (!epktrcvd && !epktsent) {
- xxscreen(SCR_ST,ST_DISC,0l,"");
- #ifdef TLOG
- if (tralog && !tlogfmt)
- doxlog(what,rfspec,fsize,binary,1,"Discarded");
- #endif /* TLOG */
- }
- }
- } else { /* Keep incomplete copy */
- debug(F100,"clsof fstats 1","",0);
- fstats();
- if (!discard) { /* Unless discarding for other reason... */
- if (what != W_NOTHING && what != W_INIT) {
- debug(F100,"closf incomplete kept","",0);
- tlog(F100," incomplete: kept","",0L);
- }
- }
- if (what != W_NOTHING && what != W_INIT)
- if (!epktrcvd && !epktsent) {
- xxscreen(SCR_ST,ST_INC,0l,"");
- #ifdef TLOG
- if (tralog && !tlogfmt)
- doxlog(what,rfspec,fsize,binary,1,"Incomplete");
- #endif /* TLOG */
- }
- }
- }
- }
- if (o_isopen && x > -1 && !disp) {
- debug(F100,"clsof fstats 2","",0);
- fstats();
- if (!epktrcvd && !epktsent && !cxseen && !czseen) {
- xxscreen(SCR_ST,ST_OK,0L,"");
- #ifdef TLOG
- if (tralog && !tlogfmt)
- doxlog(what,rfspec,fsize,binary,0,"");
- #endif /* TLOG */
- }
- }
- rs_len = 0;
- o_isopen = 0; /* The file is not open any more. */
- cxseen = 0; /* Reset per-file interruption flag */
- return(x); /* Send back zclose() return code. */
- }
- #ifdef SUNOS4S5
- tolower(c) char c; { return((c)-'A'+'a'); }
- toupper(c) char c; { return((c)-'a'+'A'); }
- #endif /* SUNOS4S5 */
- #endif /* NOXFER */