1
2 /*
3 * xa_input.c
4 *
5 * Copyright (C) 1996,1998,1999 by Mark Podlipec.
6 * All rights reserved.
7 *
8 * This software may be freely used, copied and redistributed without
9 * fee for non-commerical purposes provided that this copyright
10 * notice is preserved intact on all copies.
11 *
12 * There is no warranty or other guarantee of fitness of this software.
13 * It is provided solely "as is". The author disclaims all
14 * responsibility and liability with respect to this software's usage
15 * or its effect upon hardware or computer systems.
16 *
17 */
18 /* REVISIONS ***********
19 * 17Mar96 changed bcopy to be memcpy because many machines don't
20 * support bcopy.
21 * 17May96 Since VMS compilers are brain-dead :^) well okay, they're
22 * just case insensitive. I needed to rename xa_ftp_open_file
23 * to be xaftp_open_file to avoid conflict with xa_FTP_Open_File.
24 * Also, redid the include files for VMS.
25 */
26
27 #include "xanim.h"
28
29 #include <errno.h>
30
31 #ifdef VMS
32 #include <types.h>
33 #include <socket.h>
34 #include <string.h>
35 #include <netdb.h>
36 #include <stdlib.h>
37 #include <in.h>
38 #include <unixio.h>
39 #include <stdlib.h>
40 #else
41 #include <sys/types.h>
42 #include <sys/socket.h>
43 #include <string.h>
44 #include <netdb.h>
45 #include <stdlib.h>
46 #include <netinet/in.h>
47 #endif
48
49
50 xaULONG XA_Buff_Read_U8();
51 xaULONG XA_Buff_Read_LSB_U16();
52 xaULONG XA_Buff_Read_MSB_U16();
53 xaULONG XA_Buff_Read_LSB_U32();
54 xaULONG XA_Buff_Read_MSB_U32();
55 xaULONG XA_Buff_Read_Block();
56
57 void XA_Set_EOF();
58
59 xaULONG XA_STDIN_Open_File();
60 xaULONG XA_STDIN_Close_File();
61 xaULONG XA_STDIN_Read_U8();
62 xaULONG XA_STDIN_Read_LSB_U16();
63 xaULONG XA_STDIN_Read_MSB_U16();
64 xaULONG XA_STDIN_Read_LSB_U32();
65 xaULONG XA_STDIN_Read_MSB_U32();
66 xaLONG XA_STDIN_Read_Block();
67 xaLONG XA_STDIN_EOF();
68 xaLONG XA_STDIN_seek();
69 xaLONG XA_STDIN_ftell();
70
71 xaULONG XA_FILE_Open_File();
72 xaULONG XA_FILE_Close_File();
73 xaULONG XA_FILE_Read_U8();
74 xaULONG XA_FILE_Read_LSB_U16();
75 xaULONG XA_FILE_Read_MSB_U16();
76 xaULONG XA_FILE_Read_LSB_U32();
77 xaULONG XA_FILE_Read_MSB_U32();
78 xaLONG XA_FILE_Read_Block();
79 xaLONG XA_FILE_EOF();
80 xaLONG XA_FILE_seek();
81 xaLONG XA_FILE_ftell();
82
83 xaULONG XA_Mem_Open_Init();
84 xaULONG XA_MEM_Open_File();
85 xaULONG XA_MEM_Close_File();
86 xaULONG XA_MEM_Read_U8();
87 xaULONG XA_MEM_Read_LSB_U16();
88 xaULONG XA_MEM_Read_MSB_U16();
89 xaULONG XA_MEM_Read_LSB_U32();
90 xaULONG XA_MEM_Read_MSB_U32();
91 xaLONG XA_MEM_Read_Block();
92 xaLONG XA_MEM_EOF();
93 xaLONG XA_MEM_seek();
94 xaLONG XA_MEM_ftell();
95
96 xaULONG XA_FTP_Open_File();
97 xaULONG XA_FTP_Close_File();
98 xaULONG XA_FTP_Read_U8();
99 xaULONG XA_FTP_Read_LSB_U16();
100 xaULONG XA_FTP_Read_MSB_U16();
101 xaULONG XA_FTP_Read_LSB_U32();
102 xaULONG XA_FTP_Read_MSB_U32();
103 xaLONG XA_FTP_Read_Block();
104 xaLONG XA_FTP_EOF();
105 xaLONG XA_FTP_seek();
106 xaLONG XA_FTP_ftell();
107 xaLONG xa_ftp_get_msg();
108 xaLONG xa_ftp_send_cmd();
109 xaLONG xaftp_open_file();
110
111 xaULONG XA_File_Split();
112
113 #define BUFF_FILL_SIZE 0x20
114
XA_Alloc_Input_Methods(anim_hdr)115 xaULONG XA_Alloc_Input_Methods(anim_hdr)
116 XA_ANIM_HDR *anim_hdr;
117 { XA_INPUT *xin;
118
119 /* allocate */
120 if (anim_hdr->xin == 0)
121 {
122 xin = (XA_INPUT *)malloc(sizeof(XA_INPUT));
123 if (xin == 0) TheEnd1("XA_INPUT: malloc err\n");
124 anim_hdr->xin = xin;
125 xin->buf = 0;
126 }
127 return(xaTRUE);
128 }
129
XA_Setup_Input_Methods(xin,file)130 xaULONG XA_Setup_Input_Methods(xin,file)
131 XA_INPUT *xin;
132 char *file;
133 {
134 xin->file = file;
135
136 if (xin->buf == 0)
137 {
138 xin->buf_size = BUFF_FILL_SIZE;
139 xin->buf = (xaUBYTE *)malloc(xin->buf_size);
140 if (xin->buf == 0) TheEnd1("stdin buf malloc err");
141 }
142 xin->buf_ptr = xin->buf;
143 xin->buf_cnt = 0;
144 xin->fpos = 0;
145 xin->eof = 0;
146 xin->load_flag = XA_IN_LOAD_MEM; /* default for now */
147
148 if ( strncmp(file,"ftp://",6) == 0)
149 { xin->type_flag = XA_IN_TYPE_SEQUENTIAL;
150 xin->Open_File = XA_FTP_Open_File;
151 xin->Close_File = XA_FTP_Close_File;
152 xin->Read_U8 = XA_FTP_Read_U8;
153 xin->Read_LSB_U16 = XA_FTP_Read_LSB_U16;
154 xin->Read_MSB_U16 = XA_FTP_Read_MSB_U16;
155 xin->Read_LSB_U32 = XA_FTP_Read_LSB_U32;
156 xin->Read_MSB_U32 = XA_FTP_Read_MSB_U32;
157 xin->Read_Block = XA_FTP_Read_Block;
158 xin->Set_EOF = XA_Set_EOF;
159 xin->At_EOF = XA_FTP_EOF;
160 xin->Seek_FPos = XA_FTP_seek;
161 xin->Get_FPos = XA_FTP_ftell;
162 return(xaTRUE);
163 }
164 else if ( strcmp(file,"-") == 0)
165 { xin->type_flag = XA_IN_TYPE_SEQUENTIAL;
166 xin->Open_File = XA_STDIN_Open_File;
167 xin->Close_File = XA_STDIN_Close_File;
168 xin->Read_U8 = XA_STDIN_Read_U8;
169 xin->Read_LSB_U16 = XA_STDIN_Read_LSB_U16;
170 xin->Read_MSB_U16 = XA_STDIN_Read_MSB_U16;
171 xin->Read_LSB_U32 = XA_STDIN_Read_LSB_U32;
172 xin->Read_MSB_U32 = XA_STDIN_Read_MSB_U32;
173 xin->Read_Block = XA_STDIN_Read_Block;
174 xin->Set_EOF = XA_Set_EOF;
175 xin->At_EOF = XA_STDIN_EOF;
176 xin->Seek_FPos = XA_STDIN_seek;
177 xin->Get_FPos = XA_STDIN_ftell;
178 return(xaTRUE);
179 }
180 else
181 { xin->type_flag = XA_IN_TYPE_RANDOM;
182 xin->Open_File = XA_FILE_Open_File;
183 xin->Close_File = XA_FILE_Close_File;
184 xin->Read_U8 = XA_FILE_Read_U8;
185 xin->Read_LSB_U16 = XA_FILE_Read_LSB_U16;
186 xin->Read_MSB_U16 = XA_FILE_Read_MSB_U16;
187 xin->Read_LSB_U32 = XA_FILE_Read_LSB_U32;
188 xin->Read_MSB_U32 = XA_FILE_Read_MSB_U32;
189 xin->Read_Block = XA_FILE_Read_Block;
190 xin->Set_EOF = XA_Set_EOF;
191 xin->At_EOF = XA_FILE_EOF;
192 xin->Seek_FPos = XA_FILE_seek;
193 xin->Get_FPos = XA_FILE_ftell;
194 return(xaTRUE);
195 }
196 }
197
XA_Mem_Open_Init(xin,buf,buf_sz)198 xaULONG XA_Mem_Open_Init(xin,buf,buf_sz)
199 XA_INPUT *xin;
200 unsigned char *buf;
201 xaULONG buf_sz;
202 {
203 xin->file = "mem";
204 xin->buf = buf;
205 xin->buf_size = buf_sz;
206 xin->buf_ptr = xin->buf;
207 xin->buf_cnt = xin->buf_size;
208 xin->fpos = 0;
209 xin->eof = 0;
210 xin->load_flag = XA_IN_LOAD_MEM; /* default for now */
211 xin->type_flag = XA_IN_TYPE_RANDOM;
212 xin->Open_File = XA_MEM_Open_File;
213 xin->Close_File = XA_MEM_Close_File;
214 xin->Read_U8 = XA_MEM_Read_U8;
215 xin->Read_LSB_U16 = XA_MEM_Read_LSB_U16;
216 xin->Read_MSB_U16 = XA_MEM_Read_MSB_U16;
217 xin->Read_LSB_U32 = XA_MEM_Read_LSB_U32;
218 xin->Read_MSB_U32 = XA_MEM_Read_MSB_U32;
219 xin->Read_Block = XA_MEM_Read_Block;
220 xin->Set_EOF = XA_Set_EOF;
221 xin->At_EOF = XA_MEM_EOF;
222 xin->Seek_FPos = XA_MEM_seek;
223 xin->Get_FPos = XA_MEM_ftell;
224 return(xaTRUE);
225 }
226
227 /***************************************************************************/
228 /******** Buffer Routines(Only used for Sequential Streams) **********/
229 /***************************************************************************/
230
231 /* This is used to read the 1st section of the file so that we may
232 * hopefully determine just what in the world it is(Not always
233 * possible(thank you so very much Quicktime))
234 */
XA_BUF_Init_Fill(xin,len)235 xaLONG XA_BUF_Init_Fill(xin,len)
236 XA_INPUT *xin;
237 xaULONG len;
238 { xaLONG ret;
239 if (len > xin->buf_size) return(0); /*POD eventually bust up buf size*/
240 xin->buf_cnt = 0;
241 xin->buf_ptr = xin->buf;
242 ret = xin->Read_Block(xin,xin->buf,len);
243 if (ret < len) xin->err_flag |= XA_IN_ERR_ERR;
244 xin->buf_cnt = len;
245 xin->fpos = 0; /* keep this at 0 */
246 return( ret );
247 }
248
249
250 /* The following BUF routines are only for sequential streams and that
251 * is to drain input already read in and stored in the buffer. Random
252 * access devices, we simply seek back to fpos 0
253 */
254
255 #define XA_BUF_U8(xin) ((xaULONG)(*xin->buf_ptr++))
256
257 #define XA_BUF_INC(xin) \
258 { xin->buf_cnt--; if (xin->buf_cnt == 0) xin->buf_ptr = 0; }
259
260 #define XA_BUF_VAL(xin) xin->buf_cnt
261
262 /***************************************************
263 * The XA_BUF_Read routines are never to be called directly. Only
264 * by other input routines when xin->buf_cnt > 0.
265 *
266 **********/
XA_BUF_Read_U8(xin)267 xaULONG XA_BUF_Read_U8(xin)
268 XA_INPUT *xin;
269 { xaULONG ret = XA_BUF_U8(xin); XA_BUF_INC(xin); return(ret);
270 }
271
XA_BUF_Read_LSB_U16(xin)272 xaULONG XA_BUF_Read_LSB_U16(xin)
273 XA_INPUT *xin;
274 { xaULONG ret = XA_BUF_U8(xin); XA_BUF_INC(xin);
275 if (XA_BUF_VAL(xin)) { ret |= XA_BUF_U8(xin) << 8; XA_BUF_INC(xin);}
276 else { ret |= xin->Read_U8(xin) << 8; xin->fpos--; }
277 return(ret);
278 }
279
XA_BUF_Read_MSB_U16(xin)280 xaULONG XA_BUF_Read_MSB_U16(xin)
281 XA_INPUT *xin;
282 { xaULONG ret = XA_BUF_U8(xin) << 8; XA_BUF_INC(xin);
283 if (XA_BUF_VAL(xin)) { ret |= XA_BUF_U8(xin); XA_BUF_INC(xin);}
284 else { ret |= xin->Read_U8(xin); xin->fpos--; }
285 return(ret);
286 }
287
XA_BUF_Read_LSB_U32(xin)288 xaULONG XA_BUF_Read_LSB_U32(xin)
289 XA_INPUT *xin;
290 { xaULONG ret = XA_BUF_U8(xin); XA_BUF_INC(xin);
291 if (XA_BUF_VAL(xin)) { ret |= XA_BUF_U8(xin) << 8; XA_BUF_INC(xin);}
292 else { ret |= xin->Read_U8(xin) << 8; xin->fpos--; }
293 if (XA_BUF_VAL(xin)) { ret |= XA_BUF_U8(xin) << 16; XA_BUF_INC(xin);}
294 else { ret |= xin->Read_U8(xin) << 16; xin->fpos--; }
295 if (XA_BUF_VAL(xin)) { ret |= XA_BUF_U8(xin) << 24; XA_BUF_INC(xin);}
296 else { ret |= xin->Read_U8(xin) << 24; xin->fpos--; }
297 return(ret);
298 }
299
XA_BUF_Read_MSB_U32(xin)300 xaULONG XA_BUF_Read_MSB_U32(xin)
301 XA_INPUT *xin;
302 { xaULONG ret = XA_BUF_U8(xin) << 24; XA_BUF_INC(xin);
303 if (XA_BUF_VAL(xin)) { ret |= XA_BUF_U8(xin) << 16; XA_BUF_INC(xin);}
304 else { ret |= xin->Read_U8(xin) << 16; xin->fpos--; }
305 if (XA_BUF_VAL(xin)) { ret |= XA_BUF_U8(xin) << 8; XA_BUF_INC(xin);}
306 else { ret |= xin->Read_U8(xin) << 8; xin->fpos--; }
307 if (XA_BUF_VAL(xin)) { ret |= XA_BUF_U8(xin); XA_BUF_INC(xin);}
308 else { ret |= xin->Read_U8(xin); xin->fpos--; }
309 return(ret);
310 }
311
XA_BUF_Read_Block(xin,ptr,len)312 xaLONG XA_BUF_Read_Block(xin,ptr,len)
313 XA_INPUT *xin;
314 xaUBYTE *ptr;
315 xaULONG len;
316 { xaULONG tmp_len = len;
317 while( xin->buf_cnt && len)
318 { *ptr++ = *xin->buf_ptr++; xin->buf_cnt--; len--; }
319 if (len) { xin->fpos -= len; return(xin->Read_Block(xin,ptr,len)); }
320 else return(tmp_len);
321 }
322
323 /***************************************************************************/
324 /******** General INPUT ROUTINES **********/
325 /***************************************************************************/
XA_Set_EOF(xin,len)326 void XA_Set_EOF(xin,len)
327 XA_INPUT *xin;
328 xaULONG len;
329 { xin->eof = len;
330 }
331
332
333 /***************************************************************************/
334 /******** STDIN INPUT ROUTINES **********/
335 /***************************************************************************/
XA_STDIN_Open_File(xin)336 xaULONG XA_STDIN_Open_File(xin)
337 XA_INPUT *xin;
338 { xin->buf_ptr = xin->buf; xin->buf_cnt = 0; xin->fpos = 0;
339 xin->err_flag = XA_IN_ERR_NONE;
340 xin->fin = stdin;
341 return(xaTRUE);
342 }
343
344 /***** */
XA_STDIN_Close_File(xin)345 xaULONG XA_STDIN_Close_File(xin)
346 XA_INPUT *xin;
347 { return(xaTRUE);
348 }
349
350 /***** */
XA_STDIN_Read_U8(xin)351 xaULONG XA_STDIN_Read_U8(xin)
352 XA_INPUT *xin;
353 { xin->fpos++;
354 if (xin->buf_cnt) return(XA_BUF_Read_U8(xin));
355 else return(fgetc( xin->fin ));
356 }
357
358 /***** */
XA_STDIN_Read_LSB_U16(xin)359 xaULONG XA_STDIN_Read_LSB_U16(xin)
360 XA_INPUT *xin;
361 { xin->fpos += 2;
362 if (xin->buf_cnt) return(XA_BUF_Read_LSB_U16(xin));
363 else { xaULONG ret = fgetc(xin->fin);
364 ret |= fgetc(xin->fin) << 8; return(ret);}
365 }
366
367 /***** */
XA_STDIN_Read_MSB_U16(xin)368 xaULONG XA_STDIN_Read_MSB_U16(xin)
369 XA_INPUT *xin;
370 { xin->fpos += 2;
371 if (xin->buf_cnt) return(XA_BUF_Read_MSB_U16(xin));
372 else { xaULONG ret = fgetc(xin->fin) << 8;
373 ret |= fgetc(xin->fin); return(ret); }
374 }
375
376 /***** */
XA_STDIN_Read_LSB_U32(xin)377 xaULONG XA_STDIN_Read_LSB_U32(xin)
378 XA_INPUT *xin;
379 { xin->fpos += 4;
380 if (xin->buf_cnt) return(XA_BUF_Read_LSB_U32(xin));
381 else { xaULONG ret = fgetc(xin->fin); ret |= fgetc(xin->fin) << 8;
382 ret |= fgetc(xin->fin) << 16; ret |= fgetc(xin->fin) << 24;
383 return(ret); }
384 }
385
386 /***** */
XA_STDIN_Read_MSB_U32(xin)387 xaULONG XA_STDIN_Read_MSB_U32(xin)
388 XA_INPUT *xin;
389 { xin->fpos += 4;
390 if (xin->buf_cnt) return(XA_BUF_Read_MSB_U32(xin));
391 else {xaULONG ret = fgetc(xin->fin)<<24; ret |= fgetc(xin->fin) << 16;
392 ret |= fgetc(xin->fin) << 8; ret |= fgetc(xin->fin);
393 return(ret); }
394 }
395
396 /***** */
XA_STDIN_Read_Block(xin,ptr,len)397 xaLONG XA_STDIN_Read_Block(xin,ptr,len)
398 XA_INPUT *xin;
399 xaUBYTE *ptr;
400 xaULONG len;
401 { xin->fpos += len;
402 if (xin->buf_cnt) return(XA_BUF_Read_Block(xin,ptr,len));
403 else {xaLONG ret = fread( (char *)(ptr), 1 , len, xin->fin);
404 return(ret); }
405 }
406
407 /**************************
408 * Potential problem if File is shorter than initial buffer size
409 ********/
XA_STDIN_EOF(xin,off)410 xaLONG XA_STDIN_EOF(xin,off)
411 XA_INPUT *xin;
412 xaULONG off; /* not used */
413 { xaLONG ret = feof((xin->fin)); if (ret) xin->err_flag |= XA_IN_ERR_EOF;
414 return( ret );
415 }
416
417 /***** */
XA_STDIN_ftell(xin)418 xaLONG XA_STDIN_ftell(xin)
419 XA_INPUT *xin;
420 { return( xin->fpos );
421 }
422
423 /***** */
XA_STDIN_seek(xin,fpos,flag)424 xaLONG XA_STDIN_seek(xin,fpos,flag)
425 XA_INPUT *xin;
426 xaLONG fpos;
427 xaLONG flag;
428 { xaLONG ret = -1;
429 /** Move Forward valid in Sequential Streams */
430 if ( (flag == 1) && (fpos >= 0) )
431 { xin->fpos += fpos; ret = xin->fpos;
432 while((fpos--) && !feof(xin->fin)) (void)(fgetc(xin->fin));
433 } /** Move til End kinda of a NOP, but with stdin we can do that */
434 else if ( (flag == 2) && (fpos == 0) )
435 { while(!feof(xin->fin)) { ret = getc(xin->fin); if (ret >= 0) xin->fpos++; }
436 xin->err_flag |= XA_IN_ERR_EOF;
437 } /** Move beyond current position ok */
438 else if ((flag == 0) && (fpos >= xin->fpos))
439 { while(xin->fpos < fpos) { fgetc(xin->fin); xin->fpos++; }
440 }
441 else /** Otherwise - not possible - complain */
442 {
443 fprintf(stderr,"STDIN seek err: off = %d flag = %d curpos %d\n",
444 fpos,flag,xin->fpos);
445 return(-1);
446 }
447 return(0);
448 }
449
450 /***************************************************************************/
451 /******** FILE INPUT ROUTINES **********/
452 /***************************************************************************/
453
454 /***** */
XA_FILE_Open_File(xin)455 xaULONG XA_FILE_Open_File(xin)
456 XA_INPUT *xin;
457 { xin->buf_ptr = xin->buf; xin->buf_cnt = 0; xin->fpos = 0;
458 xin->err_flag = XA_IN_ERR_NONE;
459 xin->fin = fopen(xin->file, XA_OPEN_MODE);
460 if (xin->fin == 0) return(xaFALSE);
461 return(xaTRUE);
462 }
463
464 /***** */
XA_FILE_Close_File(xin)465 xaULONG XA_FILE_Close_File(xin)
466 XA_INPUT *xin;
467 { fclose(xin->fin);
468 return(xaTRUE);
469 }
470
471
472 /***** */
XA_FILE_Read_U8(xin)473 xaULONG XA_FILE_Read_U8(xin)
474 XA_INPUT *xin;
475 { xin->fpos++;
476 return( (fgetc(xin->fin)) & 0xff );
477 }
478
479 /***** */
XA_FILE_Read_LSB_U16(xin)480 xaULONG XA_FILE_Read_LSB_U16(xin)
481 XA_INPUT *xin;
482 { xaULONG ret; xin->fpos += 2;
483 ret = ((fgetc(xin->fin)) & 0xff);
484 ret |= ((fgetc(xin->fin)) & 0xff) << 8;
485 return(ret);
486 }
487
488 /***** */
XA_FILE_Read_MSB_U16(xin)489 xaULONG XA_FILE_Read_MSB_U16(xin)
490 XA_INPUT *xin;
491 { xaULONG ret; xin->fpos += 2;
492 ret = ((fgetc(xin->fin)) & 0xff) << 8;
493 ret |= ((fgetc(xin->fin)) & 0xff);
494 return(ret);
495 }
496
497 /***** */
XA_FILE_Read_LSB_U32(xin)498 xaULONG XA_FILE_Read_LSB_U32(xin)
499 XA_INPUT *xin;
500 { xaULONG ret; xin->fpos += 4;
501 ret = ((fgetc(xin->fin)) & 0xff);
502 ret |= ((fgetc(xin->fin)) & 0xff) << 8;
503 ret |= ((fgetc(xin->fin)) & 0xff) << 16;
504 ret |= ((fgetc(xin->fin)) & 0xff) << 24;
505 return(ret);
506 }
507
508 /***** */
XA_FILE_Read_MSB_U32(xin)509 xaULONG XA_FILE_Read_MSB_U32(xin)
510 XA_INPUT *xin;
511 { xaULONG ret; xin->fpos += 4;
512 ret = ((fgetc(xin->fin)) & 0xff) << 24;
513 ret |= ((fgetc(xin->fin)) & 0xff) << 16;
514 ret |= ((fgetc(xin->fin)) & 0xff) << 8;
515 ret |= ((fgetc(xin->fin)) & 0xff);
516 return(ret);
517 }
518
519 /***** */
XA_FILE_Read_Block(xin,ptr,len)520 xaLONG XA_FILE_Read_Block(xin,ptr,len)
521 XA_INPUT *xin;
522 xaUBYTE *ptr;
523 xaULONG len;
524 { xaLONG ret; xin->fpos += len;
525 ret = fread(ptr,1,len,xin->fin);
526 if (ret < len) xin->err_flag |= XA_IN_ERR_ERR;
527 return(ret);
528 }
529
530 /***** */
XA_FILE_EOF(xin,off)531 xaLONG XA_FILE_EOF(xin,off)
532 XA_INPUT *xin;
533 xaULONG off; /* not used */
534 { return( feof(xin->fin) );
535 }
536
537 /***** */
XA_FILE_ftell(xin)538 xaLONG XA_FILE_ftell(xin)
539 XA_INPUT *xin;
540 { return( ftell(xin->fin) );
541 }
542
543 /*****
544 * flag 0 beginning, 1 current, 2 end
545 */
XA_FILE_seek(xin,off,flag)546 xaLONG XA_FILE_seek(xin,off,flag)
547 XA_INPUT *xin;
548 xaLONG off;
549 xaLONG flag;
550 { return( fseek(xin->fin, off, flag) );
551 }
552
553
554 /***************************************************************************/
555 /******** Memory INPUT ROUTINES **********/
556 /***************************************************************************/
557
558 /***** */
XA_MEM_Open_File(xin)559 xaULONG XA_MEM_Open_File(xin)
560 XA_INPUT *xin;
561 { xin->buf_ptr = xin->buf;
562 xin->buf_cnt = xin->buf_size;
563 xin->fpos = 0;
564 xin->err_flag = XA_IN_ERR_NONE;
565 return(xaTRUE);
566 }
567
568 /***** */
XA_MEM_Close_File(xin)569 xaULONG XA_MEM_Close_File(xin)
570 XA_INPUT *xin;
571 {
572 return(xaTRUE);
573 }
574
575 /***** */
XA_MEM_Read_U8(xin)576 xaULONG XA_MEM_Read_U8(xin)
577 XA_INPUT *xin;
578 { xaULONG ret;
579 if (xin->buf_cnt < 1) { ret = 0xff; xin->err_flag |= XA_IN_ERR_EOF; }
580 else { ret = *xin->buf_ptr++; xin->fpos++; xin->buf_cnt--; }
581 return( ret );
582 }
583
584 /***** */
XA_MEM_Read_LSB_U16(xin)585 xaULONG XA_MEM_Read_LSB_U16(xin)
586 XA_INPUT *xin;
587 { xaULONG ret;
588 if (xin->buf_cnt < 2) { ret = 0xffff; xin->err_flag |= XA_IN_ERR_EOF; }
589 else
590 { ret = xin->buf_ptr[0]; ret |= xin->buf_ptr[1] << 8;
591 xin->fpos += 2; xin->buf_cnt -= 2; xin->buf_ptr += 2;
592 }
593 return(ret);
594 }
595
596 /***** */
XA_MEM_Read_MSB_U16(xin)597 xaULONG XA_MEM_Read_MSB_U16(xin)
598 XA_INPUT *xin;
599 { xaULONG ret;
600 if (xin->buf_cnt < 2) { ret = 0xffff; xin->err_flag |= XA_IN_ERR_EOF; }
601 else
602 { ret = xin->buf_ptr[1]; ret |= xin->buf_ptr[0] << 8;
603 xin->fpos += 2; xin->buf_cnt -= 2; xin->buf_ptr += 2;
604 }
605 return(ret);
606 }
607
608 /***** */
XA_MEM_Read_LSB_U32(xin)609 xaULONG XA_MEM_Read_LSB_U32(xin)
610 XA_INPUT *xin;
611 { xaULONG ret;
612 if (xin->buf_cnt < 4) { ret = 0xffffffff; xin->err_flag |= XA_IN_ERR_EOF; }
613 else
614 { ret = xin->buf_ptr[0];
615 ret |= xin->buf_ptr[1] << 8;
616 ret |= xin->buf_ptr[2] << 16;
617 ret |= xin->buf_ptr[3] << 24;
618 xin->fpos += 4; xin->buf_cnt -= 4; xin->buf_ptr += 4;
619 }
620 return(ret);
621 }
622
623 /***** */
XA_MEM_Read_MSB_U32(xin)624 xaULONG XA_MEM_Read_MSB_U32(xin)
625 XA_INPUT *xin;
626 { xaULONG ret;
627 if (xin->buf_cnt < 4) { ret = 0xffffffff; xin->err_flag |= XA_IN_ERR_EOF; }
628 else
629 { ret = xin->buf_ptr[3];
630 ret |= xin->buf_ptr[2] << 8;
631 ret |= xin->buf_ptr[1] << 16;
632 ret |= xin->buf_ptr[0] << 24;
633 xin->fpos += 4; xin->buf_cnt -= 4; xin->buf_ptr += 4;
634 }
635 return(ret);
636 }
637
638 /***** */
XA_MEM_Read_Block(xin,ptr,len)639 xaLONG XA_MEM_Read_Block(xin,ptr,len)
640 XA_INPUT *xin;
641 xaUBYTE *ptr;
642 xaULONG len;
643 {
644 if (len > xin->buf_cnt)
645 { len = xin->buf_cnt; xin->err_flag |= XA_IN_ERR_EOF; }
646 if (len)
647 { memcpy(ptr, xin->buf_ptr, len);
648 xin->fpos += len; xin->buf_cnt -= len; xin->buf_ptr += len;
649 }
650 return(len);
651 }
652
653 /***** */
XA_MEM_EOF(xin,off)654 xaLONG XA_MEM_EOF(xin,off)
655 XA_INPUT *xin;
656 xaULONG off; /* not used */
657 {
658 if ( (xin->buf_cnt == 0)
659 || (xin->err_flag & XA_IN_ERR_EOF) ) return(1);
660 return( 0 );
661 }
662
663 /***** */
XA_MEM_ftell(xin)664 xaLONG XA_MEM_ftell(xin)
665 XA_INPUT *xin;
666 { return( xin->fpos );
667 }
668
669 /*****
670 * flag 0 beginning, 1 current, 2 end
671 */
XA_MEM_seek(xin,off,flag)672 xaLONG XA_MEM_seek(xin,off,flag)
673 XA_INPUT *xin;
674 xaLONG off;
675 xaLONG flag;
676 {
677 switch( flag )
678 {
679 case 0: /* from beginning */
680 if (off > xin->buf_size) off = xin->buf_size;
681 break;
682 case 1: /* from current pos */
683 off += xin->fpos;
684 if (off > xin->buf_size) off = xin->buf_size;
685 break;
686 case 2: /* from end */
687 off = xin->buf_size - off;
688 if (off < 0) off = 0;
689 break;
690 default:
691 off = xin->fpos;
692 break;
693 }
694
695 xin->buf_cnt = xin->buf_size - off;
696 xin->buf_ptr = &xin->buf[ off ];
697 xin->fpos = off;
698 return(off);
699 }
700
701
702
703
704
705
706
707
708 /***************************************************************************/
709 /******** FTP INPUT ROUTINES **********/
710 /***************************************************************************/
711
712 #define FTP_READ(xin,ptr,len,ret) \
713 { xaLONG cnt = 0; ret = 1; \
714 while((ret > 0) && (cnt < len)) \
715 { ret = read(xin->dsock,ptr,1); if (ret <= 0) break; \
716 cnt++; ptr++; } \
717 if (ret < 0) { xin->err_flag |= XA_IN_ERR_ERR; } \
718 else { ret = cnt; if (ret == 0) xin->err_flag |= XA_IN_ERR_EOF; } }
719 /* FOR DEBUG: fprintf(stderr,"FTP-TMP: errno %d\n",errno); */
720
721 /***** */
XA_FTP_Read_U8(xin)722 xaULONG XA_FTP_Read_U8(xin)
723 XA_INPUT *xin;
724 { xin->fpos++;
725 if (xin->buf_cnt) return(XA_BUF_Read_U8(xin));
726 else
727 { xaLONG ret; xaUBYTE *ptr = xin->buf;
728 FTP_READ(xin,ptr,1,ret); if (ret < 1) return(0);
729 return( (xaULONG)(*xin->buf) );
730 }
731 }
732
733 /***** */
XA_FTP_Read_LSB_U16(xin)734 xaULONG XA_FTP_Read_LSB_U16(xin)
735 XA_INPUT *xin;
736 { xin->fpos += 2;
737 if (xin->buf_cnt) return(XA_BUF_Read_LSB_U16(xin));
738 else
739 { xaLONG ret; xaUBYTE *ptr = xin->buf;
740 FTP_READ(xin,ptr,2,ret); if (ret < 2) return(0);
741 return( (xaULONG)(xin->buf[0]) | ((xaULONG)(xin->buf[1])<<8) );
742 }
743 }
744 /***** */
XA_FTP_Read_MSB_U16(xin)745 xaULONG XA_FTP_Read_MSB_U16(xin)
746 XA_INPUT *xin;
747 { xin->fpos += 2;
748 if (xin->buf_cnt) return(XA_BUF_Read_MSB_U16(xin));
749 else
750 { xaLONG ret; xaUBYTE *ptr = xin->buf;
751 FTP_READ(xin,ptr,2,ret); if (ret < 2) return(0);
752 return( (xaULONG)(xin->buf[1]) | ((xaULONG)(xin->buf[0])<<8) );
753 }
754 }
755 /***** */
XA_FTP_Read_LSB_U32(xin)756 xaULONG XA_FTP_Read_LSB_U32(xin)
757 XA_INPUT *xin;
758 { xin->fpos += 4;
759 if (xin->buf_cnt) return(XA_BUF_Read_LSB_U32(xin));
760 else
761 { xaLONG ret; xaUBYTE *ptr = xin->buf;
762 FTP_READ(xin,ptr,4,ret); if (ret < 4) return(0);
763 return( (xaULONG)(xin->buf[0]) | ((xaULONG)(xin->buf[1])<<8)
764 | ((xaULONG)(xin->buf[2])<<16) | ((xaULONG)(xin->buf[3])<<24) );
765 }
766 }
767 /***** */
XA_FTP_Read_MSB_U32(xin)768 xaULONG XA_FTP_Read_MSB_U32(xin)
769 XA_INPUT *xin;
770 { xin->fpos += 4;
771 if (xin->buf_cnt) return(XA_BUF_Read_MSB_U32(xin));
772 else
773 { xaLONG ret; xaUBYTE *ptr = xin->buf;
774 FTP_READ(xin,ptr,4,ret); if (ret < 4) return(0);
775 return( (xaULONG)(xin->buf[3]) | ((xaULONG)(xin->buf[2])<<8)
776 | ((xaULONG)(xin->buf[1])<<16) | ((xaULONG)(xin->buf[0])<<24) );
777 }
778 }
779
780
781
782 /***** */
XA_FTP_Read_Block(xin,ptr,len)783 xaLONG XA_FTP_Read_Block(xin,ptr,len)
784 XA_INPUT *xin;
785 xaUBYTE *ptr;
786 xaULONG len;
787 { xin->fpos += len;
788 if (xin->buf_cnt) return(XA_BUF_Read_Block(xin,ptr,len));
789 else { xaLONG ret; FTP_READ(xin,ptr,len,ret); return(ret); }
790 }
791
XA_FTP_Open_File(xin)792 xaULONG XA_FTP_Open_File(xin)
793 XA_INPUT *xin;
794 { xaLONG ret;
795 char machine[256],user_cmd[256],pass_cmd[256],file_cmd[256],*tmp;
796
797 xin->buf_ptr = xin->buf; xin->buf_cnt = 0; xin->fpos = 0;
798 xin->err_flag = XA_IN_ERR_NONE;
799
800 XA_File_Split(xin->file, machine, file_cmd);
801 /* Get user name for ftp */
802 strcpy(user_cmd,"USER \0");
803 if ( (tmp = getenv("XANIM_USER")) != NULL) strcat(user_cmd,tmp);
804 else strcat(user_cmd,"anonymous\0");
805 /* Get passwd for ftp */
806 strcpy(pass_cmd,"PASS \0");
807 if ( (tmp = getenv("XANIM_PASSWD")) != NULL) strcat(pass_cmd,tmp);
808 else strcat(pass_cmd,"xanim@xanim.com\0");
809 /* Open Connection and Request remote file via ftp */
810 ret = xaftp_open_file(xin, machine, user_cmd, pass_cmd, file_cmd);
811 return(ret);
812 }
813
814 /***** */
XA_FTP_Close_File(xin)815 xaULONG XA_FTP_Close_File(xin)
816 XA_INPUT *xin;
817 { xaLONG retcode;
818 xin->buf_cnt = 0;
819 xin->buf_ptr = xin->buf;
820 if (xin->dsock >= 0) { close(xin->dsock); xin->dsock = -1; }
821 if (xa_ftp_get_msg(xin, &retcode) == xaFALSE) return(xaFALSE);
822 if (xa_ftp_send_cmd(xin, "QUIT", &retcode) == xaFALSE) return(xaFALSE);
823 if (xin->csock >= 0) { close(xin->csock); xin->csock = -1; }
824 return(xaTRUE);
825 }
826
827 /***** */
XA_FTP_EOF(xin,off)828 xaLONG XA_FTP_EOF(xin, off)
829 XA_INPUT *xin;
830 xaLONG off;
831 { if ((off >=0) && ((xin->fpos + off) > xin->eof)) return(xaTRUE);
832 return( (xin->err_flag==XA_IN_ERR_NONE)?(xaFALSE):(xaTRUE) );
833 }
834
835 /***** */
XA_FTP_ftell(xin)836 xaLONG XA_FTP_ftell(xin)
837 XA_INPUT *xin;
838 {
839 return( xin->fpos );
840 }
841
842 /***** */
XA_FTP_seek(xin,fpos,flag)843 xaLONG XA_FTP_seek(xin,fpos,flag)
844 XA_INPUT *xin;
845 xaLONG fpos;
846 xaLONG flag;
847 { char c;
848
849 /** Move Forward valid in Sequential Streams */
850 if ( (flag == 1) && (fpos >= 0) )
851 { xin->fpos += fpos;
852 while(fpos--) read( xin->dsock, &c, 1);
853 } /** Move til End kinda of a NOP */
854 else if ((flag == 2) && (fpos == 0))
855 { xin->err_flag |= XA_IN_ERR_EOF;
856 } /** Move beyond current position ok */
857 else if ((flag == 0) && (fpos >= xin->fpos) )
858 { while(xin->fpos < fpos) { read( xin->dsock, &c, 1); xin->fpos++; }
859 }
860 else /** Otherwise - not possible - complain */
861 {
862 fprintf(stderr,"FTP seek err. off = %d flag = %d=n",fpos,flag);
863 return(-1);
864 }
865 return( 0 );
866 }
867
868
XA_File_Split(file,machine,file_name)869 xaULONG XA_File_Split(file,machine,file_name)
870 char *file, *machine, *file_name;
871 { char *tmp;
872
873 /* skip over ftp:// */
874 tmp = &file[6];
875 strcpy(machine, tmp);
876 tmp = strchr(machine, '/' );
877 if (tmp == 0) return(xaFALSE);
878 strcpy(file_name, "RETR ");
879 strcat(file_name, tmp);
880 /* null terminate machine */
881 *tmp = 0;
882 return(xaTRUE);
883 }
884
885
886 /************************
887 *
888 *********/
xa_ftp_get_msg(xin,ret_code)889 xaLONG xa_ftp_get_msg(xin, ret_code)
890 XA_INPUT *xin;
891 xaLONG *ret_code;
892 { xaLONG code, msg3;
893 *ret_code = 0;
894 while(1)
895 { xaLONG ncnt = 0;
896 xaLONG state = 0;
897 msg3 = 0;
898 code = 0;
899 while(1)
900 { char tmp;
901
902 if ( read(xin->csock, &tmp, 1) != 1) return(xaFALSE);
903
904 /* construct return code */
905 if (ncnt == 0) code = (tmp - '0') * 100;
906 else if (ncnt == 1) code += (tmp - '0') * 10;
907 else if (ncnt == 2) code += (tmp - '0');
908 else if (ncnt == 3) msg3 = tmp;
909 ncnt++;
910 /* check for end of message */
911 if ((state == 0) && (tmp == 0x0d)) state++; /* detect ctl-M */
912 else if (state == 1)
913 { if (tmp == 0x0a) break; /* detect ctl-J */
914 else if (tmp == 0x0d) state = 1; /* two ctl-M's ? */
915 else state = 0;
916 }
917 else
918 {
919 state = 0;
920 DEBUG_LEVEL2 fprintf(stderr,"%c",tmp);
921 }
922 }
923 if ((ncnt < 5) || (msg3 != '-')) break;
924 }
925 DEBUG_LEVEL2 fprintf(stderr,"\n");
926 *ret_code = code;
927 return(xaTRUE);
928 }
929
930 /************************
931 *
932 *********/
xa_ftp_send_cmd(xin,cmd,retcode)933 xaLONG xa_ftp_send_cmd(xin,cmd,retcode)
934 XA_INPUT *xin;
935 char *cmd;
936 xaLONG *retcode;
937 { xaLONG len = strlen(cmd);
938 *retcode = 0;
939 if (write(xin->csock, cmd, len) < len)
940 { fprintf(stderr,"ftp send_cmd 1st write err\n");
941 return(xaFALSE); }
942 if (write(xin->csock, "\015\012", 2) < 2)
943 { fprintf(stderr,"ftp send_cmd 2nd write err\n");
944 return(xaFALSE); }
945 if (xa_ftp_get_msg(xin,retcode) == xaFALSE)
946 { fprintf(stderr,"ftp get_msg err\n");
947 return(xaFALSE); }
948
949 DEBUG_LEVEL2 fprintf(stderr,"CMD: %s retcode %d\n",cmd, *retcode);
950
951 if ((*retcode >= 100) && (*retcode < 400)) return(xaTRUE);/* POD Ness?*/
952 else return(xaFALSE);
953 }
954
xa_ftp_abort(xin)955 xaULONG xa_ftp_abort(xin)
956 XA_INPUT xin;
957 {
958 return(xaFALSE);
959 }
960
961
962 /************************
963 *
964 *********/
xaftp_open_file(xin,machine,user_cmd,passwd_cmd,file_cmd)965 xaLONG xaftp_open_file(xin, machine, user_cmd, passwd_cmd, file_cmd)
966 XA_INPUT *xin;
967 char *machine, *user_cmd, *passwd_cmd, *file_cmd;
968 { struct sockaddr_in unit, data, from;
969 struct hostent *host;
970 struct servent *service;
971 char hostname[256];
972 xaUBYTE *addr,*port;
973 xaLONG retcode;
974 int tmp_sock;
975 int len;
976 char port_cmd[256];
977
978 xin->csock = -1;
979 xin->dsock = -1;
980
981 if ((host = gethostbyname(machine)) == 0) return(xaFALSE);
982 #ifndef VMS
983 if ((service = (struct servent *)getservbyname("ftp","tcp"))==0)
984 return(xaFALSE);
985 #endif
986 unit.sin_family = host -> h_addrtype;
987 memcpy( &unit.sin_addr, host->h_addr_list[0], host->h_length);
988 if ( (xin->csock = socket(unit.sin_family, SOCK_STREAM, 0)) < 0)
989 return(xaFALSE);
990 #ifndef VMS
991 unit.sin_port = service -> s_port;
992 #else
993 unit.sin_port = htons(21);
994 #endif
995
996 while((connect(xin->csock, (struct sockaddr *)(&unit),sizeof(unit))) < 0)
997 {
998 close(xin->csock);
999 host->h_addr_list++;
1000 if (host->h_addr_list[0] == NULL) return(xaFALSE);
1001 memcpy(&unit.sin_addr, host->h_addr_list[0], host->h_length);
1002 if ((xin->csock = socket(unit.sin_family, SOCK_STREAM, 0)) < 0)
1003 return(xaFALSE);
1004 }
1005
1006 if (xa_ftp_get_msg(xin, &retcode) == xaFALSE) return(xaFALSE);
1007 if ((retcode < 100) && (retcode > 399))
1008 { close(xin->csock);
1009 return(xaFALSE);
1010 }
1011
1012 /* Now we should be connect to the remote machine */
1013 if (xa_ftp_send_cmd(xin, user_cmd, &retcode) == xaFALSE) return(xaFALSE);
1014 if (retcode != 240) /* need passwd */
1015 {
1016 if (retcode == 332)
1017 { return(xaFALSE); /* POD for now no account support */
1018 }
1019 if (xa_ftp_send_cmd(xin, passwd_cmd, &retcode) == xaFALSE) return(xaFALSE);
1020 }
1021 /* Type Binary */
1022 if (xa_ftp_send_cmd(xin, "TYPE I", &retcode) == xaFALSE) return(xaFALSE);
1023 /* Open Up Data connection */
1024
1025 memset(&data,0,sizeof(data));
1026 memset(&from,0,sizeof(from));
1027 if (gethostname(hostname, sizeof(hostname)) < 0)
1028 return(xa_ftp_abort(*xin));
1029 if ((host= (struct hostent *)gethostbyname(hostname)) == 0)
1030 return(xa_ftp_abort(*xin));
1031 data.sin_family = host->h_addrtype;
1032 memcpy( (char *)&data.sin_addr, (char *)host->h_addr_list[0], host->h_length);
1033 if ((tmp_sock = socket ( AF_INET , SOCK_STREAM , 0 )) < 0)
1034 return(xa_ftp_abort(*xin));
1035 len = 1;
1036 if (setsockopt(tmp_sock, SOL_SOCKET, SO_REUSEADDR,
1037 (char *)(&len), sizeof(len)) < 0)
1038 { close(tmp_sock); return(xa_ftp_abort(*xin)); }
1039
1040 data.sin_port = 0;
1041 if ( bind(tmp_sock, (struct sockaddr *)&data, sizeof(data)) < 0 )
1042 { close(tmp_sock); return(xa_ftp_abort(*xin)); }
1043
1044 len = sizeof(data);
1045 if (getsockname(tmp_sock, (struct sockaddr *)&data, &len) < 0 )
1046 { close(tmp_sock); return(xa_ftp_abort(*xin)); }
1047
1048 if (listen(tmp_sock, 4) < 0 )
1049 { close(tmp_sock); return(xa_ftp_abort(*xin)); }
1050
1051 /* POD add support for PORT command? */
1052 addr = (xaUBYTE *) (&data.sin_addr);
1053 port = (xaUBYTE *) (&data.sin_port);
1054
1055 sprintf(port_cmd,"PORT %d,%d,%d,%d,%d,%d\0",
1056 (addr[0] & 0xff), (addr[1] & 0xff),
1057 (addr[2] & 0xff), (addr[3] & 0xff),
1058 (port[0] & 0xff), (port[1] & 0xff) );
1059
1060 if (xa_ftp_send_cmd(xin, port_cmd, &retcode) == xaFALSE)
1061 { fprintf(stderr,"FTP: send cmd err\n");
1062 close(tmp_sock); return(xa_ftp_abort(*xin)); }
1063
1064 if (xa_ftp_send_cmd(xin, file_cmd, &retcode) == xaFALSE)
1065 { fprintf(stderr,"FTP: send cmd err\n");
1066 close(tmp_sock); return(xa_ftp_abort(*xin)); }
1067
1068 len = sizeof(from);
1069 xin->dsock = accept((int)tmp_sock, (struct sockaddr *) &from, (int *)&len);
1070 if (xin->dsock < 0) { close(tmp_sock); return(xa_ftp_abort(*xin)); }
1071 close(tmp_sock);
1072 return(xaTRUE);
1073 }
1074
1075
1076