1 | /* C K C F N 3 -- Packet buffer management for C-Kermit */ |
---|
2 | |
---|
3 | /* (plus assorted functions tacked on at the end) */ |
---|
4 | |
---|
5 | /* |
---|
6 | Author: Frank da Cruz <fdc@columbia.edu>, |
---|
7 | Columbia University Academic Information Systems, New York City. |
---|
8 | |
---|
9 | Copyright (C) 1985, 2002, |
---|
10 | Trustees of Columbia University in the City of New York. |
---|
11 | All rights reserved. See the C-Kermit COPYING.TXT file or the |
---|
12 | copyright text in the ckcmai.c module for disclaimer and permissions. |
---|
13 | */ |
---|
14 | /* |
---|
15 | Note -- if you change this file, please amend the version number and date at |
---|
16 | the top of ckcfns.c accordingly. |
---|
17 | */ |
---|
18 | |
---|
19 | #include "ckcsym.h" |
---|
20 | #include "ckcdeb.h" |
---|
21 | #include "ckcasc.h" |
---|
22 | #include "ckcker.h" |
---|
23 | #include "ckcxla.h" |
---|
24 | |
---|
25 | /* C K M K D I R -- Create a directory */ |
---|
26 | /* |
---|
27 | Call with: |
---|
28 | int fc = 0 to create, nonzero to remove, a directory. |
---|
29 | char * s = pointer to name of directory to create or remove. |
---|
30 | char ** r = address of pointer to return name or message. |
---|
31 | int m = 1 to print error messages, 0 to be silent. |
---|
32 | int cvt = 1 means convert s from standard format to local format; |
---|
33 | 0 means use s as is. |
---|
34 | Returns: |
---|
35 | 0 on success (directory was created or removed). |
---|
36 | -1 when attempt to create the directory failed. |
---|
37 | -2 on internal error (e.g. no code for creating directories). |
---|
38 | On success, the name is pointed to by p. |
---|
39 | On failure, the reason is pointed to by p. |
---|
40 | */ |
---|
41 | #ifdef CK_MKDIR |
---|
42 | static char ckmkdbuf[CKMAXPATH+1]; |
---|
43 | #else |
---|
44 | #ifdef datageneral |
---|
45 | static char ckmkdbuf[CKMAXPATH+1]; |
---|
46 | #endif /* datageneral */ |
---|
47 | #endif /* CK_MKDIR */ |
---|
48 | |
---|
49 | #ifdef CK_MKDIR |
---|
50 | int |
---|
51 | ckmkdir(fc,s,r,m,cvt) int fc; char * s; char ** r; int m; int cvt; { |
---|
52 | int x, rc = -2; |
---|
53 | char tmpbuf[CKMAXPATH+1]; |
---|
54 | char buf2[CKMAXPATH+1]; |
---|
55 | if (!s) s = ""; |
---|
56 | debug(F110,"ckmkdir 1 fc",s,fc); |
---|
57 | if (!*s) { |
---|
58 | ckmakmsg(ckmkdbuf, |
---|
59 | CKMAXPATH+1, |
---|
60 | (fc == 0) ? "mkdir" : "rmdir", |
---|
61 | ": no name given", |
---|
62 | NULL, |
---|
63 | NULL |
---|
64 | ); |
---|
65 | *r = ckmkdbuf; |
---|
66 | return(-2); |
---|
67 | } |
---|
68 | #ifdef datageneral |
---|
69 | /* Come back and make this nicer later if anybody notices */ |
---|
70 | if (fc == 0) { /* mkdir */ |
---|
71 | rc = createdir(s,0); |
---|
72 | } else { /* rmdir */ |
---|
73 | /* AOS/VS rmdir() is a no-op. */ |
---|
74 | ckmakmsg(tmpbuf,CKMAXPATH+1,"delete ",s,NULL,NULL); |
---|
75 | debug(F110,"ckmkdir 2",tmpbuf,0); |
---|
76 | rc = system(tmpbuf); |
---|
77 | } |
---|
78 | *r = NULL; |
---|
79 | #else /* not datageneral */ |
---|
80 | |
---|
81 | /* First make sure the name has an acceptable directory-name format */ |
---|
82 | |
---|
83 | #ifdef VMS |
---|
84 | { |
---|
85 | char *p = s; |
---|
86 | int lb = 0, rb = 0, sl = 0; |
---|
87 | while (*p) { |
---|
88 | if (*p == '[' || *p == '<') lb++; /* Count brackets */ |
---|
89 | else if (*p == ']' || *p == '>') rb++; |
---|
90 | else if (*p == '/') sl++; /* and slashes */ |
---|
91 | p++; |
---|
92 | } |
---|
93 | if (lb != 1 && rb != 1 && sl == 0 && p > s && *(p-1) != ':') { |
---|
94 | /* Probably just a word - convert to VMS format */ |
---|
95 | ckmakmsg(buf2, |
---|
96 | CKMAXPATH+1, |
---|
97 | "[", |
---|
98 | (*s == '.') ? "" : ".", |
---|
99 | s, |
---|
100 | "]" |
---|
101 | ); |
---|
102 | s = buf2; |
---|
103 | } else if (lb == 0 && rb == 0 && sl != 0 && p > s && *(p-1) != ':') { |
---|
104 | int flag = 0; |
---|
105 | /* Seems to be in UNIX format */ |
---|
106 | x = strlen(s); |
---|
107 | if (x > 0 && s[x-1] != '/') |
---|
108 | flag = 1; |
---|
109 | ckmakmsg(buf2,CKMAXPATH+1,s,flag ? "/" : "",NULL,NULL); |
---|
110 | s = buf2; |
---|
111 | } |
---|
112 | if (s == buf2) { |
---|
113 | ckstrncpy(tmpbuf,s,CKMAXPATH+1); |
---|
114 | s = tmpbuf; |
---|
115 | } |
---|
116 | debug(F110,"ckmkdir 2+VMS",s,0); |
---|
117 | } |
---|
118 | #else |
---|
119 | #ifdef UNIXOROSK |
---|
120 | #ifdef DTILDE |
---|
121 | s = tilde_expand(s); |
---|
122 | #endif /* DTILDE */ |
---|
123 | ckstrncpy(tmpbuf,s,CKMAXPATH+1); |
---|
124 | s = tmpbuf; |
---|
125 | x = strlen(s); |
---|
126 | if (x > 0 && s[x-1] != '/') { /* Must end in "/" for zmkdir() */ |
---|
127 | s[x] = '/'; |
---|
128 | s[x+1] = NUL; |
---|
129 | debug(F110,"ckmkdir 2+UNIXOROSK",s,0); |
---|
130 | } |
---|
131 | #else /* UNIXOROSK */ |
---|
132 | #ifdef OS2 |
---|
133 | ckstrncpy(tmpbuf,s,CKMAXPATH+1); |
---|
134 | s = tmpbuf; |
---|
135 | x = strlen(s); |
---|
136 | if (fc == 0 && x > 0 && s[x-1] != '/') { /* Must end in "/" for zmkdir() */ |
---|
137 | s[x] = '/'; |
---|
138 | s[x+1] = NUL; |
---|
139 | debug(F110,"ckmkdir 2+OS2",s,0); |
---|
140 | } |
---|
141 | #endif /* OS2 */ |
---|
142 | #endif /* UNIXOROSK */ |
---|
143 | #endif /* VMS */ |
---|
144 | #ifdef NZLTOR |
---|
145 | /* Server is calling us, so convert to local format if necessary */ |
---|
146 | if (cvt) { |
---|
147 | nzrtol(s,(char *)buf2,1,PATH_ABS,CKMAXPATH); |
---|
148 | s = buf2; |
---|
149 | debug(F110,"ckmkdir 3",s,0); |
---|
150 | } |
---|
151 | #endif /* NZLTOR */ |
---|
152 | debug(F110,"ckmkdir 4",s,0); |
---|
153 | if (fc == 0) { /* Making */ |
---|
154 | #ifdef CK_MKDIR |
---|
155 | rc = zmkdir(s); |
---|
156 | #else |
---|
157 | #ifdef NT |
---|
158 | rc = _mkdir(s); |
---|
159 | #else |
---|
160 | rc = mkdir(s,0777); |
---|
161 | #endif /* NT */ |
---|
162 | #endif /* CK_MKDIR */ |
---|
163 | } else { /* Removing */ |
---|
164 | #ifdef ZRMDIR |
---|
165 | rc = zrmdir(s); |
---|
166 | #else |
---|
167 | #ifdef NT |
---|
168 | rc = _rmdir(s); |
---|
169 | #else |
---|
170 | #ifdef OSK |
---|
171 | rc = -2; |
---|
172 | #else |
---|
173 | rc = rmdir(s); |
---|
174 | #endif /* OSK */ |
---|
175 | #endif /* NT */ |
---|
176 | #endif /* ZRMDIR */ |
---|
177 | } |
---|
178 | #endif /* datageneral */ |
---|
179 | debug(F101,"ckmkdir rc","",rc); |
---|
180 | if (rc == -2) { |
---|
181 | ckmakmsg(ckmkdbuf, |
---|
182 | CKMAXPATH, |
---|
183 | "Directory ", |
---|
184 | (fc == 0) ? "creation" : "removal", |
---|
185 | "not implemented in this version of C-Kermit", |
---|
186 | NULL |
---|
187 | ); |
---|
188 | *r = ckmkdbuf; |
---|
189 | if (m) printf("%s\n",*r); |
---|
190 | } else if (rc < 0) { |
---|
191 | if (m) perror(s); |
---|
192 | ckmakmsg(ckmkdbuf,CKMAXPATH,s,": ",ck_errstr(),NULL); |
---|
193 | *r = ckmkdbuf; |
---|
194 | } else if (fc == 0 && zfnqfp(s,CKMAXPATH,ckmkdbuf)) { |
---|
195 | *r = ckmkdbuf; |
---|
196 | } else if (fc != 0) { |
---|
197 | ckmakmsg(ckmkdbuf,CKMAXPATH,s,": removed",NULL,NULL); |
---|
198 | *r = ckmkdbuf; |
---|
199 | } |
---|
200 | return(rc); |
---|
201 | } |
---|
202 | #endif /* CK_MKDIR */ |
---|
203 | |
---|
204 | #ifndef NOXFER /* Rest of this file... */ |
---|
205 | |
---|
206 | #ifndef NODISPO |
---|
207 | #ifdef pdp11 |
---|
208 | #define NODISPO |
---|
209 | #endif /* pdpd11 */ |
---|
210 | #endif /* NODISPO */ |
---|
211 | |
---|
212 | extern int pipesend; |
---|
213 | #ifdef PIPESEND |
---|
214 | extern char ** sndfilter; |
---|
215 | #endif /* PIPESEND */ |
---|
216 | |
---|
217 | extern int unkcs, wmax, wcur, discard, bctu, bctl, local, fdispla, what, |
---|
218 | sendmode, opnerr, dest, epktrcvd, epktsent, filestatus, eofmethod, dispos; |
---|
219 | extern long sendstart, calibrate, fncnv, fnrpath; |
---|
220 | |
---|
221 | extern char * ofn2; |
---|
222 | extern char * rfspec, * sfspec, * prfspec, * psfspec, * rrfspec, * prrfspec; |
---|
223 | extern char ofn1[]; |
---|
224 | extern int ofn1x; |
---|
225 | extern char * ofperms; |
---|
226 | |
---|
227 | #ifdef VMS |
---|
228 | extern int batch; |
---|
229 | #else |
---|
230 | extern int backgrd; |
---|
231 | #endif /* VMS */ |
---|
232 | |
---|
233 | extern int xflg, remfile, remappd; |
---|
234 | extern CHAR *data; |
---|
235 | extern char filnam[]; |
---|
236 | #ifndef NOFRILLS |
---|
237 | extern int rprintf, rmailf; /* REMOTE MAIL, PRINT */ |
---|
238 | char optbuf[OPTBUFLEN]; /* Options for MAIL or REMOTE PRINT */ |
---|
239 | #endif /* NOFRILLS */ |
---|
240 | extern int wslots; |
---|
241 | extern int fblksiz, frecl, forg, frecfm, fncact, fncsav, fcctrl, lf_opts; |
---|
242 | extern CHAR * srvcmd; |
---|
243 | extern int srvcmdlen; |
---|
244 | |
---|
245 | extern int binary, spsiz; |
---|
246 | extern int pktnum, cxseen, czseen, nfils, stdinf; |
---|
247 | extern int memstr, stdouf, keep, sndsrc, hcflg; |
---|
248 | extern int server, en_cwd, en_mai, en_pri; |
---|
249 | |
---|
250 | /* Attributes in/out enabled flags */ |
---|
251 | |
---|
252 | extern int |
---|
253 | atenci, atenco, atdati, atdato, atleni, atleno, atblki, atblko, |
---|
254 | attypi, attypo, atsidi, atsido, atsysi, atsyso, atdisi, atdiso; |
---|
255 | |
---|
256 | #ifdef CK_PERMS |
---|
257 | extern int atlpri, atlpro, atgpri, atgpro; |
---|
258 | #endif /* CK_PERMS */ |
---|
259 | |
---|
260 | #ifdef STRATUS |
---|
261 | extern int atfrmi, atfrmo, atcrei, atcreo, atacti, atacto; |
---|
262 | #endif /* STRATUS */ |
---|
263 | |
---|
264 | #ifdef datageneral |
---|
265 | extern int quiet; |
---|
266 | #endif /* datageneral */ |
---|
267 | |
---|
268 | extern long fsize, filcnt, ffc, tfc; |
---|
269 | |
---|
270 | #ifndef NOCSETS |
---|
271 | _PROTOTYP (VOID setxlate, (void)); |
---|
272 | extern int tcharset, fcharset; |
---|
273 | extern int ntcsets, xlatype, xfrxla; |
---|
274 | extern struct csinfo tcsinfo[], fcsinfo[]; |
---|
275 | #endif /* NOCSETS */ |
---|
276 | |
---|
277 | /* Variables global to Kermit that are defined in this module */ |
---|
278 | |
---|
279 | #ifdef CKXXCHAR /* DOUBLE / IGNORE char table */ |
---|
280 | int dblflag = 0; |
---|
281 | int ignflag = 0; |
---|
282 | short dblt[256] = { |
---|
283 | 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, |
---|
284 | 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, |
---|
285 | 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, |
---|
286 | 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, |
---|
287 | 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, |
---|
288 | 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, |
---|
289 | 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, |
---|
290 | 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 |
---|
291 | }; |
---|
292 | #endif /* CKXXCHAR */ |
---|
293 | |
---|
294 | int winlo; /* packet number at low window edge */ |
---|
295 | |
---|
296 | int sbufnum; /* number of free buffers */ |
---|
297 | int dum001 = 1234; /* protection... */ |
---|
298 | int sbufuse[MAXWS]; /* buffer in-use flag */ |
---|
299 | int dum003 = 1111; |
---|
300 | int rbufnum; /* number of free buffers */ |
---|
301 | int dum002 = 4321; /* more protection */ |
---|
302 | int rbufuse[MAXWS]; /* buffer in-use flag */ |
---|
303 | int sseqtbl[64]; /* sequence # to buffer # table */ |
---|
304 | int rseqtbl[64]; /* sequence # to buffer # table */ |
---|
305 | int sacktbl[64]; /* sequence # ack table */ |
---|
306 | |
---|
307 | int o_isopen = 0, i_isopen = 0; /* Input & output files are open */ |
---|
308 | |
---|
309 | #ifdef DYNAMIC |
---|
310 | struct pktinfo *s_pkt = NULL; /* array of pktinfo structures */ |
---|
311 | struct pktinfo *r_pkt = NULL; /* array of pktinfo structures */ |
---|
312 | #else |
---|
313 | struct pktinfo s_pkt[MAXWS]; /* array of pktinfo structures */ |
---|
314 | struct pktinfo r_pkt[MAXWS]; /* array of pktinfo structures */ |
---|
315 | #endif /* DYNAMIC */ |
---|
316 | |
---|
317 | #ifdef DEBUG |
---|
318 | char xbuf[200]; /* For debug logging */ |
---|
319 | #endif /* DEBUG */ |
---|
320 | |
---|
321 | #ifdef DYNAMIC |
---|
322 | CHAR *bigsbuf = NULL, *bigrbuf = NULL; |
---|
323 | #else |
---|
324 | char bigsbt[8]; /* Protection (shouldn't need this). */ |
---|
325 | /* BUT DON'T REMOVE IT! */ |
---|
326 | CHAR bigsbuf[SBSIZ + 5]; /* Send-packet buffer area */ |
---|
327 | char bigrbt[8]; /* Safety padding */ |
---|
328 | CHAR bigrbuf[RBSIZ + 5]; /* Receive-packet area */ |
---|
329 | #endif |
---|
330 | int bigsbsiz = SBSIZ; /* Sizes of big send & rcv buffers. */ |
---|
331 | int bigrbsiz = RBSIZ; |
---|
332 | |
---|
333 | #ifdef VMS |
---|
334 | int zchkpath(char *s); |
---|
335 | #endif /* VMS */ |
---|
336 | |
---|
337 | /* FUNCTIONS */ |
---|
338 | |
---|
339 | VOID |
---|
340 | dofast() { |
---|
341 | long maxbufsiz = RBSIZ; /* Configuration parameters */ |
---|
342 | int maxpktsiz = MAXSP; |
---|
343 | extern int spsizf, /* For bug in IRIX Telnet server */ |
---|
344 | rpsiz, urpsiz, spsizr, spmax, wslotr; |
---|
345 | extern struct ck_p ptab[]; |
---|
346 | |
---|
347 | if (maxpktsiz < 40) /* Long packet length */ |
---|
348 | maxpktsiz = 40; |
---|
349 | else if (maxpktsiz > 4000) |
---|
350 | maxpktsiz = 4000; |
---|
351 | wslotr = maxbufsiz / maxpktsiz; |
---|
352 | if (wslotr > MAXWS) /* Window slots */ |
---|
353 | wslotr = MAXWS; |
---|
354 | if (wslotr > 30) |
---|
355 | wslotr = 30; |
---|
356 | else if (wslotr < 1) |
---|
357 | wslotr = 1; |
---|
358 | urpsiz = adjpkl(maxpktsiz,wslotr,maxbufsiz); |
---|
359 | ptab[PROTO_K].rpktlen = urpsiz; |
---|
360 | rpsiz = (urpsiz > 94) ? 94 : urpsiz; /* Max non-long packet length */ |
---|
361 | debug(F111,"dofast","uprsiz",urpsiz); |
---|
362 | #ifdef IRIX |
---|
363 | #ifndef IRIX65 |
---|
364 | /* IRIX Telnet server chops off writes longer than 4K */ |
---|
365 | spsiz = spmax = spsizr = urpsiz; |
---|
366 | debug(F101,"doarg Q IRIX spsiz","",spsiz); |
---|
367 | spsizf = 1; |
---|
368 | #endif /* IRIX65 */ |
---|
369 | #endif /* IRIX */ |
---|
370 | #ifdef CK_SPEED |
---|
371 | setprefix(PX_CAU); /* Cautious unprefixing */ |
---|
372 | #endif /* CK_SPEED */ |
---|
373 | } |
---|
374 | |
---|
375 | |
---|
376 | /* For sanity, use "i" for buffer slots, "n" for packet numbers. */ |
---|
377 | |
---|
378 | /* I N I B U F S */ |
---|
379 | |
---|
380 | /* |
---|
381 | Allocates the big send and receive buffers. |
---|
382 | Call with size for big send buffer (s) and receive buffer (r). |
---|
383 | These sizes can be different. |
---|
384 | Attempts to allocate buffers of the requested size, but if it can't, |
---|
385 | it will allocate smaller ones. |
---|
386 | Sets global variables bigsbsiz and bigrbsiz to the actual sizes, |
---|
387 | and bigsbuf and bigrbuf pointing to the actual buffers. |
---|
388 | Designed to be called more than once. |
---|
389 | Returns 0 on success, -1 on failure. |
---|
390 | */ |
---|
391 | |
---|
392 | CHAR *bigbufp = NULL; |
---|
393 | |
---|
394 | int |
---|
395 | inibufs(s,r) int s, r; { |
---|
396 | #ifdef DYNAMIC |
---|
397 | unsigned |
---|
398 | int size; |
---|
399 | #ifdef OS2 |
---|
400 | unsigned /* Don't you wish everybody had unsigned long... */ |
---|
401 | #endif /* OS2 */ |
---|
402 | long z; |
---|
403 | int x; |
---|
404 | |
---|
405 | debug(F101,"inibufs s","",s); |
---|
406 | debug(F101,"inibufs r","",r); |
---|
407 | |
---|
408 | if (s < 80 || r < 80) return(-1); /* Validate arguments. */ |
---|
409 | |
---|
410 | if (!s_pkt) { /* Allocate packet info structures */ |
---|
411 | if (!(s_pkt = (struct pktinfo *) malloc(sizeof(struct pktinfo)*MAXWS))) |
---|
412 | fatal("ini_pkts: no memory for s_pkt"); |
---|
413 | } |
---|
414 | for (x = 0; x < MAXWS; x++) |
---|
415 | s_pkt[x].pk_adr = NULL; /* Initialize addresses */ |
---|
416 | |
---|
417 | if (!r_pkt) { |
---|
418 | if (!(r_pkt = (struct pktinfo *) malloc(sizeof(struct pktinfo)*MAXWS))) |
---|
419 | fatal("ini_pkts: no memory for s_pkt"); |
---|
420 | } |
---|
421 | for (x = 0; x < MAXWS; x++) |
---|
422 | r_pkt[x].pk_adr = NULL; /* Initialize addresses */ |
---|
423 | |
---|
424 | if (!srvcmd) { /* Allocate srvcmd buffer */ |
---|
425 | srvcmd = (CHAR *) malloc(r + 100); |
---|
426 | if (!srvcmd) return(-1); |
---|
427 | srvcmdlen = r + 99; |
---|
428 | *srvcmd = NUL; |
---|
429 | } |
---|
430 | if (bigbufp) { /* Free previous buffers, if any. */ |
---|
431 | free(bigbufp); |
---|
432 | bigbufp = NULL; |
---|
433 | } |
---|
434 | size = s + r + 40; /* Combined requested size + padding */ |
---|
435 | z = (unsigned) s + (unsigned) r + 40; |
---|
436 | debug(F101,"inibufs size 1","",size); |
---|
437 | debug(F101,"inibufs size z","",z); |
---|
438 | if ((long) size != z) { |
---|
439 | debug(F100,"inibufs overflow","",0); |
---|
440 | size = 65535; |
---|
441 | } |
---|
442 | |
---|
443 | /* Try to get the space. If malloc fails, try to get a little less. */ |
---|
444 | /* (Obviously, this algorithm can be refined.) */ |
---|
445 | |
---|
446 | while (!(bigbufp = (CHAR *) malloc(size))) { |
---|
447 | debug(F101,"inibufs bigbuf malloc failed","",size); |
---|
448 | size = (size * 2) / 3; /* Failed, cut size by 1/3. */ |
---|
449 | if (size < 200) /* Try again until too small. */ |
---|
450 | return(-1); |
---|
451 | } |
---|
452 | debug(F101,"inibufs size 2","",size); /* OK, we got some space. */ |
---|
453 | |
---|
454 | /* |
---|
455 | Now divide the allocated space between the send and receive buffers in the |
---|
456 | requested proportion. The natural formula would be (s / (s + r)) * size |
---|
457 | (for the send buffer), but that doesn't work with integer arithmetic and we |
---|
458 | can't use floating point because some machines don't have it. This can be |
---|
459 | rearranged as (s * size) / (s + r). But (s * size) can be VERY large, too |
---|
460 | large for 32 bits. So let's do it this way. This arithmetic works for |
---|
461 | buffer sizes up to about 5,000,000. |
---|
462 | */ |
---|
463 | #define FACTOR 20L |
---|
464 | z = ( (long) s * FACTOR ) / ( (long) s + (long) r ); |
---|
465 | x = ( z * ( (long) size / FACTOR ) ); |
---|
466 | if (x < 0) return(-1); /* Catch overflow */ |
---|
467 | |
---|
468 | bigsbsiz = x - 5; /* Size of send buffer */ |
---|
469 | bigsbuf = bigbufp; /* Address of send buffer */ |
---|
470 | debug(F101,"inibufs bigsbsiz","",bigsbsiz); |
---|
471 | |
---|
472 | bigrbsiz = size - x - 5; /* Size of receive buffer */ |
---|
473 | bigrbuf = bigbufp + x; /* Addresss of receive buffer */ |
---|
474 | debug(F101,"inibufs bigrbsiz","",bigrbsiz); |
---|
475 | |
---|
476 | return(0); /* Success */ |
---|
477 | #else /* No dynamic allocation */ |
---|
478 | bigsbsiz = SBSIZ; /* Just use the symbols */ |
---|
479 | bigrbsiz = RBSIZ; /* ... */ |
---|
480 | return(0); /* Success. */ |
---|
481 | #endif /* DYNAMIC */ |
---|
482 | } |
---|
483 | |
---|
484 | |
---|
485 | /* M A K E B U F -- Makes and clears a new buffers. */ |
---|
486 | |
---|
487 | /* Call with: */ |
---|
488 | /* slots: number of buffer slots to make, 1 to 32 */ |
---|
489 | /* bufsiz: size of the big buffer */ |
---|
490 | /* buf: address of the big buffer */ |
---|
491 | /* xx: pointer to array of pktinfo structures for these buffers */ |
---|
492 | |
---|
493 | /* Subdivides the big buffer into "slots" buffers. */ |
---|
494 | |
---|
495 | /* Returns: */ |
---|
496 | /* -1 if too many or too few slots requested, */ |
---|
497 | /* -2 if slots would be too small. */ |
---|
498 | /* n (positive) on success = size of one buffer. */ |
---|
499 | /* with pktinfo structure initialized for this set of buffers. */ |
---|
500 | |
---|
501 | int |
---|
502 | makebuf(slots,bufsiz,buf,xx) |
---|
503 | /* makebuf */ int slots, bufsiz; CHAR buf[]; struct pktinfo *xx; { |
---|
504 | |
---|
505 | CHAR *a; |
---|
506 | int i, size; |
---|
507 | |
---|
508 | debug(F101,"makebuf","",slots); |
---|
509 | debug(F101,"makebuf bufsiz","",bufsiz); |
---|
510 | debug(F101,"makebuf MAXWS","",MAXWS); |
---|
511 | |
---|
512 | if (slots > MAXWS || slots < 1) return(-1); |
---|
513 | if (bufsiz < slots * 10 ) return(-2); |
---|
514 | |
---|
515 | size = bufsiz / slots; /* Divide up the big buffer. */ |
---|
516 | a = buf; /* Address of first piece. */ |
---|
517 | |
---|
518 | for (i = 0; i < slots; i++) { |
---|
519 | struct pktinfo *x = &xx[i]; |
---|
520 | x->bf_adr = a; /* Address of this buffer */ |
---|
521 | x->bf_len = size; /* Length of this buffer */ |
---|
522 | x->pk_len = 0; /* Length of data field */ |
---|
523 | x->pk_typ = ' '; /* packet type */ |
---|
524 | x->pk_seq = -1; /* packet sequence number */ |
---|
525 | x->pk_rtr = 0; /* retransmissions */ |
---|
526 | *a = '\0'; /* Clear the buffer */ |
---|
527 | a += size; /* Position to next buffer slot */ |
---|
528 | } |
---|
529 | return(size); |
---|
530 | } |
---|
531 | |
---|
532 | /* M A K S B U F -- Makes the send-packet buffer */ |
---|
533 | |
---|
534 | int |
---|
535 | mksbuf(slots) int slots; { |
---|
536 | int i, x; |
---|
537 | sbufnum = 0; |
---|
538 | if ((x = makebuf(slots,bigsbsiz,bigsbuf,s_pkt)) < 0) { |
---|
539 | debug(F101,"mksbuf makebuf return","",x); |
---|
540 | return(x); |
---|
541 | } |
---|
542 | debug(F101,"mksbuf makebuf return","",x); |
---|
543 | for (i = 0; i < 64; i++) { /* Initialize sequence-number- */ |
---|
544 | sseqtbl[i] = -1; /* to-buffer-number table. */ |
---|
545 | sacktbl[i] = 0; |
---|
546 | } |
---|
547 | for (i = 0; i < MAXWS; i++) |
---|
548 | sbufuse[i] = 0; /* Mark each buffer as free */ |
---|
549 | sbufnum = slots; |
---|
550 | wcur = 0; |
---|
551 | return(x); |
---|
552 | } |
---|
553 | |
---|
554 | /* M A K R B U F -- Makes the receive-packet buffer */ |
---|
555 | |
---|
556 | int |
---|
557 | mkrbuf(slots) int slots; { |
---|
558 | int i, x; |
---|
559 | rbufnum = 0; |
---|
560 | if ((x = makebuf(slots,bigrbsiz,bigrbuf,r_pkt)) < 0) { |
---|
561 | debug(F101,"mkrbuf makebuf return","",x); |
---|
562 | return(x); |
---|
563 | } |
---|
564 | debug(F101,"mkrbuf makebuf return","",x); |
---|
565 | for (i = 0; i < 64; i++) { /* Initialize sequence-number- */ |
---|
566 | rseqtbl[i] = -1; /* to-buffer-number table. */ |
---|
567 | } |
---|
568 | for (i = 0; i < MAXWS; i++) |
---|
569 | rbufuse[i] = 0; /* Mark each buffer as free */ |
---|
570 | rbufnum = slots; |
---|
571 | wcur = 0; |
---|
572 | return(x); |
---|
573 | } |
---|
574 | |
---|
575 | /* W I N D O W -- Resize the window to n */ |
---|
576 | |
---|
577 | int |
---|
578 | window(n) int n; { |
---|
579 | debug(F101,"window","",n); |
---|
580 | if (n < 1 || n > MAXWS) return(-1); |
---|
581 | if (mksbuf(n) < 0) return(-1); |
---|
582 | if (mkrbuf(n) < 0) return(-1); |
---|
583 | wslots = n; |
---|
584 | #ifdef DEBUG |
---|
585 | if (deblog) dumpsbuf(); |
---|
586 | if (deblog) dumprbuf(); |
---|
587 | #endif /* DEBUG */ |
---|
588 | return(0); |
---|
589 | } |
---|
590 | |
---|
591 | /* G E T S B U F -- Allocate a send-buffer. */ |
---|
592 | |
---|
593 | /* Call with packet sequence number to allocate buffer for. */ |
---|
594 | /* Returns: */ |
---|
595 | /* -4 if argument is invalid (negative, or greater than 63) */ |
---|
596 | /* -3 if buffers were thought to be available but really weren't (bug!) */ |
---|
597 | /* -2 if the number of free buffers is negative (bug!) */ |
---|
598 | /* -1 if no free buffers. */ |
---|
599 | /* 0 or positive, packet sequence number, with buffer allocated for it. */ |
---|
600 | |
---|
601 | int |
---|
602 | getsbuf(n) int n; { /* Allocate a send-buffer */ |
---|
603 | int i; |
---|
604 | CHAR * p = NULL; |
---|
605 | if (n < 0 || n > 63) { |
---|
606 | debug(F101,"getsbuf bad arg","",n); |
---|
607 | return(-4); /* Bad argument */ |
---|
608 | } |
---|
609 | debug(F101,"getsbuf packet","",n); |
---|
610 | /* debug(F101,"getsbuf, sbufnum","",sbufnum); */ |
---|
611 | if (sbufnum == 0) return(-1); /* No free buffers. */ |
---|
612 | if (sbufnum < 0) return(-2); /* Shouldn't happen. */ |
---|
613 | for (i = 0; i < wslots; i++) /* Find the first one not in use. */ |
---|
614 | if (sbufuse[i] == 0) { /* Got one? */ |
---|
615 | sbufuse[i] = 1; /* Mark it as in use. */ |
---|
616 | sbufnum--; /* One less free buffer. */ |
---|
617 | *s_pkt[i].bf_adr = '\0'; /* Zero the buffer data field */ |
---|
618 | s_pkt[i].pk_seq = n; /* Put in the sequence number */ |
---|
619 | sseqtbl[n] = i; /* Back pointer from sequence number */ |
---|
620 | sacktbl[n] = 0; /* ACK flag */ |
---|
621 | s_pkt[i].pk_len = 0; /* Data field length now zero. */ |
---|
622 | s_pkt[i].pk_typ = ' '; /* Blank the packet type too. */ |
---|
623 | s_pkt[i].pk_rtr = 0; /* Zero the retransmission count */ |
---|
624 | p = s_pkt[i].bf_adr + 7; /* Set global "data" address. */ |
---|
625 | debug(F101,"getsbuf p","",0); |
---|
626 | data = p; |
---|
627 | if (!data) { |
---|
628 | debug(F100,"getsbuf data == NULL","",0); |
---|
629 | return(-3); |
---|
630 | } |
---|
631 | if ((what & (W_SEND|W_REMO)) && (++wcur > wmax)) |
---|
632 | wmax = wcur; /* For statistics. */ |
---|
633 | /* debug(F101,"getsbuf wcur","",wcur); */ |
---|
634 | return(n); /* Return its index. */ |
---|
635 | } |
---|
636 | sbufnum = 0; /* Didn't find one. */ |
---|
637 | return(-3); /* Shouldn't happen! */ |
---|
638 | } |
---|
639 | |
---|
640 | int |
---|
641 | getrbuf() { /* Allocate a receive buffer */ |
---|
642 | int i; |
---|
643 | #ifdef COMMENT |
---|
644 | /* This code is pretty stable by now... */ |
---|
645 | /* Looks like we might need this after all */ |
---|
646 | debug(F101,"getrbuf rbufnum","",rbufnum); |
---|
647 | debug(F101,"getrbuf wslots","",wslots); |
---|
648 | debug(F101,"getrbuf dum002","",dum002); |
---|
649 | debug(F101,"getrbuf dum003","",dum003); |
---|
650 | #endif /* COMMENT */ |
---|
651 | if (rbufnum == 0) return(-1); /* No free buffers. */ |
---|
652 | if (rbufnum < 0) return(-2); /* Shouldn't happen. */ |
---|
653 | for (i = 0; i < wslots; i++) /* Find the first one not in use. */ |
---|
654 | if (rbufuse[i] == 0) { /* Got one? */ |
---|
655 | rbufuse[i] = 1; /* Mark it as in use. */ |
---|
656 | *r_pkt[i].bf_adr = '\0'; /* Zero the buffer data field */ |
---|
657 | rbufnum--; /* One less free buffer. */ |
---|
658 | debug(F101,"getrbuf new rbufnum","",rbufnum); |
---|
659 | if ((what & W_RECV) && (++wcur > wmax)) |
---|
660 | wmax = wcur; /* For statistics. */ |
---|
661 | /* debug(F101,"getrbuf wcur","",wcur); */ |
---|
662 | return(i); /* Return its index. */ |
---|
663 | } |
---|
664 | /* debug(F101,"getrbuf foulup","",i); */ |
---|
665 | rbufnum = 0; /* Didn't find one. */ |
---|
666 | return(-3); /* Shouldn't happen! */ |
---|
667 | } |
---|
668 | |
---|
669 | /* F R E E S B U F -- Free send-buffer for given packet sequence number */ |
---|
670 | |
---|
671 | /* Returns: */ |
---|
672 | /* 1 upon success */ |
---|
673 | /* -1 if specified buffer does not exist */ |
---|
674 | |
---|
675 | int |
---|
676 | freesbuf(n) int n; { /* Release send-buffer for packet n. */ |
---|
677 | int i; |
---|
678 | |
---|
679 | debug(F101,"freesbuf","",n); |
---|
680 | if (n < 0 || n > 63) /* No such packet. */ |
---|
681 | return(-1); |
---|
682 | i = sseqtbl[n]; /* Get the window slot number. */ |
---|
683 | if (i > -1 && i <= wslots) { |
---|
684 | sseqtbl[n] = -1; /* If valid, remove from seqtbl */ |
---|
685 | sbufnum++; /* and count one more free buffer */ |
---|
686 | sbufuse[i] = 0; /* and mark it as free, */ |
---|
687 | if (what & (W_SEND|W_REMO)) /* decrement active slots */ |
---|
688 | wcur--; /* for statistics and display. */ |
---|
689 | } else { |
---|
690 | debug(F101," sseqtbl[n]","",sseqtbl[n]); |
---|
691 | return(-1); |
---|
692 | } |
---|
693 | |
---|
694 | /* The following is done only so dumped buffers will look right. */ |
---|
695 | |
---|
696 | if (1) { |
---|
697 | *s_pkt[i].bf_adr = '\0'; /* Zero the buffer data field */ |
---|
698 | s_pkt[i].pk_seq = -1; /* Invalidate the sequence number */ |
---|
699 | s_pkt[i].pk_len = 0; /* Data field length now zero. */ |
---|
700 | s_pkt[i].pk_typ = ' '; /* Blank the packet type too. */ |
---|
701 | s_pkt[i].pk_rtr = 0; /* And the retries field. */ |
---|
702 | } |
---|
703 | return(1); |
---|
704 | } |
---|
705 | |
---|
706 | int |
---|
707 | freerbuf(i) int i; { /* Release receive-buffer slot "i". */ |
---|
708 | int n; |
---|
709 | |
---|
710 | /* NOTE !! Currently, this function frees the indicated buffer, but */ |
---|
711 | /* does NOT erase the data. The program counts on this. Will find a */ |
---|
712 | /* better way later.... */ |
---|
713 | |
---|
714 | /* debug(F101,"freerbuf, slot","",i); */ |
---|
715 | if (i < 0 || i >= wslots) { /* No such slot. */ |
---|
716 | debug(F101,"freerbuf no such slot","",i); |
---|
717 | return(-1); |
---|
718 | } |
---|
719 | n = r_pkt[i].pk_seq; /* Get the packet sequence number */ |
---|
720 | debug(F101,"freerbuf packet","",n); |
---|
721 | if (n > -1 && n < 64) /* If valid, remove from seqtbl */ |
---|
722 | rseqtbl[n] = -1; |
---|
723 | if (rbufuse[i] != 0) { /* If really allocated, */ |
---|
724 | rbufuse[i] = 0; /* mark it as free, */ |
---|
725 | rbufnum++; /* and count one more free buffer. */ |
---|
726 | if (what & W_RECV) /* Keep track of current slots */ |
---|
727 | wcur--; /* for statistics and display */ |
---|
728 | debug(F101,"freerbuf rbufnum","",rbufnum); |
---|
729 | } |
---|
730 | |
---|
731 | /* The following is done only so dumped buffers will look right. */ |
---|
732 | |
---|
733 | if (1) { |
---|
734 | /* *r_pkt[i].bf_adr = '\0'; */ /* Zero the buffer data field */ |
---|
735 | r_pkt[i].pk_seq = -1; /* And from packet list */ |
---|
736 | r_pkt[i].pk_len = 0; /* Data field length now zero. */ |
---|
737 | r_pkt[i].pk_typ = ' '; /* Blank the packet type too. */ |
---|
738 | r_pkt[i].pk_rtr = 0; /* And the retries field. */ |
---|
739 | } |
---|
740 | return(1); |
---|
741 | } |
---|
742 | |
---|
743 | /* This is like freerbuf, except it's called with a packet sequence number */ |
---|
744 | /* rather than a packet buffer index. */ |
---|
745 | |
---|
746 | VOID |
---|
747 | freerpkt(seq) int seq; { |
---|
748 | int k; |
---|
749 | debug(F101,"freerpkt seq","",seq); |
---|
750 | k = rseqtbl[seq]; |
---|
751 | /* debug(F101,"freerpkt k","",k); */ |
---|
752 | if (k > -1) { |
---|
753 | k = freerbuf(k); |
---|
754 | /* debug(F101,"freerpkt freerbuf","",k); */ |
---|
755 | } |
---|
756 | } |
---|
757 | |
---|
758 | |
---|
759 | /* C H K W I N -- Check if packet n is in window. */ |
---|
760 | |
---|
761 | /* Returns: */ |
---|
762 | /* 0 if it is in the current window, */ |
---|
763 | /* +1 if it would have been in previous window (e.g. if ack was lost), */ |
---|
764 | /* -1 if it is outside any window (protocol error), */ |
---|
765 | /* -2 if either of the argument packet numbers is out of range. */ |
---|
766 | |
---|
767 | /* Call with packet number to check (n), lowest packet number in window */ |
---|
768 | /* (bottom), and number of slots in window (slots). */ |
---|
769 | |
---|
770 | int |
---|
771 | chkwin(n,bottom,slots) int n, bottom, slots; { |
---|
772 | int top, prev; |
---|
773 | |
---|
774 | debug(F101,"chkwin packet","",n); |
---|
775 | debug(F101,"chkwin winlo","",bottom); |
---|
776 | debug(F101,"chkwin slots","",slots); |
---|
777 | |
---|
778 | /* First do the easy and common cases, where the windows are not split. */ |
---|
779 | |
---|
780 | if (n < 0 || n > 63 || bottom < 0 || bottom > 63) |
---|
781 | return(-2); |
---|
782 | |
---|
783 | if (n == bottom) return(0); /* In a perfect world... */ |
---|
784 | |
---|
785 | top = bottom + slots; /* Calculate window top. */ |
---|
786 | if (top < 64 && n < top && n >= bottom) |
---|
787 | return(0); /* In current window. */ |
---|
788 | |
---|
789 | prev = bottom - slots; /* Bottom of previous window. */ |
---|
790 | if (prev > -1 && n < bottom && n > prev) |
---|
791 | return(1); /* In previous. */ |
---|
792 | |
---|
793 | /* Now consider the case where the current window is split. */ |
---|
794 | |
---|
795 | if (top > 63) { /* Wraparound... */ |
---|
796 | top -= 64; /* Get modulo-64 sequence number */ |
---|
797 | if (n < top || n >= bottom) { |
---|
798 | return(0); /* In current window. */ |
---|
799 | } else { /* Not in current window. */ |
---|
800 | if (n < bottom && n >= prev) /* Previous window can't be split. */ |
---|
801 | return(1); /* In previous window. */ |
---|
802 | else |
---|
803 | return(-1); /* Not in previous window. */ |
---|
804 | } |
---|
805 | } |
---|
806 | |
---|
807 | /* Now the case where current window not split, but previous window is. */ |
---|
808 | |
---|
809 | if (prev < 0) { /* Is previous window split? */ |
---|
810 | prev += 64; /* Yes. */ |
---|
811 | if (n < bottom || n >= prev) |
---|
812 | return(1); /* In previous window. */ |
---|
813 | } else { /* Previous window not split. */ |
---|
814 | if (n < bottom && n >= prev) |
---|
815 | return(1); /* In previous window. */ |
---|
816 | } |
---|
817 | |
---|
818 | /* It's not in the current window, and not in the previous window... */ |
---|
819 | |
---|
820 | return(-1); /* So it's not in any window. */ |
---|
821 | } |
---|
822 | |
---|
823 | int |
---|
824 | dumpsbuf() { /* Dump send-buffers */ |
---|
825 | #ifdef DEBUG |
---|
826 | int j, x, z; /* to debug log. */ |
---|
827 | |
---|
828 | if (! deblog) return(0); |
---|
829 | x = zsoutl(ZDFILE,"SEND BUFFERS:"); |
---|
830 | if (x < 0) { |
---|
831 | deblog = 0; |
---|
832 | return(0); |
---|
833 | } |
---|
834 | x=zsoutl(ZDFILE,"buffer inuse address length data type seq flag retries"); |
---|
835 | if (x < 0) { |
---|
836 | deblog = 0; |
---|
837 | return(0); |
---|
838 | } |
---|
839 | for (j = 0; j < wslots; j++) { |
---|
840 | if (!sbufuse[j]) |
---|
841 | continue; |
---|
842 | z = ((unsigned long)(s_pkt[j].bf_adr)) & 0xffff; |
---|
843 | |
---|
844 | sprintf(xbuf, /* safe (200) */ |
---|
845 | "%4d%6d%10d%5d%6d%4c%5d%6d\n", |
---|
846 | j, |
---|
847 | sbufuse[j], |
---|
848 | /* Avoid warnings when addresses are bigger than ints */ |
---|
849 | z, |
---|
850 | s_pkt[j].bf_len, |
---|
851 | s_pkt[j].pk_len, |
---|
852 | s_pkt[j].pk_typ, |
---|
853 | s_pkt[j].pk_seq, |
---|
854 | s_pkt[j].pk_rtr |
---|
855 | ); |
---|
856 | if (zsout(ZDFILE,xbuf) < 0) { |
---|
857 | deblog = 0; |
---|
858 | return(0); |
---|
859 | } |
---|
860 | if (s_pkt[j].pk_adr) { |
---|
861 | x = (int)strlen((char *) s_pkt[j].pk_adr); |
---|
862 | if (x) |
---|
863 | sprintf(xbuf, /* safe (checked) */ |
---|
864 | "[%.72s%s]\n",s_pkt[j].pk_adr, x > 72 ? "..." : ""); |
---|
865 | else |
---|
866 | sprintf(xbuf,"[(empty string)]\n"); /* safe (200) */ |
---|
867 | } else { |
---|
868 | sprintf(xbuf,"[(null pointer)]\n"); /* safe (200) */ |
---|
869 | } |
---|
870 | if (zsout(ZDFILE,xbuf) < 0) { |
---|
871 | deblog = 0; |
---|
872 | return(0); |
---|
873 | } |
---|
874 | } |
---|
875 | sprintf(xbuf,"free: %d, winlo: %d\n", sbufnum, winlo); /* safe (200) */ |
---|
876 | if (zsout(ZDFILE,xbuf) < 0) { |
---|
877 | deblog = 0; |
---|
878 | return(0); |
---|
879 | } |
---|
880 | #endif /* DEBUG */ |
---|
881 | return(0); |
---|
882 | } |
---|
883 | int |
---|
884 | dumprbuf() { /* Dump receive-buffers */ |
---|
885 | #ifdef DEBUG |
---|
886 | int j, x, z; |
---|
887 | if (! deblog) return(0); |
---|
888 | if (zsoutl(ZDFILE,"RECEIVE BUFFERS:") < 0) { |
---|
889 | deblog = 0; |
---|
890 | return(0); |
---|
891 | } |
---|
892 | x=zsoutl(ZDFILE,"buffer inuse address length data type seq flag retries"); |
---|
893 | if (x < 0) { |
---|
894 | deblog = 0; |
---|
895 | return(0); |
---|
896 | } |
---|
897 | for ( j = 0; j < wslots; j++ ) { |
---|
898 | if (!rbufuse[j]) |
---|
899 | continue; |
---|
900 | z = ((unsigned long)(r_pkt[j].bf_adr)) & 0xffff; |
---|
901 | sprintf(xbuf, /* 200, safe */ |
---|
902 | "%4d%6d%10d%5d%6d%4c%5d%6d\n", |
---|
903 | j, |
---|
904 | rbufuse[j], |
---|
905 | /* Avoid warnings when addresses are bigger than ints */ |
---|
906 | z, |
---|
907 | r_pkt[j].bf_len, |
---|
908 | r_pkt[j].pk_len, |
---|
909 | r_pkt[j].pk_typ, |
---|
910 | r_pkt[j].pk_seq, |
---|
911 | r_pkt[j].pk_rtr |
---|
912 | ); |
---|
913 | if (zsout(ZDFILE,xbuf) < 0) { |
---|
914 | deblog = 0; |
---|
915 | return(0); |
---|
916 | } |
---|
917 | x = (int)strlen((char *)r_pkt[j].bf_adr); |
---|
918 | sprintf(xbuf, /* safe (checked) */ |
---|
919 | "[%.72s%s]\n",r_pkt[j].bf_adr, x > 72 ? "..." : ""); |
---|
920 | if (zsout(ZDFILE,xbuf) < 0) { |
---|
921 | deblog = 0; |
---|
922 | return(0); |
---|
923 | } |
---|
924 | } |
---|
925 | sprintf(xbuf,"free: %d, winlo: %d\n", rbufnum, winlo); /* safe (200) */ |
---|
926 | if (zsout(ZDFILE,xbuf) < 0) { |
---|
927 | deblog = 0; |
---|
928 | return(0); |
---|
929 | } |
---|
930 | #endif /* DEBUG */ |
---|
931 | return(0); |
---|
932 | } |
---|
933 | |
---|
934 | /* S A T T R -- Send an Attribute Packet */ |
---|
935 | |
---|
936 | /* |
---|
937 | Sends attribute packet(s) for the current file. If the info will not |
---|
938 | fit into one packet, it can be called repeatedly until all the fields |
---|
939 | that will fit are sent. |
---|
940 | |
---|
941 | Call with: |
---|
942 | xp == 0 if we're sending a real file (F packet), or: |
---|
943 | xp != 0 for screen data (X packet). |
---|
944 | And: |
---|
945 | flag == 1 for first A packet |
---|
946 | flag == 0 for subsequent A packets. |
---|
947 | Returns: |
---|
948 | 1 or greater if an A packet was sent, or: |
---|
949 | 0 if an S-packet was not sent because there was no data to send or |
---|
950 | there was no data left that was short enough to send, or: |
---|
951 | -1 on any kind of error. |
---|
952 | */ |
---|
953 | |
---|
954 | /* (don't) #define TSOFORMAT */ |
---|
955 | /* which was only for making C-Kermit send TSO-Kermit-like A packets */ |
---|
956 | /* to try to track down a problem somebody reported... */ |
---|
957 | |
---|
958 | int |
---|
959 | sattr(xp, flag) int xp, flag; { /* Send Attributes */ |
---|
960 | |
---|
961 | static int max; /* Maximum length for Attributes */ |
---|
962 | static short done[95]; /* Field-complete array */ |
---|
963 | static struct zattr x; /* File attribute struct */ |
---|
964 | static char xdate[24]; |
---|
965 | |
---|
966 | extern char * cksysid; |
---|
967 | |
---|
968 | /* Some extra flags are used because the "done" array is sparse */ |
---|
969 | |
---|
970 | int i, j, rc, aln, left = 0, numset = 0, xbin = 0; /* Workers */ |
---|
971 | int notafile = 0; |
---|
972 | char *tp, c; |
---|
973 | |
---|
974 | notafile = sndarray || pipesend || |
---|
975 | #ifdef PIPESEND |
---|
976 | sndfilter || |
---|
977 | #endif /* PIPESEND */ |
---|
978 | calibrate; |
---|
979 | |
---|
980 | debug(F101,"sattr flag","",flag); |
---|
981 | if (!flag) /* No more attributes to send */ |
---|
982 | if (done[xunchar('@')]) |
---|
983 | return(0); |
---|
984 | |
---|
985 | /* Initialize Attribute mechanism */ |
---|
986 | |
---|
987 | if (flag) { /* First time here for this file? */ |
---|
988 | initattr(&x); /* Blank out all the fields. */ |
---|
989 | for (j = 0; j < 95; j++) /* Init array of completed fields */ |
---|
990 | done[j] = 0; |
---|
991 | max = maxdata(); /* Get maximum data field length */ |
---|
992 | if (notafile || xp == 1) { /* Is it not a real file? */ |
---|
993 | extern char * zzndate(); |
---|
994 | char * p; |
---|
995 | int i; |
---|
996 | #ifdef CALIBRATE |
---|
997 | if (calibrate) { /* Calibration run... */ |
---|
998 | x.lengthk = calibrate / 1024L; /* We know the length */ |
---|
999 | x.length = calibrate; |
---|
1000 | } |
---|
1001 | #endif /* CALIBRATE */ |
---|
1002 | x.systemid.val = cksysid; /* System ID */ |
---|
1003 | x.systemid.len = (int)strlen(cksysid); |
---|
1004 | ckstrncpy(xdate,zzndate(),24); |
---|
1005 | xdate[8] = SP; |
---|
1006 | ztime(&p); |
---|
1007 | for (i = 11; i < 19; i++) /* copy hh:mm:ss */ |
---|
1008 | xdate[i - 2] = p[i]; /* to xdate */ |
---|
1009 | xdate[17] = NUL; /* terminate */ |
---|
1010 | x.date.val = xdate; |
---|
1011 | x.date.len = 17; |
---|
1012 | debug(F111,"sattr notafile date",x.date.val,x.date.len); |
---|
1013 | } else { /* Real file */ |
---|
1014 | rc = zsattr(&x); /* Get attributes for this file */ |
---|
1015 | debug(F101,"sattr zsattr","",rc); |
---|
1016 | if (rc < 0) /* Can't get 'em so don't send 'em */ |
---|
1017 | return(0); |
---|
1018 | debug(F101,"sattr init max","",max); |
---|
1019 | } |
---|
1020 | } |
---|
1021 | if (nxtpkt() < 0) /* Got 'em, get next packet number */ |
---|
1022 | return(-1); /* Bad news if we can't */ |
---|
1023 | |
---|
1024 | i = 0; /* Init data field character number */ |
---|
1025 | |
---|
1026 | /* Do each attribute using first-fit method, marking as we go */ |
---|
1027 | /* This is rather long and repititious - could be done more cleverly */ |
---|
1028 | |
---|
1029 | if (atsido && !done[xunchar(c = '.')]) { /* System type */ |
---|
1030 | if (max - i >= x.systemid.len + 2) { /* Enough space ? */ |
---|
1031 | data[i++] = c; /* Yes, add parameter */ |
---|
1032 | data[i++] = tochar(x.systemid.len); /* Add length */ |
---|
1033 | for (j = 0; j < x.systemid.len; j++) /* Add data */ |
---|
1034 | data[i++] = x.systemid.val[j]; |
---|
1035 | numset++; /* Count that we did at least one */ |
---|
1036 | done[xunchar(c)] = 1; /* Mark this attribute as done */ |
---|
1037 | } else /* No */ |
---|
1038 | left++; /* so mark this one left to do */ |
---|
1039 | } |
---|
1040 | #ifdef STRATUS |
---|
1041 | if (atcreo && !done[xunchar(c = '$')]) { /* Creator */ |
---|
1042 | if (max - i >= x.creator.len + 2) { /* Enough space ? */ |
---|
1043 | data[i++] = c; |
---|
1044 | data[i++] = tochar(x.creator.len); |
---|
1045 | for (j = 0; j < x.creator.len; j++) |
---|
1046 | data[i++] = x.creator.val[j]; |
---|
1047 | numset++; |
---|
1048 | done[xunchar(c)] = 1; |
---|
1049 | } else |
---|
1050 | left++; |
---|
1051 | } |
---|
1052 | if (atacto && !done[xunchar(c = '%')]) { /* File account */ |
---|
1053 | if (max - i >= x.account.len + 2) { |
---|
1054 | data[i++] = c; |
---|
1055 | data[i++] = tochar(x.account.len); |
---|
1056 | for (j = 0; j < x.account.len; j++) |
---|
1057 | data[i++] = x.account.val[j]; |
---|
1058 | numset++; |
---|
1059 | done[xunchar(c)] = 1; |
---|
1060 | } else |
---|
1061 | left++; |
---|
1062 | } |
---|
1063 | if (atfrmo && !done[xunchar(c = '/')]) { /* Packet data format */ |
---|
1064 | if (max - i >= x.recfm.len + 2) { |
---|
1065 | data[i++] = c; |
---|
1066 | data[i++] = tochar(x.recfm.len); /* Copy from attr structure */ |
---|
1067 | for (j = 0; j < x.recfm.len; j++) |
---|
1068 | data[i++] = x.recfm.val[j]; |
---|
1069 | numset++; |
---|
1070 | done[xunchar(c)] = 1; |
---|
1071 | } else |
---|
1072 | left++; |
---|
1073 | } |
---|
1074 | #endif /* STRATUS */ |
---|
1075 | |
---|
1076 | xbin = /* Is the transfer in binary mode? */ |
---|
1077 | #ifdef VMS |
---|
1078 | binary == XYFT_I || binary == XYFT_L || /* IMAGE or LABELED */ |
---|
1079 | !strncmp(x.recfm.val,"F",1) /* or RECFM=Fxxxxxx */ |
---|
1080 | #else |
---|
1081 | binary /* User said SET FILE TYPE BINARY */ |
---|
1082 | #endif /* VMS */ |
---|
1083 | ; |
---|
1084 | |
---|
1085 | if (attypo && !done[xunchar(c = '"')]) { /* File type */ |
---|
1086 | if (max - i >= 5) { /* Max length for this field */ |
---|
1087 | data[i++] = c; |
---|
1088 | if (xbin) { /* Binary */ |
---|
1089 | data[i++] = tochar(2); /* Two characters */ |
---|
1090 | data[i++] = 'B'; /* B for Binary */ |
---|
1091 | data[i++] = '8'; /* 8-bit bytes (note assumption...) */ |
---|
1092 | #ifdef CK_LABELED |
---|
1093 | if (binary != XYFT_L |
---|
1094 | #ifdef VMS |
---|
1095 | && binary != XYFT_I |
---|
1096 | #endif /* VMS */ |
---|
1097 | ) |
---|
1098 | binary = XYFT_B; |
---|
1099 | #endif /* CK_LABELED */ |
---|
1100 | } else { /* Text */ |
---|
1101 | #ifdef TSOFORMAT |
---|
1102 | data[i++] = tochar(1); /* One character */ |
---|
1103 | data[i++] = 'A'; /* A = (extended) ASCII with CRLFs */ |
---|
1104 | #else |
---|
1105 | data[i++] = tochar(3); /* Three characters */ |
---|
1106 | data[i++] = 'A'; /* A = (extended) ASCII with CRLFs */ |
---|
1107 | data[i++] = 'M'; /* M for carriage return */ |
---|
1108 | data[i++] = 'J'; /* J for linefeed */ |
---|
1109 | #endif /* TSOFORMAT */ |
---|
1110 | |
---|
1111 | #ifdef VMS |
---|
1112 | binary = XYFT_T; /* We automatically detected text */ |
---|
1113 | #endif /* VMS */ |
---|
1114 | } |
---|
1115 | numset++; |
---|
1116 | done[xunchar(c)] = 1; |
---|
1117 | } else |
---|
1118 | left++; |
---|
1119 | } |
---|
1120 | |
---|
1121 | #ifdef TSOFORMAT |
---|
1122 | if (attypo && !xbin && !done[xunchar(c = '/')]) { /* Record format */ |
---|
1123 | if (max - i >= 5) { |
---|
1124 | data[i++] = c; |
---|
1125 | data[i++] = tochar(3); /* Three characters */ |
---|
1126 | data[i++] = 'A'; /* A = variable with CRLFs */ |
---|
1127 | data[i++] = 'M'; /* M for carriage return */ |
---|
1128 | data[i++] = 'J'; /* J for linefeed */ |
---|
1129 | } |
---|
1130 | } |
---|
1131 | #endif /* TSOFORMAT */ |
---|
1132 | |
---|
1133 | if (attypo && !xbin && !done[xunchar(c = '*')]) { /* Text encoding */ |
---|
1134 | #ifdef NOCSETS |
---|
1135 | if (max - i >= 3) { |
---|
1136 | data[i++] = c; |
---|
1137 | data[i++] = tochar(1); /* Length of value is 1 */ |
---|
1138 | data[i++] = 'A'; /* A for ASCII */ |
---|
1139 | numset++; |
---|
1140 | done[xunchar(c)] = 1; |
---|
1141 | } else |
---|
1142 | left++; |
---|
1143 | #else |
---|
1144 | if (tcharset == TC_TRANSP || !xfrxla) { /* Transfer character set */ |
---|
1145 | if (max - i >= 3) { |
---|
1146 | data[i++] = c; /* Encoding */ |
---|
1147 | data[i++] = tochar(1); /* Length of value is 1 */ |
---|
1148 | data[i++] = 'A'; /* A for ASCII (i.e. text) */ |
---|
1149 | numset++; |
---|
1150 | done[xunchar(c)] = 1; |
---|
1151 | } else |
---|
1152 | left++; |
---|
1153 | } else { |
---|
1154 | tp = tcsinfo[tcharset].designator; |
---|
1155 | if (!tp) tp = ""; |
---|
1156 | aln = strlen(tp); |
---|
1157 | if (aln > 0) { |
---|
1158 | if (max - i >= aln + 2) { |
---|
1159 | data[i++] = c; /* Encoding */ |
---|
1160 | data[i++] = tochar(aln+1); /* Length of designator. */ |
---|
1161 | data[i++] = 'C'; /* Text in specified charset. */ |
---|
1162 | for (j = 0; j < aln; j++) /* Copy designator */ |
---|
1163 | data[i++] = *tp++; /* Example: *&I6/100 */ |
---|
1164 | numset++; |
---|
1165 | done[xunchar(c)] = 1; |
---|
1166 | } else |
---|
1167 | left++; |
---|
1168 | } else |
---|
1169 | done[xunchar(c)] = 1; |
---|
1170 | } |
---|
1171 | #endif /* NOCSETS */ |
---|
1172 | } |
---|
1173 | if (atdato && !done[xunchar(c = '#')] && /* Creation date, if any */ |
---|
1174 | (aln = x.date.len) > 0) { |
---|
1175 | if (max - i >= aln + 2) { |
---|
1176 | data[i++] = c; |
---|
1177 | data[i++] = tochar(aln); |
---|
1178 | for (j = 0; j < aln; j++) |
---|
1179 | data[i++] = x.date.val[j]; |
---|
1180 | numset++; |
---|
1181 | done[xunchar(c)] = 1; |
---|
1182 | } else |
---|
1183 | left++; |
---|
1184 | } |
---|
1185 | /* File length in K */ |
---|
1186 | if (atleno && !done[xunchar(c = '!')] && x.lengthk > -1L) { |
---|
1187 | sprintf((char *) &data[i+2],"%ld",x.lengthk); /* safe */ |
---|
1188 | aln = (int)strlen((char *)(data+i+2)); |
---|
1189 | if (max - i >= aln + 2) { |
---|
1190 | data[i] = c; |
---|
1191 | data[i+1] = tochar(aln); |
---|
1192 | i += aln + 2; |
---|
1193 | numset++; |
---|
1194 | done[xunchar(c)] = 1; |
---|
1195 | } else { |
---|
1196 | data[i] = NUL; |
---|
1197 | left++; |
---|
1198 | } |
---|
1199 | } |
---|
1200 | /* File length in bytes */ |
---|
1201 | if (atleno && !done[xunchar(c = '1')] && x.length > -1L) { |
---|
1202 | sprintf((char *) &data[i+2],"%ld",x.length); /* safe */ |
---|
1203 | aln = (int)strlen((char *)(data+i+2)); |
---|
1204 | if (max - i >= aln + 2) { |
---|
1205 | data[i] = c; |
---|
1206 | data[i+1] = tochar(aln); |
---|
1207 | i += aln + 2; |
---|
1208 | numset++; |
---|
1209 | done[xunchar(c)] = 1; |
---|
1210 | } else { |
---|
1211 | data[i] = NUL; |
---|
1212 | left++; |
---|
1213 | } |
---|
1214 | } |
---|
1215 | #ifdef CK_PERMS |
---|
1216 | if (atlpro && !done[xunchar(c = ',')] && /* Local protection */ |
---|
1217 | (aln = x.lprotect.len) > 0 && !notafile && xp == 0) { |
---|
1218 | if (max - i >= aln + 2) { |
---|
1219 | data[i++] = c; |
---|
1220 | data[i++] = tochar(aln); |
---|
1221 | for (j = 0; j < aln; j++) |
---|
1222 | data[i++] = x.lprotect.val[j]; |
---|
1223 | numset++; |
---|
1224 | done[xunchar(c)] = 1; |
---|
1225 | } else |
---|
1226 | left++; |
---|
1227 | } |
---|
1228 | if (atgpro && !done[xunchar(c = '-')] && /* Generic protection */ |
---|
1229 | (aln = x.gprotect.len) > 0 && !notafile && xp == 0) { |
---|
1230 | if (max - i >= aln + 2) { |
---|
1231 | data[i++] = c; |
---|
1232 | data[i++] = tochar(aln); |
---|
1233 | for (j = 0; j < aln; j++) |
---|
1234 | data[i++] = x.gprotect.val[j]; |
---|
1235 | numset++; |
---|
1236 | done[xunchar(c)] = 1; |
---|
1237 | } else |
---|
1238 | left++; |
---|
1239 | } |
---|
1240 | #endif /* CK_PERMS */ |
---|
1241 | if (atblko && fblksiz && !done[xunchar(c = '(')] && |
---|
1242 | !notafile && xp == 0) { /* Blocksize */ |
---|
1243 | sprintf((char *) &data[i+2],"%d",fblksiz); /* safe */ |
---|
1244 | aln = (int)strlen((char *)(data+i+2)); |
---|
1245 | if (max - i >= aln + 2) { |
---|
1246 | data[i] = c; |
---|
1247 | data[i+1] = tochar(aln); |
---|
1248 | i += aln + 2; |
---|
1249 | numset++; |
---|
1250 | done[xunchar(c)] = 1; |
---|
1251 | } else { |
---|
1252 | data[i] = NUL; |
---|
1253 | left++; |
---|
1254 | } |
---|
1255 | } |
---|
1256 | #ifndef NOFRILLS |
---|
1257 | if ((rprintf || rmailf) && atdiso && /* MAIL, or REMOTE PRINT? */ |
---|
1258 | !done[xunchar(c = '+')]) { |
---|
1259 | aln = (int) strlen(optbuf) + 1; /* Options, if any */ |
---|
1260 | if (max - i >= aln + 2) { |
---|
1261 | data[i++] = c; /* Disposition */ |
---|
1262 | data[i++] = tochar(aln); /* Options, if any */ |
---|
1263 | if (rprintf) |
---|
1264 | data[i++] = 'P'; /* P for Print */ |
---|
1265 | else |
---|
1266 | data[i++] = 'M'; /* M for Mail */ |
---|
1267 | for (j = 0; optbuf[j]; j++) /* Copy any options */ |
---|
1268 | data[i++] = optbuf[j]; |
---|
1269 | numset++; |
---|
1270 | done[xunchar(c)] = 1; |
---|
1271 | } else { |
---|
1272 | data[i] = NUL; |
---|
1273 | left++; |
---|
1274 | } |
---|
1275 | } |
---|
1276 | #endif /* NOFRILLS */ |
---|
1277 | #ifdef CK_RESEND |
---|
1278 | if (sendmode == SM_RESEND && !done[xunchar(c = '+')]) { |
---|
1279 | if (max - i >= 3) { |
---|
1280 | data[i++] = c; /* Disposition */ |
---|
1281 | data[i++] = tochar(1); |
---|
1282 | data[i++] = 'R'; /* is RESEND */ |
---|
1283 | numset++; |
---|
1284 | done[xunchar(c)] = 1; |
---|
1285 | } else |
---|
1286 | left++; |
---|
1287 | } |
---|
1288 | #endif /* CK_RESEND */ |
---|
1289 | |
---|
1290 | /* End of Attributes -- to be sent only after sending all others */ |
---|
1291 | |
---|
1292 | debug(F111,"sattr","@",i); |
---|
1293 | debug(F101,"sattr numset","",numset); |
---|
1294 | debug(F101,"sattr left","",left); |
---|
1295 | |
---|
1296 | if ((left == 0 || numset == 0) && !done[xunchar(c = '@')]) { |
---|
1297 | if (max - i >= 3) { |
---|
1298 | data[i++] = c; /* End of Attributes */ |
---|
1299 | data[i++] = SP; /* Length 0 */ |
---|
1300 | data[i] = NUL; /* Make sure it's null-terminated */ |
---|
1301 | numset++; |
---|
1302 | done[xunchar(c)] = 1; |
---|
1303 | } |
---|
1304 | } |
---|
1305 | |
---|
1306 | /* Finished - send the packet off if we have anything in it */ |
---|
1307 | |
---|
1308 | if (numset) { |
---|
1309 | data[i] = NUL; /* Terminate last good field */ |
---|
1310 | debug(F111,"sattr sending",data,left); |
---|
1311 | aln = (int)strlen((char *)data); /* Get overall length of attributes */ |
---|
1312 | return(spack('A',pktnum,aln,data)); /* Send it */ |
---|
1313 | } else |
---|
1314 | return(0); |
---|
1315 | } |
---|
1316 | |
---|
1317 | static char *refused = ""; |
---|
1318 | |
---|
1319 | static char *reason[] = { |
---|
1320 | "size", "type", "date", "creator", "account", "area", "password", |
---|
1321 | "blocksize", "access", "encoding", "disposition", "protection", |
---|
1322 | "protection", "origin", "format", |
---|
1323 | "sys-dependent", /* 0 */ |
---|
1324 | "size", /* 1 */ |
---|
1325 | "2", /* 2 */ |
---|
1326 | "3", /* 3 */ |
---|
1327 | "4", /* 4 */ |
---|
1328 | "5", /* 5 */ |
---|
1329 | "6", /* 6 */ |
---|
1330 | "7", /* 7 */ |
---|
1331 | "8", /* 8 */ |
---|
1332 | "9", /* 9 */ |
---|
1333 | ":", /* : */ |
---|
1334 | ";", /* ; */ |
---|
1335 | "<", /* < */ |
---|
1336 | "=", /* = */ |
---|
1337 | ">", /* > */ |
---|
1338 | "name", /* ? */ |
---|
1339 | "@" |
---|
1340 | }; |
---|
1341 | static int nreason = sizeof(reason) / sizeof(char *); |
---|
1342 | int rejection = -1; |
---|
1343 | |
---|
1344 | char * |
---|
1345 | getreason(s) char *s; { /* Decode attribute refusal reason */ |
---|
1346 | char c, *p; |
---|
1347 | if (rejection == 1) /* Kludge for SET FIL COLL DISCARD */ |
---|
1348 | return("name"); /* when other Kermit doesn't... */ |
---|
1349 | p = s; |
---|
1350 | if (*p++ != 'N') return(""); /* Should start with N */ |
---|
1351 | else if ((c = *p) > SP) { /* get reason, */ |
---|
1352 | rejection = c; /* remember it, */ |
---|
1353 | c -= '!'; /* get offset */ |
---|
1354 | p = ((unsigned int) ((CHAR) c) <= (unsigned int) nreason) ? |
---|
1355 | reason[c] : |
---|
1356 | "unknown"; |
---|
1357 | } |
---|
1358 | return(p); |
---|
1359 | } |
---|
1360 | |
---|
1361 | int |
---|
1362 | rsattr(s) CHAR *s; { /* Read response to attribute packet */ |
---|
1363 | debug(F111,"rsattr",s,*s); |
---|
1364 | if (*s == 'N') { /* If it's 'N' followed by anything, */ |
---|
1365 | refused = getreason((char *)s); /* they are refusing, get reason. */ |
---|
1366 | debug(F110,"rsattr refused",refused,0); |
---|
1367 | tlog(F110," refused:",refused,0L); |
---|
1368 | return(-1); |
---|
1369 | } |
---|
1370 | #ifdef CK_RESEND |
---|
1371 | if (sendmode == SM_RESEND && *s == '1') { /* RESEND length */ |
---|
1372 | int n; long z; CHAR *p; |
---|
1373 | p = s + 1; |
---|
1374 | n = xunchar(*p++); |
---|
1375 | debug(F101,"rsattr RESEND n","",n); |
---|
1376 | z = 0L; |
---|
1377 | while (n-- > 0) /* We assume the format is good. */ |
---|
1378 | z = 10L * z + (long) (*p++ - '0'); |
---|
1379 | debug(F101,"rsattr RESEND z","",z); |
---|
1380 | if (z > 0L) sendstart = z; |
---|
1381 | debug(F101,"rsattr RESEND sendstart","",sendstart); |
---|
1382 | if (sendstart > 0L) |
---|
1383 | if (zfseek(sendstart) < 0) /* Input file is already open. */ |
---|
1384 | return(0); |
---|
1385 | #ifdef CK_CURSES |
---|
1386 | if (fdispla == XYFD_C) |
---|
1387 | xxscreen(SCR_FS,0,fsize,""); /* Refresh file transfer display */ |
---|
1388 | #endif /* CK_CURSES */ |
---|
1389 | } |
---|
1390 | #endif /* CK_RESEND */ |
---|
1391 | refused = ""; |
---|
1392 | return(0); |
---|
1393 | } |
---|
1394 | |
---|
1395 | long rs_len = 0L; /* Length of file being resent to */ |
---|
1396 | |
---|
1397 | /* |
---|
1398 | Get attributes from incoming A packet. Returns: |
---|
1399 | 0 on success, file is to be accepted |
---|
1400 | -1 on failure, file is to be refused |
---|
1401 | */ |
---|
1402 | int |
---|
1403 | gattr(s, yy) CHAR *s; struct zattr *yy; { /* Read incoming attribute packet */ |
---|
1404 | char c, d; |
---|
1405 | char *ff; |
---|
1406 | int aln, i; |
---|
1407 | |
---|
1408 | #ifndef NOCSETS |
---|
1409 | extern int r_cset, axcset[]; |
---|
1410 | #endif /* NOCSETS */ |
---|
1411 | |
---|
1412 | #define ABUFL 40 /* Temporary buffer for conversions */ |
---|
1413 | char abuf[ABUFL+1]; |
---|
1414 | #define RFBUFL 10 /* Record-format buffer */ |
---|
1415 | static char rfbuf[RFBUFL+1]; |
---|
1416 | #define FTBUFL 10 /* File type buffer */ |
---|
1417 | static char ftbuf[FTBUFL+1]; |
---|
1418 | #define DTBUFL 40 /* File creation date */ |
---|
1419 | static char dtbuf[DTBUFL+1]; |
---|
1420 | #define TSBUFL 10 /* Transfer syntax */ |
---|
1421 | static char tsbuf[TSBUFL+1]; |
---|
1422 | #define IDBUFL 10 /* System ID */ |
---|
1423 | static char idbuf[IDBUFL+1]; |
---|
1424 | #ifndef DYNAMIC |
---|
1425 | #define DSBUFL 100 /* Disposition */ |
---|
1426 | static char dsbuf[DSBUFL+1]; |
---|
1427 | #define SPBUFL 512 /* System-dependent parameters */ |
---|
1428 | static char spbuf[SPBUFL+1]; |
---|
1429 | #else |
---|
1430 | #define DSBUFL 100 /* Disposition */ |
---|
1431 | static char *dsbuf = NULL; |
---|
1432 | #define SPBUFL 512 /* System-dependent parameters */ |
---|
1433 | static char *spbuf = NULL; |
---|
1434 | #endif /* DYNAMIC */ |
---|
1435 | #define RPBUFL 20 /* Attribute reply */ |
---|
1436 | static char rpbuf[RPBUFL+1]; |
---|
1437 | |
---|
1438 | #ifdef CK_PERMS |
---|
1439 | static char lprmbuf[CK_PERMLEN+1]; |
---|
1440 | static char gprmbuf[2]; |
---|
1441 | #endif /* CK_PERMS */ |
---|
1442 | |
---|
1443 | char *rp; /* Pointer to reply buffer */ |
---|
1444 | int retcode; /* Return code */ |
---|
1445 | |
---|
1446 | d = SP; /* Initialize disposition */ |
---|
1447 | ff = filnam; /* Filename returned by rcvfil */ |
---|
1448 | if (fncact == XYFX_R && ofn1x && ofn1[0]) /* But watch out for FC=RENAME */ |
---|
1449 | ff = ofn1; /* because we haven't renamed it yet */ |
---|
1450 | |
---|
1451 | /* Fill in the attributes we have received */ |
---|
1452 | |
---|
1453 | rp = rpbuf; /* Initialize reply buffer */ |
---|
1454 | *rp++ = 'N'; /* for negative reply. */ |
---|
1455 | *rp = NUL; |
---|
1456 | retcode = 0; /* Initialize return code. */ |
---|
1457 | |
---|
1458 | if (dest == DEST_P) { /* SET DESTINATION PRINTER */ |
---|
1459 | #ifdef DYNAMIC |
---|
1460 | if (!dsbuf) |
---|
1461 | if ((dsbuf = malloc(DSBUFL+1)) == NULL) |
---|
1462 | fatal("gtattr: no memory for dsbuf"); |
---|
1463 | #endif /* DYNAMIC */ |
---|
1464 | dsbuf[0] = 'P'; |
---|
1465 | dsbuf[1] = '\0'; |
---|
1466 | yy->disp.val = dsbuf; |
---|
1467 | yy->disp.len = 1; |
---|
1468 | } |
---|
1469 | while (c = *s++) { /* Get attribute tag */ |
---|
1470 | aln = xunchar(*s++); /* Length of attribute string */ |
---|
1471 | switch (c) { |
---|
1472 | case '!': /* File length in K */ |
---|
1473 | for (i = 0; (i < aln) && (i < ABUFL); i++) /* Copy it */ |
---|
1474 | abuf[i] = *s++; |
---|
1475 | abuf[i] = '\0'; /* Terminate with null */ |
---|
1476 | if (i < aln) s += (aln - i); /* If field was too long for buffer */ |
---|
1477 | yy->lengthk = atol(abuf); /* Convert to number */ |
---|
1478 | break; |
---|
1479 | |
---|
1480 | case '/': /* Record format */ |
---|
1481 | rfbuf[1] = NUL; |
---|
1482 | rfbuf[2] = NUL; |
---|
1483 | for (i = 0; (i < aln) && (i < RFBUFL); i++) /* Copy it */ |
---|
1484 | rfbuf[i] = *s++; |
---|
1485 | rfbuf[i] = NUL; /* Terminate with null */ |
---|
1486 | yy->recfm.val = rfbuf; /* Pointer to string */ |
---|
1487 | yy->recfm.len = i; /* Length of string */ |
---|
1488 | if ((rfbuf[0] != 'A') || |
---|
1489 | (rfbuf[1] && rfbuf[1] != 'M') || |
---|
1490 | (rfbuf[2] && rfbuf[2] != 'J')) { |
---|
1491 | debug(F110,"gattr bad recfm",rfbuf,0); |
---|
1492 | *rp++ = c; |
---|
1493 | retcode = -1; |
---|
1494 | } |
---|
1495 | break; |
---|
1496 | |
---|
1497 | case '"': /* File type (text, binary, ...) */ |
---|
1498 | for (i = 0; (i < aln) && (i < FTBUFL); i++) |
---|
1499 | ftbuf[i] = *s++; /* Copy it into a static string */ |
---|
1500 | ftbuf[i] = '\0'; |
---|
1501 | if (i < aln) s += (aln - i); |
---|
1502 | /* TYPE attribute is enabled? */ |
---|
1503 | if (attypi) { |
---|
1504 | yy->type.val = ftbuf; /* Pointer to string */ |
---|
1505 | yy->type.len = i; /* Length of string */ |
---|
1506 | debug(F111,"gattr file type", ftbuf, i); |
---|
1507 | debug(F101,"gattr binary 1","",binary); |
---|
1508 | /* Unknown type? */ |
---|
1509 | if ((*ftbuf != 'A' && *ftbuf != 'B' && *ftbuf != 'I') |
---|
1510 | #ifdef CK_LABELED |
---|
1511 | /* ... Or our FILE TYPE is LABELED and the incoming file is text... */ |
---|
1512 | || (binary == XYFT_L && *ftbuf == 'A' && !xflg) |
---|
1513 | #endif /* CK_LABELED */ |
---|
1514 | ) { |
---|
1515 | retcode = -1; /* Reject the file */ |
---|
1516 | *rp++ = c; |
---|
1517 | if (!opnerr) tlog(F100," refused: type","",0); |
---|
1518 | break; |
---|
1519 | } |
---|
1520 | /* |
---|
1521 | The following code moved here from opena() so we set binary mode |
---|
1522 | as soon as requested by the attribute packet. That way when the first |
---|
1523 | data packet comes, the mode of transfer can be displayed correctly |
---|
1524 | before opena() is called. |
---|
1525 | */ |
---|
1526 | if (yy->type.val[0] == 'A') { /* Check received attributes. */ |
---|
1527 | #ifdef VMS |
---|
1528 | if (binary != XYFT_I) /* VMS IMAGE overrides this */ |
---|
1529 | #endif /* VMS */ |
---|
1530 | binary = XYFT_T; /* Set current type to Text. */ |
---|
1531 | debug(F101,"gattr binary 2","",binary); |
---|
1532 | } else if (yy->type.val[0] == 'B') { |
---|
1533 | #ifdef CK_LABELED |
---|
1534 | if (binary != XYFT_L |
---|
1535 | #ifdef VMS |
---|
1536 | && binary != XYFT_U /* VMS special case */ |
---|
1537 | #endif /* VMS */ |
---|
1538 | ) |
---|
1539 | #endif /* CK_LABELED */ |
---|
1540 | #ifdef MAC |
---|
1541 | if (binary != XYFT_M) /* If not MacBinary... */ |
---|
1542 | #endif /* MAC */ |
---|
1543 | binary = XYFT_B; |
---|
1544 | debug(F101,"gattr binary 3","",binary); |
---|
1545 | } |
---|
1546 | } |
---|
1547 | break; |
---|
1548 | |
---|
1549 | case '#': /* File creation date */ |
---|
1550 | for (i = 0; (i < aln) && (i < DTBUFL); i++) |
---|
1551 | dtbuf[i] = *s++; /* Copy it into a static string */ |
---|
1552 | if (i < aln) s += (aln - i); |
---|
1553 | dtbuf[i] = '\0'; |
---|
1554 | if (atdati && !xflg) { /* Real file and dates enabled */ |
---|
1555 | yy->date.val = dtbuf; /* Pointer to string */ |
---|
1556 | yy->date.len = i; /* Length of string */ |
---|
1557 | if (fncact == XYFX_U) { /* Receiving in update mode? */ |
---|
1558 | if (zstime(ff,yy,1) > 0) { /* Compare dates */ |
---|
1559 | *rp++ = c; /* Discard if older, reason = date. */ |
---|
1560 | if (!opnerr) tlog(F100," refused: date","",0); |
---|
1561 | retcode = -1; /* Rejection notice. */ |
---|
1562 | } |
---|
1563 | } |
---|
1564 | } |
---|
1565 | break; |
---|
1566 | |
---|
1567 | case '(': /* File Block Size */ |
---|
1568 | for (i = 0; (i < aln) && (i < ABUFL); i++) /* Copy it */ |
---|
1569 | abuf[i] = *s++; |
---|
1570 | abuf[i] = '\0'; /* Terminate with null */ |
---|
1571 | if (i < aln) s += (aln - i); |
---|
1572 | if (atblki) |
---|
1573 | yy->blksize = atol(abuf); /* Convert to number */ |
---|
1574 | break; |
---|
1575 | |
---|
1576 | case '*': /* Encoding (transfer syntax) */ |
---|
1577 | for (i = 0; (i < aln) && (i < TSBUFL); i++) |
---|
1578 | tsbuf[i] = *s++; /* Copy it into a static string */ |
---|
1579 | if (i < aln) s += (aln - i); |
---|
1580 | tsbuf[i] = '\0'; |
---|
1581 | #ifndef NOCSETS |
---|
1582 | xlatype = XLA_NONE; /* Assume no translation */ |
---|
1583 | #endif /* NOCSETS */ |
---|
1584 | if (atenci) { |
---|
1585 | char * ss; |
---|
1586 | yy->encoding.val = tsbuf; /* Pointer to string */ |
---|
1587 | yy->encoding.len = i; /* Length of string */ |
---|
1588 | debug(F101,"gattr encoding",tsbuf,i); |
---|
1589 | ss = tsbuf+1; |
---|
1590 | switch (*tsbuf) { |
---|
1591 | #ifndef NOCSETS |
---|
1592 | case 'A': /* Normal, nothing special */ |
---|
1593 | tcharset = TC_TRANSP; /* Transparent chars untranslated */ |
---|
1594 | debug(F110,"gattr sets tcharset TC_TRANSP","A",0); |
---|
1595 | break; |
---|
1596 | case 'C': /* Specified character set */ |
---|
1597 | if (!xfrxla) { /* But translation disabled */ |
---|
1598 | tcharset = TC_TRANSP; |
---|
1599 | debug(F110,"gattr sets tcharset TC_TRANSP","C",0); |
---|
1600 | break; |
---|
1601 | } |
---|
1602 | #ifdef UNICODE |
---|
1603 | if (!strcmp("I196",ss)) /* Treat I196 (UTF-8 no level) */ |
---|
1604 | ss = "I190"; /* as I190 (UTF-8 Level 1) */ |
---|
1605 | #endif /* UNICODE */ |
---|
1606 | if (!strcmp("I6/204",ss)) /* Treat "Latin-1 + Euro" */ |
---|
1607 | ss = "I6/100"; /* as I6/100 (regular Latin-1) */ |
---|
1608 | for (i = 0; i < ntcsets; i++) { |
---|
1609 | if (!strcmp(tcsinfo[i].designator,ss)) |
---|
1610 | break; |
---|
1611 | } |
---|
1612 | debug(F101,"gattr xfer charset lookup","",i); |
---|
1613 | if (i == ntcsets) { /* If unknown character set, */ |
---|
1614 | debug(F110,"gattr: xfer charset unknown",ss,0); |
---|
1615 | if (!unkcs) { /* and SET UNKNOWN DISCARD, */ |
---|
1616 | retcode = -1; /* reject the file. */ |
---|
1617 | *rp++ = c; |
---|
1618 | if (!opnerr) |
---|
1619 | tlog(F100," refused: character set","",0); |
---|
1620 | } |
---|
1621 | } else { |
---|
1622 | tcharset = tcsinfo[i].code; /* it's known, use it */ |
---|
1623 | debug(F101,"gattr switch tcharset","",tcharset); |
---|
1624 | debug(F101,"gattr fcharset","",fcharset); |
---|
1625 | if (r_cset == XMODE_A) { /* Automatic switching? */ |
---|
1626 | if (tcharset > -1 && tcharset <= MAXTCSETS) { |
---|
1627 | int x; |
---|
1628 | x = axcset[tcharset]; |
---|
1629 | if (x > 0 && x <= MAXFCSETS) { |
---|
1630 | fcharset = x; |
---|
1631 | debug(F101,"gattr switch fcharset","",x); |
---|
1632 | } |
---|
1633 | } |
---|
1634 | } |
---|
1635 | /* Set up translation type and function */ |
---|
1636 | setxlatype(tcharset,fcharset); |
---|
1637 | } |
---|
1638 | break; |
---|
1639 | #endif /* NOCSETS */ |
---|
1640 | default: /* Something else. */ |
---|
1641 | debug(F110,"gattr unk encoding attribute",tsbuf,0); |
---|
1642 | if (!unkcs) { /* If SET UNK DISC */ |
---|
1643 | retcode = -1; |
---|
1644 | *rp++ = c; |
---|
1645 | if (!opnerr) tlog(F100," refused: encoding","",0); |
---|
1646 | } |
---|
1647 | break; |
---|
1648 | } |
---|
1649 | } |
---|
1650 | break; |
---|
1651 | |
---|
1652 | case '+': /* Disposition */ |
---|
1653 | #ifdef DYNAMIC |
---|
1654 | if (!dsbuf) |
---|
1655 | if ((dsbuf = malloc(DSBUFL+1)) == NULL) |
---|
1656 | fatal("gtattr: no memory for dsbuf"); |
---|
1657 | #endif /* DYNAMIC */ |
---|
1658 | for (i = 0; (i < aln) && (i < DSBUFL); i++) |
---|
1659 | dsbuf[i] = *s++; /* Copy it into a separate string */ |
---|
1660 | dsbuf[i] = '\0'; |
---|
1661 | if (i < aln) s += (aln - i); |
---|
1662 | rs_len = 0; |
---|
1663 | if (atdisi) { /* We are doing this attribute */ |
---|
1664 | /* Copy it into the attribute structure */ |
---|
1665 | yy->disp.val = dsbuf; /* Pointer to string */ |
---|
1666 | yy->disp.len = i; /* Length of string */ |
---|
1667 | d = *dsbuf; |
---|
1668 | #ifndef NODISPO |
---|
1669 | /* |
---|
1670 | Define NODISPO to disable receipt of mail or print files and of RESEND. |
---|
1671 | */ |
---|
1672 | if ( |
---|
1673 | #ifndef datageneral /* MAIL supported only for */ |
---|
1674 | #ifndef OS2 /* UNIX, VMS, and OS-9 */ |
---|
1675 | #ifndef MAC |
---|
1676 | #ifndef GEMDOS |
---|
1677 | #ifndef AMIGA |
---|
1678 | d != 'M' && /* MAIL */ |
---|
1679 | #endif /* AMIGA */ |
---|
1680 | #endif /* GEMDOS */ |
---|
1681 | #endif /* MAC */ |
---|
1682 | #endif /* OS/2 */ |
---|
1683 | #endif /* datageneral */ |
---|
1684 | #ifdef CK_RESEND |
---|
1685 | d != 'R' && /* RESEND */ |
---|
1686 | #endif /* CK_RESEND */ |
---|
1687 | d != 'P') { /* PRINT */ |
---|
1688 | retcode = -1; /* Unknown/unsupported disposition */ |
---|
1689 | *rp++ = c; |
---|
1690 | if (!opnerr) tlog(F101," refused: bad disposition","",d); |
---|
1691 | } |
---|
1692 | dispos = d; |
---|
1693 | debug(F000,"gattr dispos","",dispos); |
---|
1694 | switch (d) { |
---|
1695 | #ifndef NOFRILLS |
---|
1696 | case 'M': |
---|
1697 | if (!en_mai) { |
---|
1698 | retcode = -1; |
---|
1699 | *rp++ = c; |
---|
1700 | if (!opnerr) tlog(F100," refused: mail disabled","",0); |
---|
1701 | dispos = 0; |
---|
1702 | } |
---|
1703 | break; |
---|
1704 | #endif /* NOFRILLS */ |
---|
1705 | case 'P': |
---|
1706 | if (!en_pri) { |
---|
1707 | retcode = -1; |
---|
1708 | *rp++ = c; |
---|
1709 | if (!opnerr) |
---|
1710 | tlog(F100," refused: print disabled","",0); |
---|
1711 | dispos = 0; |
---|
1712 | } |
---|
1713 | break; |
---|
1714 | |
---|
1715 | case 'R': |
---|
1716 | dispos = 0; |
---|
1717 | #ifdef CK_RESEND |
---|
1718 | rs_len = zgetfs(ff); /* Get length of file */ |
---|
1719 | debug(F111,"gattr RESEND",ff,rs_len); |
---|
1720 | #ifdef VMS |
---|
1721 | rs_len &= (long) -512; /* Ensure block boundary if VMS */ |
---|
1722 | rs_len -= 512; /* In case last block not complete */ |
---|
1723 | debug(F111,"gattr rs_len",ff,rs_len); |
---|
1724 | #endif /* VMS */ |
---|
1725 | #ifdef COMMENT |
---|
1726 | if (rs_len < 0L) /* Local file doesn't exist */ |
---|
1727 | rs_len = 0L; |
---|
1728 | #endif /* COMMENT */ |
---|
1729 | /* |
---|
1730 | Another possibility here (or later, really) would be to check if the two |
---|
1731 | file lengths are the same, and if so, keep the prevailing collision action |
---|
1732 | as is (note: rs_len == length of existing file; yy->length == fsize == |
---|
1733 | length of incoming file). This could be complicated, though, since |
---|
1734 | (a) we might not have received the length attribute yet, and in fact it |
---|
1735 | might even be in a subsequent A-packet, yet (b) we have to accept or reject |
---|
1736 | the Recover attribute now. So better to leave as-is. Anyway, it's probably |
---|
1737 | more useful this way. |
---|
1738 | */ |
---|
1739 | if (rs_len > 0L) { |
---|
1740 | fncsav = fncact; /* Save collision action */ |
---|
1741 | fncact = XYFX_A; /* Switch to APPEND */ |
---|
1742 | } |
---|
1743 | #else |
---|
1744 | retcode = -1; /* This shouldn't happen */ |
---|
1745 | *rp++ = c; /* 'cause it wasn't negotiated. */ |
---|
1746 | if (!opnerr) tlog(F100," refused: resend","",0); |
---|
1747 | #endif /* CK_RESEND */ |
---|
1748 | } |
---|
1749 | #else /* NODISPO */ |
---|
1750 | retcode = -1; |
---|
1751 | *rp++ = c; |
---|
1752 | if (!opnerr) tlog(F100," refused: NODISPO","",0); |
---|
1753 | #endif /* NODISPO */ |
---|
1754 | } |
---|
1755 | break; |
---|
1756 | |
---|
1757 | case '.': /* Sender's system ID */ |
---|
1758 | for (i = 0; (i < aln) && (i < IDBUFL); i++) |
---|
1759 | idbuf[i] = *s++; /* Copy it into a static string */ |
---|
1760 | idbuf[i] = '\0'; |
---|
1761 | if (i < aln) s += (aln - i); |
---|
1762 | if (atsidi) { |
---|
1763 | yy->systemid.val = idbuf; /* Pointer to string */ |
---|
1764 | yy->systemid.len = i; /* Length of string */ |
---|
1765 | } |
---|
1766 | break; |
---|
1767 | |
---|
1768 | case '0': /* System-dependent parameters */ |
---|
1769 | #ifdef DYNAMIC |
---|
1770 | if (!spbuf && !(spbuf = malloc(SPBUFL))) |
---|
1771 | fatal("gattr: no memory for spbuf"); |
---|
1772 | #endif /* DYNAMIC */ |
---|
1773 | for (i = 0; (i < aln) && (i < SPBUFL); i++) |
---|
1774 | spbuf[i] = *s++; /* Copy it into a static string */ |
---|
1775 | spbuf[i] = '\0'; |
---|
1776 | if (i < aln) s += (aln - i); |
---|
1777 | if (atsysi) { |
---|
1778 | yy->sysparam.val = spbuf; /* Pointer to string */ |
---|
1779 | yy->sysparam.len = i; /* Length of string */ |
---|
1780 | } |
---|
1781 | break; |
---|
1782 | |
---|
1783 | case '1': /* File length in bytes */ |
---|
1784 | for (i = 0; (i < aln) && (i < ABUFL); i++) /* Copy it */ |
---|
1785 | abuf[i] = *s++; |
---|
1786 | abuf[i] = '\0'; /* Terminate with null */ |
---|
1787 | if (i < aln) s += (aln - i); |
---|
1788 | yy->length = atol(abuf); /* Convert to number */ |
---|
1789 | debug(F111,"gattr length",abuf,(int) yy->length); |
---|
1790 | break; |
---|
1791 | |
---|
1792 | |
---|
1793 | #ifdef CK_PERMS |
---|
1794 | case ',': /* System-dependent protection code */ |
---|
1795 | for (i = 0; (i < aln) && (i < CK_PERMLEN); i++) |
---|
1796 | lprmbuf[i] = *s++; /* Just copy it - decode later */ |
---|
1797 | lprmbuf[i] = '\0'; /* Terminate with null */ |
---|
1798 | if (i < aln) s += (aln - i); |
---|
1799 | if (atlpri) { |
---|
1800 | yy->lprotect.val = (char *)lprmbuf; |
---|
1801 | yy->lprotect.len = i; |
---|
1802 | } else |
---|
1803 | lprmbuf[0] = NUL; |
---|
1804 | break; |
---|
1805 | |
---|
1806 | case '-': /* Generic "world" protection code */ |
---|
1807 | gprmbuf[0] = NUL; /* Just 1 byte by definition */ |
---|
1808 | for (i = 0; i < aln; i++) /* But allow for more... */ |
---|
1809 | if (i == 0) gprmbuf[0] = *s++; |
---|
1810 | gprmbuf[1] = NUL; |
---|
1811 | if (atgpri) { |
---|
1812 | yy->gprotect.val = (char *)gprmbuf; |
---|
1813 | yy->gprotect.len = gprmbuf[0] ? 1 : 0; |
---|
1814 | } else |
---|
1815 | gprmbuf[0] = NUL; |
---|
1816 | break; |
---|
1817 | #endif /* CK_PERMS */ |
---|
1818 | |
---|
1819 | default: /* Unknown attribute */ |
---|
1820 | s += aln; /* Just skip past it */ |
---|
1821 | break; |
---|
1822 | } |
---|
1823 | } |
---|
1824 | |
---|
1825 | /* Check file length now, because we also need to know the file type */ |
---|
1826 | /* in case zchkspa() differentiates text and binary (VMS version does) */ |
---|
1827 | |
---|
1828 | if (atleni) { /* Length attribute enabled? */ |
---|
1829 | if (yy->length > -1L) { /* Length-in-bytes attribute rec'd? */ |
---|
1830 | if (!zchkspa(ff,(yy->length))) { /* Check space */ |
---|
1831 | retcode = -1; /* Not enuf */ |
---|
1832 | *rp++ = '1'; |
---|
1833 | if (!opnerr) tlog(F100," refused: length bytes","",0); |
---|
1834 | } |
---|
1835 | } else if (yy->lengthk > -1L) { /* Length in K attribute rec'd? */ |
---|
1836 | if (!zchkspa(ff,(yy->lengthk * 1024))) { |
---|
1837 | retcode = -1; /* Check space */ |
---|
1838 | *rp++ = '!'; |
---|
1839 | if (!opnerr) tlog(F100," refused: length K","",0); |
---|
1840 | } |
---|
1841 | } |
---|
1842 | } |
---|
1843 | if (yy->length > -1L) { /* Remember the file size */ |
---|
1844 | fsize = yy->length; |
---|
1845 | } else if (yy->lengthk > -1L) { |
---|
1846 | fsize = yy->lengthk * 1024L; |
---|
1847 | } else fsize = -1L; |
---|
1848 | |
---|
1849 | #ifdef DEBUG |
---|
1850 | if (deblog) { |
---|
1851 | sprintf(abuf,"%ld",fsize); /* safe */ |
---|
1852 | debug(F110,"gattr fsize",abuf,0); |
---|
1853 | } |
---|
1854 | #endif /* DEBUG */ |
---|
1855 | |
---|
1856 | if (retcode == 0) rp = rpbuf; /* Null reply string if accepted */ |
---|
1857 | *rp = '\0'; /* End of reply string */ |
---|
1858 | |
---|
1859 | #ifdef CK_RESEND |
---|
1860 | if (d == 'R') { /* Receiving a RESEND? */ |
---|
1861 | debug(F101,"gattr RESEND","",retcode); |
---|
1862 | /* We ignore retcodes because this overrides */ |
---|
1863 | if (binary != XYFT_B) { /* Reject if not binary */ |
---|
1864 | retcode = -1; /* in case type field came */ |
---|
1865 | ckstrncpy(rpbuf,"N+",RPBUFL); /* after the disposition field */ |
---|
1866 | debug(F111,"gattr RESEND not binary",rpbuf,binary); |
---|
1867 | } else { /* Binary mode */ |
---|
1868 | retcode = 0; /* Accept the file */ |
---|
1869 | discard = 0; /* If SET FILE COLLISION DISCARD */ |
---|
1870 | sprintf(rpbuf+2,"%ld",rs_len); /* Reply with length of file */ |
---|
1871 | rpbuf[0] = '1'; /* '1' means Length in Bytes */ |
---|
1872 | rpbuf[1] = tochar((int)strlen(rpbuf+2)); /* Length of length */ |
---|
1873 | debug(F111,"gattr RESEND OK",rpbuf,retcode); |
---|
1874 | } |
---|
1875 | } |
---|
1876 | #endif /* CK_RESEND */ |
---|
1877 | if (retcode == 0 && discard != 0) { /* Do we still have a discard flag? */ |
---|
1878 | ckstrncpy(rpbuf,"N?",RPBUFL); /* Yes, must be filename collision */ |
---|
1879 | retcode = -1; /* "?" = name (reply-only code) */ |
---|
1880 | } |
---|
1881 | yy->reply.val = rpbuf; /* Add it to attribute structure */ |
---|
1882 | yy->reply.len = (int)strlen(rpbuf); |
---|
1883 | if (retcode < 0) { /* If we are rejecting */ |
---|
1884 | discard = 1; /* remember to discard the file */ |
---|
1885 | rejection = rpbuf[1]; /* and use the first reason given. */ |
---|
1886 | if (fncsav != -1) { |
---|
1887 | fncact = fncsav; |
---|
1888 | fncsav = -1; |
---|
1889 | } |
---|
1890 | } |
---|
1891 | debug(F111,"gattr return",rpbuf,retcode); |
---|
1892 | return(retcode); |
---|
1893 | } |
---|
1894 | |
---|
1895 | /* I N I T A T T R -- Initialize file attribute structure */ |
---|
1896 | |
---|
1897 | int |
---|
1898 | initattr(yy) struct zattr *yy; { |
---|
1899 | yy->lengthk = yy->length = -1L; |
---|
1900 | yy->type.val = ""; |
---|
1901 | yy->type.len = 0; |
---|
1902 | yy->date.val = ""; |
---|
1903 | yy->date.len = 0; |
---|
1904 | yy->encoding.val = ""; |
---|
1905 | yy->encoding.len = 0; |
---|
1906 | yy->disp.val = ""; |
---|
1907 | yy->disp.len = 0; |
---|
1908 | yy->systemid.val = ""; |
---|
1909 | yy->systemid.len = 0; |
---|
1910 | yy->sysparam.val = ""; |
---|
1911 | yy->sysparam.len = 0; |
---|
1912 | yy->creator.val = ""; |
---|
1913 | yy->creator.len = 0; |
---|
1914 | yy->account.val = ""; |
---|
1915 | yy->account.len = 0; |
---|
1916 | yy->area.val = ""; |
---|
1917 | yy->area.len = 0; |
---|
1918 | yy->password.val = ""; |
---|
1919 | yy->password.len = 0; |
---|
1920 | yy->blksize = -1L; |
---|
1921 | yy->xaccess.val = ""; |
---|
1922 | yy->xaccess.len = 0; |
---|
1923 | #ifdef CK_PERMS |
---|
1924 | if (!ofperms) ofperms = ""; |
---|
1925 | debug(F110,"initattr ofperms",ofperms,0); |
---|
1926 | yy->lprotect.val = ofperms; |
---|
1927 | yy->lprotect.len = 0 - strlen(ofperms); /* <-- NOTE! */ |
---|
1928 | /* |
---|
1929 | A negative length indicates that we have a permissions string but it has |
---|
1930 | been inherited from a previously existing file rather than picked up |
---|
1931 | from an incoming A-packet. |
---|
1932 | */ |
---|
1933 | #else |
---|
1934 | yy->lprotect.val = ""; |
---|
1935 | yy->lprotect.len = 0; |
---|
1936 | #endif /* CK_PERMS */ |
---|
1937 | yy->gprotect.val = ""; |
---|
1938 | yy->gprotect.len = 0; |
---|
1939 | yy->recfm.val = ""; |
---|
1940 | yy->recfm.len = 0; |
---|
1941 | yy->reply.val = ""; |
---|
1942 | yy->reply.len = 0; |
---|
1943 | #ifdef OS2 |
---|
1944 | yy->longname.len = 0 ; |
---|
1945 | yy->longname.val = "" ; |
---|
1946 | #endif /* OS2 */ |
---|
1947 | return(0); |
---|
1948 | } |
---|
1949 | |
---|
1950 | /* A D E B U -- Write attribute packet info to debug log */ |
---|
1951 | |
---|
1952 | int |
---|
1953 | adebu(f,zz) char *f; struct zattr *zz; { |
---|
1954 | #ifdef DEBUG |
---|
1955 | if (deblog == 0) return(0); |
---|
1956 | debug(F110,"Attributes for incoming file ",f,0); |
---|
1957 | debug(F101," length in K","",(int) zz->lengthk); |
---|
1958 | debug(F111," file type",zz->type.val,zz->type.len); |
---|
1959 | debug(F111," creation date",zz->date.val,zz->date.len); |
---|
1960 | debug(F111," creator",zz->creator.val,zz->creator.len); |
---|
1961 | debug(F111," account",zz->account.val,zz->account.len); |
---|
1962 | debug(F111," area",zz->area.val,zz->area.len); |
---|
1963 | debug(F111," password",zz->password.val,zz->password.len); |
---|
1964 | debug(F101," blksize","",(int) zz->blksize); |
---|
1965 | debug(F111," access",zz->xaccess.val,zz->xaccess.len); |
---|
1966 | debug(F111," encoding",zz->encoding.val,zz->encoding.len); |
---|
1967 | debug(F111," disposition",zz->disp.val,zz->disp.len); |
---|
1968 | debug(F111," lprotection",zz->lprotect.val,zz->lprotect.len); |
---|
1969 | debug(F111," gprotection",zz->gprotect.val,zz->gprotect.len); |
---|
1970 | debug(F111," systemid",zz->systemid.val,zz->systemid.len); |
---|
1971 | debug(F111," recfm",zz->recfm.val,zz->recfm.len); |
---|
1972 | debug(F111," sysparam",zz->sysparam.val,zz->sysparam.len); |
---|
1973 | debug(F101," length","",(int) zz->length); |
---|
1974 | debug(F110," reply",zz->reply.val,0); |
---|
1975 | #endif /* DEBUG */ |
---|
1976 | return(0); |
---|
1977 | } |
---|
1978 | |
---|
1979 | /* O P E N A -- Open a file, with attributes. */ |
---|
1980 | /* |
---|
1981 | This function tries to open a new file to put the arriving data in. The |
---|
1982 | filename is the one in the srvcmd buffer. File collision actions are: |
---|
1983 | OVERWRITE (the existing file is overwritten), RENAME (the new file is |
---|
1984 | renamed), BACKUP (the existing file is renamed), DISCARD (the new file is |
---|
1985 | refused), UPDATE (the incoming file replaces the existing file only if the |
---|
1986 | incoming file has a newer creation date). |
---|
1987 | |
---|
1988 | Returns 0 on failure, nonzero on success. |
---|
1989 | */ |
---|
1990 | extern char *rf_err; |
---|
1991 | |
---|
1992 | int |
---|
1993 | opena(f,zz) char *f; struct zattr *zz; { |
---|
1994 | int x, dispos = 0; |
---|
1995 | static struct filinfo fcb; /* Must be static! */ |
---|
1996 | |
---|
1997 | debug(F110,"opena f",f,0); |
---|
1998 | debug(F101,"opena discard","",discard); |
---|
1999 | |
---|
2000 | adebu(f,zz); /* Write attributes to debug log */ |
---|
2001 | |
---|
2002 | ffc = 0L; /* Init file-character counter */ |
---|
2003 | |
---|
2004 | #ifdef PIPESEND |
---|
2005 | if (pipesend) /* Receiving to a pipe - easy. */ |
---|
2006 | return(openo(f,zz,&fcb)); /* Just open the pipe. */ |
---|
2007 | #endif /* PIPESEND */ |
---|
2008 | |
---|
2009 | /* Receiving to a file - set up file control structure */ |
---|
2010 | |
---|
2011 | fcb.bs = fblksiz; /* Blocksize */ |
---|
2012 | #ifndef NOCSETS |
---|
2013 | fcb.cs = fcharset; /* Character set */ |
---|
2014 | #else |
---|
2015 | fcb.cs = 0; /* Character set */ |
---|
2016 | #endif /* NOCSETS */ |
---|
2017 | fcb.rl = frecl; /* Record Length */ |
---|
2018 | fcb.fmt = frecfm; /* Record Format */ |
---|
2019 | fcb.org = forg; /* Organization */ |
---|
2020 | fcb.cc = fcctrl; /* Carriage control */ |
---|
2021 | fcb.typ = binary; /* Type */ |
---|
2022 | debug(F101,"opena xflg","",xflg); |
---|
2023 | debug(F101,"opena remfile","",remfile); |
---|
2024 | debug(F101,"opena remappd","",remappd); |
---|
2025 | if (xflg && remfile && remappd) /* REMOTE output redirected with >> */ |
---|
2026 | fcb.dsp = XYFZ_A; |
---|
2027 | else |
---|
2028 | fcb.dsp = (fncact == XYFX_A) ? XYFZ_A : XYFZ_N; /* Disposition */ |
---|
2029 | debug(F101,"opena disp","",fcb.dsp); |
---|
2030 | fcb.os_specific = ""; /* OS-specific info */ |
---|
2031 | #ifdef CK_LABELED |
---|
2032 | fcb.lblopts = lf_opts; /* Labeled file options */ |
---|
2033 | #else |
---|
2034 | fcb.lblopts = 0; |
---|
2035 | #endif /* CK_LABELED */ |
---|
2036 | |
---|
2037 | if (zz->disp.len > 0) { /* Incoming file has a disposition? */ |
---|
2038 | debug(F111,"open disposition",zz->disp.val,zz->disp.len); |
---|
2039 | dispos = (int) (*(zz->disp.val)); |
---|
2040 | } |
---|
2041 | if (!dispos && xflg && remfile && remappd) /* REMOTE redirect append ? */ |
---|
2042 | dispos = fcb.dsp; |
---|
2043 | |
---|
2044 | debug(F101,"opena dispos","",dispos); |
---|
2045 | |
---|
2046 | if (!dispos) { /* No special disposition? */ |
---|
2047 | if (fncact == XYFX_B && ofn1x && ofn2) { /* File collision = BACKUP? */ |
---|
2048 | if (zrename(ofn1,ofn2) < 0) { /* Rename existing file. */ |
---|
2049 | debug(F110,"opena rename fails",ofn1,0); |
---|
2050 | rf_err = "Can't create backup file"; |
---|
2051 | return(0); |
---|
2052 | } else debug(F110,"opena rename ok",ofn2,0); |
---|
2053 | } |
---|
2054 | } else if (dispos == 'R') { /* Receiving a RESEND */ |
---|
2055 | debug(F101,"opena remote len","",zz->length); |
---|
2056 | debug(F101,"opena local len","",rs_len); |
---|
2057 | #ifdef COMMENT |
---|
2058 | if (fncact == XYFX_R) /* and file collision = RENAME */ |
---|
2059 | if (ofn1x) |
---|
2060 | #endif /* COMMENT */ |
---|
2061 | if (ofn1[0]) |
---|
2062 | f = ofn1; /* use original name. */ |
---|
2063 | if (fncact == XYFX_R) /* if file collision is RENAME */ |
---|
2064 | ckstrncpy(filnam,ofn1,CKMAXPATH+1); /* restore the real name */ |
---|
2065 | xxscreen(SCR_AN,0,0L,f); /* update name on screen */ |
---|
2066 | if (zz->length == rs_len) /* Local and remote lengths equal? */ |
---|
2067 | return(-17); /* Secret code */ |
---|
2068 | } |
---|
2069 | debug(F111,"opena [file]=mode: ",f,fcb.dsp); |
---|
2070 | if (x = openo(f,zz,&fcb)) { /* Try to open the file. */ |
---|
2071 | #ifdef pdp11 |
---|
2072 | tlog(F110," local name:",f,0L); /* OK, open, record local name. */ |
---|
2073 | makestr(&prfspec,f); /* New preliminary name */ |
---|
2074 | #else |
---|
2075 | #ifndef ZFNQFP |
---|
2076 | tlog(F110," local name:",f,0L); |
---|
2077 | makestr(&prfspec,f); |
---|
2078 | #else |
---|
2079 | { /* Log full local pathname */ |
---|
2080 | char *p = NULL, *q = f; |
---|
2081 | if ((p = malloc(CKMAXPATH+1))) |
---|
2082 | if (zfnqfp(filnam, CKMAXPATH, p)) |
---|
2083 | q = p; |
---|
2084 | tlog(F110," local name:",q,0L); |
---|
2085 | makestr(&prfspec,q); |
---|
2086 | if (p) free(p); |
---|
2087 | } |
---|
2088 | #endif /* ZFNQFP */ |
---|
2089 | #endif /* pdp11 */ |
---|
2090 | |
---|
2091 | if (binary) { /* Log file mode in transaction log */ |
---|
2092 | tlog(F101," mode: binary","",(long) binary); |
---|
2093 | } else { /* If text mode, check character set */ |
---|
2094 | tlog(F100," mode: text","",0L); |
---|
2095 | #ifndef NOCSETS |
---|
2096 | if (xfrxla) { |
---|
2097 | if (fcharset > -1 && fcharset <= MAXFCSETS) |
---|
2098 | tlog(F110," file character-set:",fcsinfo[fcharset].name,0L); |
---|
2099 | if (tcharset > -1 && tcharset <= MAXTCSETS) |
---|
2100 | tlog(F110," xfer character-set:",tcsinfo[tcharset].name,0L); |
---|
2101 | } else { |
---|
2102 | tlog(F110," character-set:","transparent",0L); |
---|
2103 | } |
---|
2104 | #endif /* NOCSETS */ |
---|
2105 | debug(F111,"opena charset",zz->encoding.val,zz->encoding.len); |
---|
2106 | } |
---|
2107 | debug(F101,"opena binary","",binary); |
---|
2108 | |
---|
2109 | #ifdef COMMENT |
---|
2110 | if (fsize > -1L) |
---|
2111 | #endif /* COMMENT */ |
---|
2112 | xxscreen(SCR_FS,0,fsize,""); |
---|
2113 | |
---|
2114 | #ifdef datageneral |
---|
2115 | /* |
---|
2116 | Need to turn on multi-tasking console interrupt task here, since multiple |
---|
2117 | files may be received (huh?) ... |
---|
2118 | */ |
---|
2119 | if ((local) && (!quiet)) /* Only do this if local & not quiet */ |
---|
2120 | consta_mt(); /* Start the async read task */ |
---|
2121 | #endif /* datageneral */ |
---|
2122 | |
---|
2123 | } else { /* Did not open file OK. */ |
---|
2124 | |
---|
2125 | rf_err = ck_errstr(); /* Get system error message */ |
---|
2126 | if (*rf_err) |
---|
2127 | xxscreen(SCR_EM,0,0l,rf_err); |
---|
2128 | else |
---|
2129 | xxscreen(SCR_EM,0,0l,"Can't open output file"); |
---|
2130 | tlog(F110,"Failure to open",f,0L); |
---|
2131 | tlog(F110,"Error:",rf_err,0L); |
---|
2132 | debug(F110,"opena error",rf_err,0); |
---|
2133 | } |
---|
2134 | return(x); /* Pass on return code from openo */ |
---|
2135 | } |
---|
2136 | |
---|
2137 | /* O P E N C -- Open a command (in place of a file) for output */ |
---|
2138 | |
---|
2139 | int |
---|
2140 | openc(n,s) int n; char * s; { |
---|
2141 | int x; |
---|
2142 | #ifndef NOPUSH |
---|
2143 | x = zxcmd(n,s); |
---|
2144 | #else |
---|
2145 | x = 0; |
---|
2146 | #endif /* NOPUSH */ |
---|
2147 | debug(F111,"openc zxcmd",s,x); |
---|
2148 | o_isopen = (x > 0) ? 1 : 0; |
---|
2149 | return(x); |
---|
2150 | } |
---|
2151 | |
---|
2152 | /* C A N N E D -- Check if current file transfer cancelled */ |
---|
2153 | |
---|
2154 | int |
---|
2155 | canned(buf) CHAR *buf; { |
---|
2156 | extern int interrupted; |
---|
2157 | if (*buf == 'X') cxseen = 1; |
---|
2158 | if (*buf == 'Z') czseen = 1; |
---|
2159 | if (czseen || cxseen) |
---|
2160 | interrupted = 1; |
---|
2161 | debug(F101,"canned: cxseen","",cxseen); |
---|
2162 | debug(F101," czseen","",czseen); |
---|
2163 | return((czseen || cxseen) ? 1 : 0); |
---|
2164 | } |
---|
2165 | |
---|
2166 | |
---|
2167 | /* O P E N I -- Open an existing file for input */ |
---|
2168 | |
---|
2169 | int |
---|
2170 | openi(name) char *name; { |
---|
2171 | #ifndef NOSERVER |
---|
2172 | extern int fromgetpath; |
---|
2173 | #endif /* NOSERVER */ |
---|
2174 | int x, filno; |
---|
2175 | char *name2; |
---|
2176 | extern CHAR *epktmsg; |
---|
2177 | |
---|
2178 | epktmsg[0] = NUL; /* Initialize error message */ |
---|
2179 | if (memstr || sndarray) { /* Just return if "file" is memory. */ |
---|
2180 | i_isopen = 1; |
---|
2181 | return(1); |
---|
2182 | } |
---|
2183 | debug(F110,"openi name",name,0); |
---|
2184 | debug(F101,"openi sndsrc","",sndsrc); |
---|
2185 | |
---|
2186 | filno = (sndsrc == 0) ? ZSTDIO : ZIFILE; /* ... */ |
---|
2187 | debug(F101,"openi file number","",filno); |
---|
2188 | |
---|
2189 | #ifndef NOSERVER |
---|
2190 | /* If I'm a server and CWD is disabled and name is not from GET-PATH... */ |
---|
2191 | |
---|
2192 | if (server && !en_cwd && !fromgetpath) { |
---|
2193 | zstrip(name,&name2); |
---|
2194 | if ( /* ... check if pathname included. */ |
---|
2195 | #ifdef VMS |
---|
2196 | zchkpath(name) |
---|
2197 | #else |
---|
2198 | strcmp(name,name2) |
---|
2199 | #endif /* VMS */ |
---|
2200 | ) { |
---|
2201 | tlog(F110,name,"access denied",0L); |
---|
2202 | debug(F110,"openi CD disabled",name,0); |
---|
2203 | ckstrncpy((char *)epktmsg,"Access denied",PKTMSGLEN); |
---|
2204 | return(0); |
---|
2205 | } else name = name2; |
---|
2206 | } |
---|
2207 | #endif /* NOSERVER */ |
---|
2208 | |
---|
2209 | #ifdef PIPESEND |
---|
2210 | debug(F101,"openi pipesend","",pipesend); |
---|
2211 | if (pipesend) { |
---|
2212 | int x; |
---|
2213 | #ifndef NOPUSH |
---|
2214 | x = zxcmd(ZIFILE,name); |
---|
2215 | #else |
---|
2216 | x = 0; |
---|
2217 | #endif /* NOPUSH */ |
---|
2218 | i_isopen = (x > 0) ? 1 : 0; |
---|
2219 | if (!i_isopen) |
---|
2220 | ckstrncpy((char *)epktmsg,"Command or pipe failure",PKTMSGLEN); |
---|
2221 | debug(F111,"openi pipesend zxcmd",name,x); |
---|
2222 | return(i_isopen); |
---|
2223 | } |
---|
2224 | #endif /* PIPESEND */ |
---|
2225 | |
---|
2226 | #ifdef CALIBRATE |
---|
2227 | if (calibrate) { |
---|
2228 | i_isopen = 1; |
---|
2229 | return(1); |
---|
2230 | } |
---|
2231 | #endif /* CALIBRATE */ |
---|
2232 | |
---|
2233 | x = zopeni(filno,name); /* Otherwise, try to open it. */ |
---|
2234 | debug(F111,"openi zopeni 1",name,x); |
---|
2235 | if (x) { |
---|
2236 | i_isopen = 1; |
---|
2237 | return(1); |
---|
2238 | } else { /* If not found, */ |
---|
2239 | char xname[CKMAXPATH]; /* convert the name */ |
---|
2240 | #ifdef NZLTOR |
---|
2241 | nzrtol(name,xname,fncnv,fnrpath,CKMAXPATH); |
---|
2242 | #else |
---|
2243 | zrtol(name,xname); /* to local form and then */ |
---|
2244 | #endif /* NZLTOR */ |
---|
2245 | x = zopeni(filno,xname); /* try opening it again. */ |
---|
2246 | debug(F111,"openi zopeni 2",xname,x); |
---|
2247 | if (x) { |
---|
2248 | i_isopen = 1; |
---|
2249 | return(1); /* It worked. */ |
---|
2250 | } else { |
---|
2251 | char * s; |
---|
2252 | s = ck_errstr(); |
---|
2253 | if (s) if (!s) s = NULL; |
---|
2254 | if (!s) s = "Can't open file"; |
---|
2255 | ckstrncpy((char *)epktmsg,s,PKTMSGLEN); |
---|
2256 | tlog(F110,xname,s,0L); |
---|
2257 | debug(F110,"openi failed",xname,0); |
---|
2258 | debug(F110,"openi message",s,0); |
---|
2259 | i_isopen = 0; |
---|
2260 | return(0); |
---|
2261 | } |
---|
2262 | } |
---|
2263 | } |
---|
2264 | |
---|
2265 | /* O P E N O -- Open a new file for output. */ |
---|
2266 | |
---|
2267 | int |
---|
2268 | openo(name,zz,fcb) char *name; struct zattr *zz; struct filinfo *fcb; { |
---|
2269 | char *name2; |
---|
2270 | #ifdef DTILDE |
---|
2271 | char *dirp; |
---|
2272 | #endif /* DTILDE */ |
---|
2273 | |
---|
2274 | int channel, x; |
---|
2275 | |
---|
2276 | if (stdouf) { /* Receiving to stdout? */ |
---|
2277 | x = zopeno(ZSTDIO,"",zz,NULL); |
---|
2278 | o_isopen = (x > 0); |
---|
2279 | debug(F101,"openo stdouf zopeno","",x); |
---|
2280 | return(x); |
---|
2281 | } |
---|
2282 | debug(F110,"openo: name",name,0); |
---|
2283 | |
---|
2284 | if (cxseen || czseen || discard) { /* If interrupted, get out before */ |
---|
2285 | debug(F100," open cancelled","",0); /* destroying existing file. */ |
---|
2286 | return(1); /* Pretend to succeed. */ |
---|
2287 | } |
---|
2288 | channel = ZOFILE; /* SET DESTINATION DISK or PRINTER */ |
---|
2289 | |
---|
2290 | #ifdef PIPESEND |
---|
2291 | debug(F101,"openo pipesend","",pipesend); |
---|
2292 | if (pipesend) { |
---|
2293 | int x; |
---|
2294 | #ifndef NOPUSH |
---|
2295 | x = zxcmd(ZOFILE,(char *)srvcmd); |
---|
2296 | #else |
---|
2297 | x = 0; |
---|
2298 | #endif /* NOPUSH */ |
---|
2299 | o_isopen = x > 0; |
---|
2300 | debug(F101,"openo zxcmd","",x); |
---|
2301 | return(x); |
---|
2302 | } |
---|
2303 | #endif /* PIPESEND */ |
---|
2304 | |
---|
2305 | if (dest == DEST_S) { /* SET DEST SCREEN... */ |
---|
2306 | channel = ZCTERM; |
---|
2307 | fcb = NULL; |
---|
2308 | } |
---|
2309 | #ifdef DTILDE |
---|
2310 | if (*name == '~') { |
---|
2311 | dirp = tilde_expand(name); |
---|
2312 | if (*dirp) ckstrncpy(name,dirp,CKMAXPATH+1); |
---|
2313 | } |
---|
2314 | #endif /* DTILDE */ |
---|
2315 | if (server && !en_cwd) { /* If running as server */ |
---|
2316 | zstrip(name,&name2); /* and CWD is disabled, */ |
---|
2317 | if (strcmp(name,name2)) { /* check if pathname was included. */ |
---|
2318 | tlog(F110,name,"authorization failure",0L); |
---|
2319 | debug(F110,"openo CD disabled",name,0); |
---|
2320 | return(0); |
---|
2321 | } else name = name2; |
---|
2322 | } |
---|
2323 | if (zopeno(channel,name,zz,fcb) <= 0) { /* Try to open the file */ |
---|
2324 | o_isopen = 0; |
---|
2325 | debug(F110,"openo failed",name,0); |
---|
2326 | /* tlog(F110,"Failure to open",name,0L); */ |
---|
2327 | return(0); |
---|
2328 | } else { |
---|
2329 | o_isopen = 1; |
---|
2330 | debug(F110,"openo ok, name",name,0); |
---|
2331 | return(1); |
---|
2332 | } |
---|
2333 | } |
---|
2334 | |
---|
2335 | /* O P E N T -- Open the terminal for output, in place of a file */ |
---|
2336 | |
---|
2337 | int |
---|
2338 | opent(zz) struct zattr *zz; { |
---|
2339 | int x; |
---|
2340 | ffc = tfc = 0L; |
---|
2341 | x = zopeno(ZCTERM,"",zz,NULL); |
---|
2342 | debug(F101,"opent zopeno","",x); |
---|
2343 | if (x >= 0) { |
---|
2344 | o_isopen = 1; |
---|
2345 | binary = XYFT_T; |
---|
2346 | } else |
---|
2347 | return(0); |
---|
2348 | return(x); |
---|
2349 | } |
---|
2350 | |
---|
2351 | /* O P E N X -- Open nothing (incoming file to be accepted but ignored) */ |
---|
2352 | |
---|
2353 | int |
---|
2354 | ckopenx(zz) struct zattr *zz; { |
---|
2355 | ffc = tfc = 0L; /* Reset counters */ |
---|
2356 | o_isopen = 1; |
---|
2357 | debug(F101,"ckopenx fsize","",fsize); |
---|
2358 | xxscreen(SCR_FS,0,fsize,""); /* Let screen display know the size */ |
---|
2359 | return(1); |
---|
2360 | } |
---|
2361 | |
---|
2362 | /* C L S I F -- Close the current input file. */ |
---|
2363 | |
---|
2364 | int |
---|
2365 | clsif() { |
---|
2366 | extern int xferstat, success; |
---|
2367 | int x = 0; |
---|
2368 | |
---|
2369 | fcps(); /* Calculate CPS quickly */ |
---|
2370 | |
---|
2371 | #ifdef datageneral |
---|
2372 | if ((local) && (!quiet)) /* Only do this if local & not quiet */ |
---|
2373 | if (nfils < 1) /* More files to send ... leave it on! */ |
---|
2374 | connoi_mt(); |
---|
2375 | #endif /* datageneral */ |
---|
2376 | |
---|
2377 | debug(F101,"clsif i_isopen","",i_isopen); |
---|
2378 | if (i_isopen) { /* If input file is open... */ |
---|
2379 | if (memstr) { /* If input was memory string, */ |
---|
2380 | memstr = 0; /* indicate no more. */ |
---|
2381 | } else { |
---|
2382 | x = zclose(ZIFILE); /* else close input file. */ |
---|
2383 | } |
---|
2384 | #ifdef DEBUG |
---|
2385 | if (deblog) { |
---|
2386 | debug(F101,"clsif zclose","",x); |
---|
2387 | debug(F101,"clsif success","",success); |
---|
2388 | debug(F101,"clsif xferstat","",xferstat); |
---|
2389 | debug(F101,"clsif fsize","",fsize); |
---|
2390 | debug(F101,"clsif ffc","",ffc); |
---|
2391 | debug(F101,"clsif cxseen","",cxseen); |
---|
2392 | debug(F101,"clsif czseen","",czseen); |
---|
2393 | debug(F101,"clsif discard","",czseen); |
---|
2394 | } |
---|
2395 | #endif /* DEBUG */ |
---|
2396 | if ((cxseen || czseen) && !epktsent) { /* If interrupted */ |
---|
2397 | xxscreen(SCR_ST,ST_INT,0l,""); /* say so */ |
---|
2398 | #ifdef TLOG |
---|
2399 | if (tralog && !tlogfmt) |
---|
2400 | doxlog(what,psfspec,fsize,binary,1,"Interrupted"); |
---|
2401 | #endif /* TLOG */ |
---|
2402 | } else if (discard && !epktsent) { /* If I'm refusing */ |
---|
2403 | xxscreen(SCR_ST,ST_REFU,0l,refused); /* say why */ |
---|
2404 | #ifdef TLOG |
---|
2405 | if (tralog && !tlogfmt) { |
---|
2406 | char buf[128]; |
---|
2407 | ckmakmsg(buf,128,"Refused: ",refused,NULL,NULL); |
---|
2408 | doxlog(what,psfspec,fsize,binary,1,buf); |
---|
2409 | } |
---|
2410 | #endif /* TLOG */ |
---|
2411 | } else if (!epktrcvd && !epktsent && !cxseen && !czseen) { |
---|
2412 | long zz; |
---|
2413 | zz = ffc; |
---|
2414 | #ifdef CK_RESEND |
---|
2415 | if (sendmode == SM_RESEND || sendmode == SM_PSEND) |
---|
2416 | zz += sendstart; |
---|
2417 | #endif /* CK_RESEND */ |
---|
2418 | debug(F101,"clsif fstats","",zz); |
---|
2419 | fstats(); /* Update statistics */ |
---|
2420 | if ( /* Was the whole file sent? */ |
---|
2421 | #ifdef VMS |
---|
2422 | 0 /* Not a reliable check in VMS */ |
---|
2423 | #else |
---|
2424 | #ifdef STRATUS |
---|
2425 | 0 /* Probably not for VOS either */ |
---|
2426 | #else |
---|
2427 | zz < fsize |
---|
2428 | #ifdef CK_CTRLZ |
---|
2429 | && ((eofmethod != XYEOF_Z && !binary) || binary) |
---|
2430 | #endif /* CK_CTRLZ */ |
---|
2431 | #endif /* STRATUS */ |
---|
2432 | #endif /* VMS */ |
---|
2433 | ) { |
---|
2434 | xxscreen(SCR_ST,ST_INT,0l,""); |
---|
2435 | #ifdef TLOG |
---|
2436 | if (tralog && !tlogfmt) |
---|
2437 | doxlog(what,psfspec,fsize,binary,1,"Incomplete"); |
---|
2438 | #endif /* TLOG */ |
---|
2439 | } else { |
---|
2440 | #ifdef COMMENT |
---|
2441 | /* Not yet -- we don't have confirmation from the receiver */ |
---|
2442 | xxscreen(SCR_ST,ST_OK,0l,""); |
---|
2443 | #endif /* COMMENT */ |
---|
2444 | #ifdef TLOG |
---|
2445 | if (tralog && !tlogfmt) |
---|
2446 | doxlog(what,psfspec,fsize,binary,0,""); |
---|
2447 | #endif /* TLOG */ |
---|
2448 | } |
---|
2449 | } |
---|
2450 | } |
---|
2451 | i_isopen = 0; |
---|
2452 | hcflg = 0; /* Reset flags */ |
---|
2453 | sendstart = 0L; /* Don't do this again! */ |
---|
2454 | #ifdef COMMENT |
---|
2455 | /* |
---|
2456 | This prevents a subsequent call to clsof() from deleting the file |
---|
2457 | when given the discard flag. |
---|
2458 | */ |
---|
2459 | *filnam = '\0'; /* and current file name */ |
---|
2460 | #endif /* COMMENT */ |
---|
2461 | return(x); |
---|
2462 | } |
---|
2463 | |
---|
2464 | |
---|
2465 | /* C L S O F -- Close an output file. */ |
---|
2466 | |
---|
2467 | /* Call with disp != 0 if file is to be discarded. */ |
---|
2468 | /* Returns -1 upon failure to close, 0 or greater on success. */ |
---|
2469 | |
---|
2470 | int |
---|
2471 | clsof(disp) int disp; { |
---|
2472 | int x = 0; |
---|
2473 | extern int success; |
---|
2474 | |
---|
2475 | fcps(); /* Calculate CPS quickly */ |
---|
2476 | |
---|
2477 | debug(F101,"clsof disp","",disp); |
---|
2478 | debug(F101,"clsof cxseen","",cxseen); |
---|
2479 | debug(F101,"clsof success","",success); |
---|
2480 | |
---|
2481 | debug(F101,"clsof o_isopen","",o_isopen); |
---|
2482 | if (fncsav != -1) { /* Saved file collision action... */ |
---|
2483 | fncact = fncsav; /* Restore it. */ |
---|
2484 | fncsav = -1; /* Unsave it. */ |
---|
2485 | } |
---|
2486 | #ifdef datageneral |
---|
2487 | if ((local) && (!quiet)) /* Only do this if local & not quiet */ |
---|
2488 | connoi_mt(); |
---|
2489 | #endif /* datageneral */ |
---|
2490 | if (o_isopen && !calibrate) { |
---|
2491 | if ((x = zclose(ZOFILE)) < 0) { /* Try to close the file */ |
---|
2492 | tlog(F100,"Failure to close",filnam,0L); |
---|
2493 | xxscreen(SCR_ST,ST_ERR,0l,"Can't close file"); |
---|
2494 | #ifdef TLOG |
---|
2495 | if (tralog && !tlogfmt) |
---|
2496 | doxlog(what,prfspec,fsize,binary,1,"Can't close file"); |
---|
2497 | #endif /* TLOG */ |
---|
2498 | } else if (disp) { /* Interrupted or refused */ |
---|
2499 | if (keep == 0 || /* If not keeping incomplete files */ |
---|
2500 | (keep == SET_AUTO && binary == XYFT_T) |
---|
2501 | ) { |
---|
2502 | if (*filnam && (what & W_RECV)) /* AND we're receiving */ |
---|
2503 | zdelet(filnam); /* ONLY THEN, delete it */ |
---|
2504 | if (what & W_KERMIT) { |
---|
2505 | debug(F100,"clsof incomplete discarded","",0); |
---|
2506 | tlog(F100," incomplete: discarded","",0L); |
---|
2507 | if (!epktrcvd && !epktsent) { |
---|
2508 | xxscreen(SCR_ST,ST_DISC,0l,""); |
---|
2509 | #ifdef TLOG |
---|
2510 | if (tralog && !tlogfmt) |
---|
2511 | doxlog(what,prfspec,fsize,binary,1,"Discarded"); |
---|
2512 | #endif /* TLOG */ |
---|
2513 | } |
---|
2514 | } |
---|
2515 | } else { /* Keep incomplete copy */ |
---|
2516 | debug(F100,"clsof fstats 1","",0); |
---|
2517 | fstats(); |
---|
2518 | if (!discard) { /* Unless discarding for other reason... */ |
---|
2519 | if (what & W_KERMIT) { |
---|
2520 | debug(F100,"closf incomplete kept","",0); |
---|
2521 | tlog(F100," incomplete: kept","",0L); |
---|
2522 | } |
---|
2523 | } |
---|
2524 | if (what & W_KERMIT) { |
---|
2525 | if (!epktrcvd && !epktsent) { |
---|
2526 | xxscreen(SCR_ST,ST_INC,0l,""); |
---|
2527 | #ifdef TLOG |
---|
2528 | if (tralog && !tlogfmt) |
---|
2529 | doxlog(what,prfspec,fsize,binary,1,"Incomplete"); |
---|
2530 | #endif /* TLOG */ |
---|
2531 | } |
---|
2532 | } |
---|
2533 | } |
---|
2534 | } |
---|
2535 | } |
---|
2536 | if (o_isopen && x > -1 && !disp) { |
---|
2537 | debug(F110,"clsof OK",rfspec,0); |
---|
2538 | makestr(&rfspec,prfspec); |
---|
2539 | makestr(&rrfspec,prrfspec); |
---|
2540 | fstats(); |
---|
2541 | if (!epktrcvd && !epktsent && !cxseen && !czseen) { |
---|
2542 | xxscreen(SCR_ST,ST_OK,0L,""); |
---|
2543 | #ifdef TLOG |
---|
2544 | if (tralog && !tlogfmt) |
---|
2545 | doxlog(what,rfspec,fsize,binary,0,""); |
---|
2546 | #endif /* TLOG */ |
---|
2547 | } |
---|
2548 | } |
---|
2549 | rs_len = 0; |
---|
2550 | o_isopen = 0; /* The file is not open any more. */ |
---|
2551 | cxseen = 0; /* Reset per-file interruption flag */ |
---|
2552 | return(x); /* Send back zclose() return code. */ |
---|
2553 | } |
---|
2554 | |
---|
2555 | #ifdef SUNOS4S5 |
---|
2556 | tolower(c) char c; { return((c)-'A'+'a'); } |
---|
2557 | toupper(c) char c; { return((c)-'a'+'A'); } |
---|
2558 | #endif /* SUNOS4S5 */ |
---|
2559 | #endif /* NOXFER */ |
---|