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