~ubuntu-branches/ubuntu/trusty/maloc/trusty-proposed

« back to all changes in this revision

Viewing changes to src/vsys/vio.c

  • Committer: Bazaar Package Importer
  • Author(s): Michael Banck
  • Date: 2006-06-29 15:21:06 UTC
  • Revision ID: james.westby@ubuntu.com-20060629152106-kyqdw6qlc3vmqum3
Tags: upstream-0.2
ImportĀ upstreamĀ versionĀ 0.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * ***************************************************************************
 
3
 * MALOC = < Minimal Abstraction Layer for Object-oriented C >
 
4
 * Copyright (C) 1994--2000  Michael Holst
 
5
 * 
 
6
 * This program is free software; you can redistribute it and/or modify it
 
7
 * under the terms of the GNU General Public License as published by the
 
8
 * Free Software Foundation; either version 2 of the License, or (at your
 
9
 * option) any later version.
 
10
 * 
 
11
 * This program is distributed in the hope that it will be useful,
 
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
14
 * See the GNU General Public License for more details.
 
15
 * 
 
16
 * You should have received a copy of the GNU General Public License along
 
17
 * with this program; if not, write to the Free Software Foundation, Inc.,
 
18
 * 675 Mass Ave, Cambridge, MA 02139, USA.
 
19
 * 
 
20
 * rcsid="$Id: vio.c,v 1.28 2004/02/18 01:10:56 mholst Exp $"
 
21
 * ***************************************************************************
 
22
 */
 
23
 
 
24
/*
 
25
 * ***************************************************************************
 
26
 * File:     vio.c
 
27
 *
 
28
 * Purpose:  Class Vio: methods.
 
29
 *
 
30
 * Author:   Michael Holst
 
31
 * ***************************************************************************
 
32
 */
 
33
 
 
34
#include "vio_p.h"
 
35
 
 
36
VEMBED(rcsid="$Id: vio.c,v 1.28 2004/02/18 01:10:56 mholst Exp $")
 
37
 
 
38
#if defined(HAVE_UNISTD_H)
 
39
#   include <unistd.h>
 
40
#endif
 
41
 
 
42
#if defined(HAVE_SYS_TYPES_H)
 
43
#   include <sys/types.h> 
 
44
#endif
 
45
 
 
46
#if defined(HAVE_SYS_STAT_H)
 
47
#   include <sys/stat.h> 
 
48
#endif
 
49
 
 
50
#if defined(HAVE_FCNTL_H)
 
51
#   include <fcntl.h>
 
52
#endif
 
53
 
 
54
#if defined(HAVE_SYS_SOCKET_H)
 
55
#   include <sys/socket.h>
 
56
#endif
 
57
 
 
58
#if defined(HAVE_SYS_UN_H)
 
59
#   include <sys/un.h>
 
60
#endif
 
61
 
 
62
#if defined(HAVE_NETINET_IN_H)
 
63
#   include <netinet/in.h> 
 
64
#endif
 
65
 
 
66
#if defined(HAVE_ARPA_INET_H)
 
67
#   include <arpa/inet.h> 
 
68
#endif
 
69
 
 
70
#if defined(HAVE_NETDB_H)
 
71
#   include <netdb.h> 
 
72
#endif
 
73
 
 
74
#if defined(HAVE_RPC_RPC_H)
 
75
#   include <rpc/rpc.h> 
 
76
#elif defined(HAVE_RPC_H)
 
77
#   include <rpc.h> 
 
78
#endif
 
79
 
 
80
#if defined(HAVE_WINSOCK_H)
 
81
#   include <winsock.h>
 
82
#endif
 
83
 
 
84
#if defined(HAVE_IO_H)
 
85
#   include <io.h>
 
86
#endif
 
87
 
 
88
/* ASC modes as dual to the XDR modes */
 
89
typedef enum ASCmode {
 
90
    ASC_NO_MODE,
 
91
    ASC_DECODE,
 
92
    ASC_ENCODE
 
93
} ASCmode;
 
94
 
 
95
/* ASC structure as dual to the XDR structure */
 
96
typedef struct ASC {
 
97
    ASCmode mode;                    /* ASC_DECODE or ASC_ENCODE            */
 
98
    int     pos;                     /* position of next character in buf   */
 
99
    int     size;                    /* size of buf                         */
 
100
    char    *buf;                    /* the character buffer                */
 
101
    char    whiteChars[VMAX_ARGNUM]; /* white space character set           */
 
102
    char    commChars[VMAX_ARGNUM];  /* comment character set               */
 
103
} ASC;
 
104
 
 
105
/* use ASC in place of XDR if XDR does not exist */
 
106
#if !defined(HAVE_XDR)
 
107
#   define XDR           ASC
 
108
#   define XDR_DECODE    ASC_DECODE
 
109
#   define XDR_ENCODE    ASC_ENCODE
 
110
#   define xdrmem_create ascmem_create
 
111
#   define xdr_destroy   asc_destroy
 
112
#   define xdr_getpos    asc_getpos
 
113
#   define xdr_setpos    asc_setpos
 
114
#   define xdr_string    asc_string
 
115
#   define xdr_char      asc_char
 
116
#   define xdr_int       asc_int
 
117
#   define xdr_float     asc_float
 
118
#   define xdr_double    asc_double
 
119
#endif
 
120
 
 
121
/* communication startup */
 
122
VPRIVATE int VIOstarted = 0;
 
123
 
 
124
/* default comment char set and white space char set */
 
125
VPRIVATE char *VIOwhiteChars = " \t\n";
 
126
VPRIVATE char *VIOcommChars  = "";
 
127
 
 
128
/* initialization, signals, and other tools */
 
129
VPRIVATE void VIOregHand(void);
 
130
VPRIVATE void VIOunregHand(void);
 
131
VPRIVATE void VIOsigHand(int num);
 
132
VPRIVATE int VIOgethostname(char *name, unsigned int len);
 
133
VPRIVATE const char *VIOstrerrno(int err);
 
134
 
 
135
/* buffer management */
 
136
VPRIVATE void Vio_initIoPutBuffers(Vio *thee);
 
137
VPRIVATE void Vio_purgePutBuffer(Vio *thee);
 
138
VPRIVATE int Vio_writePutBuffer(Vio *thee, char *buf, int bufsize);
 
139
 
 
140
/* ASC analogs to the core XDR routines */
 
141
VPRIVATE void ascmem_create(ASC *thee, char *buf, int size, ASCmode mode);
 
142
VPRIVATE void asc_destroy(ASC *thee);
 
143
VPRIVATE int asc_getpos(ASC *thee);
 
144
VPRIVATE int asc_setpos(ASC *thee, int pos);
 
145
VPRIVATE int asc_string(ASC *thee, char **sval, int size);
 
146
VPRIVATE int asc_char(ASC *thee, char *cval);
 
147
VPRIVATE int asc_int(ASC *thee, int *ival);
 
148
VPRIVATE int asc_float(ASC *thee, float *fval);
 
149
VPRIVATE int asc_double(ASC *thee, double *dval);
 
150
 
 
151
/* some additional ASC routines (no analogs in XDR) */
 
152
VPRIVATE void asc_setWhiteChars(ASC *thee, char *whiteChars);
 
153
VPRIVATE void asc_setCommChars(ASC *thee, char *commChars);
 
154
VPRIVATE char *asc_getToken(ASC *thee, char *tok, int toksize);
 
155
 
 
156
/* two low-level file-descriptor i/o jewels from Rick Steven's book */
 
157
VPRIVATE int readn(int fd, void *vptr, unsigned int n);
 
158
VPRIVATE int writen(int fd, void *vptr, unsigned int n) ;
 
159
 
 
160
/*
 
161
 * ***************************************************************************
 
162
 * Class Vio: Inlineable methods
 
163
 * ***************************************************************************
 
164
 */
 
165
#if !defined(VINLINE_MALOC)
 
166
 
 
167
#endif /* if !defined(VINLINE_MALOC) */
 
168
/*
 
169
 * ***************************************************************************
 
170
 * Class Vio: Non-inlineable methods
 
171
 * ***************************************************************************
 
172
 */
 
173
 
 
174
/*
 
175
 * ***************************************************************************
 
176
 * Routine:  Vio_start
 
177
 *
 
178
 * Purpose:  Startup the Vio communication layer.
 
179
 *
 
180
 * Notes:    This routine initializes some internal variables and buffers.
 
181
 *           This routine also deals with the interception of fatal
 
182
 *           SIGPIPE signals which are generated on some systems when a
 
183
 *           socket connection is broken by one of the send/receive pair.
 
184
 *
 
185
 *           We don't want to abort in this situation, but rather do some
 
186
 *           damage control.  Hence we register our own SIGPIPE interrupt
 
187
 *           handler in Vio_start(), and re-register it every time a SIGPIPE
 
188
 *           is intercepted.  We re-register it because some systems reset
 
189
 *           the interrupt mask after a single interrupt is generated.
 
190
 *           We un-register the SIGPIPE handler in Vio_stop().
 
191
 *
 
192
 *           To use the Vio library, you need to call Vio_start() before
 
193
 *           you make any calls to the Vio_ctor().  Calling the Vio_ctor() 
 
194
 *           (or any other Vio method) before Vio_start() generates an error.
 
195
 *           For example, you can call this routine as follows:
 
196
 *
 
197
 *               Vio_start()
 
198
 *
 
199
 * Author:   Michael Holst
 
200
 * ***************************************************************************
 
201
 */
 
202
VPUBLIC void Vio_start(void)
 
203
{
 
204
    /* repeated initializations ARE legal (no error; possibly frees memory) */
 
205
    /* VASSERT( !VIOstarted ); */
 
206
 
 
207
    /* mark as initialized */
 
208
    VIOstarted = 1;
 
209
 
 
210
    /* register the SIGPIPE handler to avoid aborts on a SIGPIPE */
 
211
    VIOregHand();
 
212
 
 
213
    /* normal return */
 
214
    return;
 
215
}
 
216
 
 
217
/*
 
218
 * ***************************************************************************
 
219
 * Routine:  Vio_stop
 
220
 *
 
221
 * Purpose:  Shutdown the Vio communication layer.
 
222
 *
 
223
 * Notes:    This routine was written primarily to deal with some
 
224
 *           communication runtime environments which require a shutdown.
 
225
 *
 
226
 * Author:   Michael Holst
 
227
 * ***************************************************************************
 
228
 */
 
229
VPUBLIC void Vio_stop(void)
 
230
{
 
231
    /* repeated de-initializations ARE legal (no error; just a no-op) */
 
232
    /* VASSERT( VIOstarted ); */
 
233
 
 
234
    /* un-initialize us */
 
235
    VIOstarted = 0;
 
236
 
 
237
    /* un-register the SIGPIPE handler */
 
238
    VIOunregHand();
 
239
 
 
240
    /* normal return */
 
241
    return;
 
242
}
 
243
 
 
244
/*
 
245
 * ***************************************************************************
 
246
 * Routine:  VIOregHand
 
247
 *
 
248
 * Purpose:  Register the signal handler with the operating system.
 
249
 *
 
250
 * Author:   Michael Holst
 
251
 * ***************************************************************************
 
252
 */
 
253
VPRIVATE void VIOregHand(void)
 
254
{
 
255
#if !defined(HAVE_WINSOCK_H)
 
256
    VASSERT( signal(SIGPIPE,&VIOsigHand) != SIG_ERR );
 
257
#endif
 
258
}
 
259
 
 
260
/*
 
261
 * ***************************************************************************
 
262
 * Routine:  VIOunregHand
 
263
 *
 
264
 * Purpose:  Un-Register the signal handler with the operating system.
 
265
 *
 
266
 * Author:   Michael Holst
 
267
 * ***************************************************************************
 
268
 */
 
269
VPRIVATE void VIOunregHand(void)
 
270
{
 
271
#if !defined(HAVE_WINSOCK_H)
 
272
    VASSERT( signal(SIGPIPE,SIG_DFL) != SIG_ERR );
 
273
#endif
 
274
}
 
275
 
 
276
/*
 
277
 * ***************************************************************************
 
278
 * Routine:  VIOsigHand
 
279
 *
 
280
 * Purpose:  Handle events such as SIGPIPE.
 
281
 *
 
282
 * Author:   Michael Holst
 
283
 * ***************************************************************************
 
284
 */
 
285
VPRIVATE void VIOsigHand(int num)
 
286
{
 
287
    /* some i/o */
 
288
    fprintf(stderr,"VIOsigHand: yow! caught a hot SIGPIPE....diffused it.\n");
 
289
 
 
290
    /* just re-register interrupt handler in case it was cleared by default */
 
291
    VIOregHand();
 
292
}
 
293
 
 
294
/*
 
295
 * ***************************************************************************
 
296
 * Routine:  VIOgethostname
 
297
 *
 
298
 * Purpose:  Get the hostname of this machine.
 
299
 *           Returns 0 on success.  Returns -1 on error.
 
300
 *
 
301
 * Author:   Michael Holst
 
302
 * ***************************************************************************
 
303
 */
 
304
VPRIVATE int VIOgethostname(char *name, unsigned int len)
 
305
{
 
306
#if defined(HAVE_WINSOCK_H)
 
307
    return gethostname(name,(int)len);
 
308
#else
 
309
    return gethostname(name,len);
 
310
#endif
 
311
}
 
312
 
 
313
/*
 
314
 * ***************************************************************************
 
315
 * Routine:  VIOstrerrno
 
316
 *
 
317
 * Purpose:  Return the error string corresponding to the error number.
 
318
 *
 
319
 * Notes:    This is a partial implementation of the "iberty" library
 
320
 *           function "strerrno" that exists on most Linux boxes.  It is
 
321
 *           simply a mapping of error number to error string.  It is
 
322
 *           very useful for debugging UNIX and INET socket code.
 
323
 *
 
324
 * Author:   Michael Holst
 
325
 * ***************************************************************************
 
326
 */
 
327
VPRIVATE const char *VIOstrerrno(int err)
 
328
{
 
329
    static char errstr[80];
 
330
 
 
331
    if      (err == EFAULT           ) strcpy(errstr,"EFAULT");
 
332
    else if (err == EINTR            ) strcpy(errstr,"EINTR");
 
333
    else if (err == EINVAL           ) strcpy(errstr,"EINVAL");
 
334
    else if (err == ENOENT           ) strcpy(errstr,"ENOENT");
 
335
    else if (err == EPIPE            ) strcpy(errstr,"EPIPE");
 
336
    else if (err == ENOMEM           ) strcpy(errstr,"ENOMEM");
 
337
    else if (err == EAGAIN           ) strcpy(errstr,"EAGAIN");
 
338
    else if (err == EBADF            ) strcpy(errstr,"EBADF");
 
339
 
 
340
#if defined(HAVE_WINSOCK_H)
 
341
    else if (err == WSAENETDOWN      ) strcpy(errstr,"WSAENETDOWN");
 
342
    else if (err == WSAEFAULT        ) strcpy(errstr,"WSAEFAULT");
 
343
    else if (err == WSAENOTCONN      ) strcpy(errstr,"WSAENOTCONN");
 
344
    else if (err == WSAEINTR         ) strcpy(errstr,"WSAEINTR");
 
345
    else if (err == WSAEINPROGRESS   ) strcpy(errstr,"WSAEINPROGRESS");
 
346
    else if (err == WSAENETRESET     ) strcpy(errstr,"WSAENETRESET");
 
347
    else if (err == WSAENOTSOCK      ) strcpy(errstr,"WSAENOTSOCK");
 
348
    else if (err == WSAEOPNOTSUPP    ) strcpy(errstr,"WSAEOPNOTSUPP");
 
349
    else if (err == WSAESHUTDOWN     ) strcpy(errstr,"WSAESHUTDOWN");
 
350
    else if (err == WSAEWOULDBLOCK   ) strcpy(errstr,"WSAEWOULDBLOCK");
 
351
    else if (err == WSAEMSGSIZE      ) strcpy(errstr,"WSAEMSGSIZE");
 
352
    else if (err == WSAEINVAL        ) strcpy(errstr,"WSAEINVAL");
 
353
    else if (err == WSAETIMEDOUT     ) strcpy(errstr,"WSAETIMEDOUT");
 
354
    else if (err == WSAECONNABORTED  ) strcpy(errstr,"WSAECONNABORTED");
 
355
    else if (err == WSAECONNREFUSED  ) strcpy(errstr,"WSAECONNREFUSED");
 
356
    else if (err == WSAECONNRESET    ) strcpy(errstr,"WSAECONNRESET");
 
357
    else if (err == WSANOTINITIALISED) strcpy(errstr,"WSANOTINITIALISED");
 
358
#else
 
359
    else if (err == ENETDOWN         ) strcpy(errstr,"ENETDOWN");
 
360
    else if (err == ENOTCONN         ) strcpy(errstr,"ENOTCONN");
 
361
    else if (err == EINPROGRESS      ) strcpy(errstr,"EINPROGRESS");
 
362
    else if (err == ENETRESET        ) strcpy(errstr,"ENETRESET");
 
363
    else if (err == ENOTSOCK         ) strcpy(errstr,"ENOTSOCK");
 
364
    else if (err == EOPNOTSUPP       ) strcpy(errstr,"EOPNOTSUPP");
 
365
    else if (err == ESHUTDOWN        ) strcpy(errstr,"ESHUTDOWN");
 
366
    else if (err == EWOULDBLOCK      ) strcpy(errstr,"EWOULDBLOCK");
 
367
    else if (err == EMSGSIZE         ) strcpy(errstr,"EMSGSIZE");
 
368
    else if (err == ETIMEDOUT        ) strcpy(errstr,"ETIMEDOUT");
 
369
    else if (err == ECONNABORTED     ) strcpy(errstr,"ECONNABORTED");
 
370
    else if (err == ECONNREFUSED     ) strcpy(errstr,"ECONNREFUSED");
 
371
    else if (err == ECONNRESET       ) strcpy(errstr,"ECONNRESET");
 
372
    else if (err == ENOBUFS          ) strcpy(errstr,"ENOBUFS");
 
373
#endif
 
374
 
 
375
    else sprintf(errstr,"VIO_UNKNOWN_ERROR(%d)",err);
 
376
    return errstr; 
 
377
}
 
378
 
 
379
/*
 
380
 * ***************************************************************************
 
381
 * Routine:  Vio_ctor
 
382
 *
 
383
 * Purpose:  Construct the [sdio/file/buff/unix/inet] container object.
 
384
 *
 
385
 * Author:   Michael Holst
 
386
 * ***************************************************************************
 
387
 */
 
388
VPUBLIC Vio* Vio_ctor(const char *socktype, const char *datafrmt, 
 
389
    const char *hostname, const char *filename, const char *rwkey)
 
390
{
 
391
    Vio *thee = VNULL;
 
392
 
 
393
    /* make sure Vio was started */
 
394
    VJMPERR1( VIOstarted );
 
395
 
 
396
    thee = (Vio*)calloc( 1, sizeof(Vio) );
 
397
    VJMPERR2( thee != VNULL );
 
398
    VJMPERR3( Vio_ctor2(thee, socktype, datafrmt, hostname, filename, rwkey) );
 
399
 
 
400
    /* normal return */
 
401
    return thee;
 
402
 
 
403
  VERROR1:
 
404
    fprintf(stderr,"Vio_ctor: Vio library has not been started.\n");
 
405
    return VNULL;
 
406
 
 
407
  VERROR2:
 
408
    fprintf(stderr,"Vio_ctor: malloc of Vio structure failed.\n");
 
409
    return VNULL;
 
410
 
 
411
  VERROR3:
 
412
    fprintf(stderr,"Vio_ctor: Vio_ctor2() failed.\n");
 
413
    Vio_dtor(&thee);
 
414
    return VNULL;
 
415
}
 
416
 
 
417
/*
 
418
 * ***************************************************************************
 
419
 * Routine:  Vio_ctor2
 
420
 *
 
421
 * Purpose:  Construct the [sdio/file/buff/unix/inet] container object.
 
422
 *
 
423
 * Author:   Michael Holst
 
424
 * ***************************************************************************
 
425
 */
 
426
VPUBLIC int Vio_ctor2(Vio *thee, const char *socktype, const char *datafrmt, 
 
427
    const char *hostname, const char *filename, const char *rwkey)
 
428
{
 
429
    int n, ival;
 
430
    char host[80];
 
431
    struct linger ling;
 
432
    unsigned int len;
 
433
    struct hostent *hpTmp;
 
434
#if defined(HAVE_WINSOCK_H)
 
435
    WSADATA wsaData;
 
436
#endif
 
437
#if defined(HAVE_SYS_UN_H)
 
438
    char username[80];
 
439
#endif
 
440
 
 
441
    /* make sure Vio was started */
 
442
    VJMPERR1( VIOstarted );
 
443
 
 
444
    /* initialize all Vio fields */
 
445
    thee->type     = VIO_NO_TYPE;
 
446
    thee->frmt     = VIO_NO_FRMT;
 
447
    thee->rwkey    = VIO_NO_RW;
 
448
    thee->error    = 0;
 
449
    thee->dirty    = 0;
 
450
    thee->fp       = VNULL;
 
451
    thee->axdr     = VNULL;
 
452
    thee->so       = -1;
 
453
    thee->soc      = -1;
 
454
    thee->name     = VNULL;
 
455
 
 
456
    /* initialize the internal buffer (for BUFF datatype) */
 
457
    thee->VIObuffer = VNULL;
 
458
    thee->VIObufferLen = 0;
 
459
    thee->VIObufferPtr = 0;
 
460
 
 
461
    /* initialize the socktype field */
 
462
    if (!strcmp(socktype,"SDIO")) {
 
463
        thee->type = VIO_SDIO;
 
464
    } else if (!strcmp(socktype,"FILE")) {
 
465
        thee->type = VIO_FILE;
 
466
    } else if (!strcmp(socktype,"BUFF")) {
 
467
        thee->type = VIO_BUFF;
 
468
    } else if (!strcmp(socktype,"UNIX")) {
 
469
        thee->type = VIO_UNIX;
 
470
    } else if (!strcmp(socktype,"INET")) {
 
471
        thee->type = VIO_INET;
 
472
    } else {
 
473
        fprintf(stderr,"Vio_ctor2: Incorrect socktype given <%s>\n",socktype);
 
474
        VJMPERR2( 0 );
 
475
    }
 
476
 
 
477
    /* initialize the datafrmt field */
 
478
    if (!strcmp(datafrmt,"ASC")) {
 
479
        thee->frmt = VIO_ASC;
 
480
    } else if (!strcmp(datafrmt,"XDR")) {
 
481
        thee->frmt = VIO_XDR;
 
482
    } else {
 
483
        fprintf(stderr,"Vio_ctor2: Incorrect datafrmt given <%s>\n", datafrmt);
 
484
        VJMPERR2( 0 );
 
485
    }
 
486
 
 
487
    /* initialize the r/w field */
 
488
    if (!strcmp(rwkey,"r")) {
 
489
        thee->rwkey = VIO_R;
 
490
    } else if (!strcmp(rwkey,"w")) {
 
491
        thee->rwkey = VIO_W;
 
492
    } else {
 
493
        fprintf(stderr,"Vio_ctor2: Incorrect rwkey given <%s>\n", rwkey);
 
494
        VJMPERR2( 0 );
 
495
    }
 
496
 
 
497
    /* need to call this stupid Win32 function before gethostname... */
 
498
#if defined(HAVE_WINSOCK_H)
 
499
    if ( WSAStartup(0x0101, &wsaData) != 0 ) {
 
500
        fprintf(stderr, "Vio_ctor2: WSAStartup fail INET sock <%s>"
 
501
            " dueto <%s>\n", thee->file,VIOstrerrno(errno));
 
502
        VJMPERR2( 0 );
 
503
    }
 
504
#endif
 
505
 
 
506
    /* get "my" local hostname */
 
507
    if ((VIOgethostname(thee->lhost,sizeof(thee->lhost))) < 0) {
 
508
        fprintf(stderr,
 
509
            "Vio_ctor2: Gethostname fail INET sock <%s> dueto <%s>\n",
 
510
            thee->file, VIOstrerrno(errno));
 
511
        strcpy(thee->lhost,"unknown");
 
512
    } else if ((hpTmp=gethostbyname(thee->lhost))==VNULL) {
 
513
        fprintf(stderr,
 
514
            "Vio_ctor2: Gethostbyname fail INET sock <%s> dueto <%s>\n",
 
515
            thee->file, VIOstrerrno(errno));
 
516
        strcpy(thee->lhost,"unknown");
 
517
    } else strcpy(thee->lhost,hpTmp->h_name);
 
518
 
 
519
    /* default remote hostname */
 
520
    strcpy(thee->rhost,"unknown");
 
521
 
 
522
    /* initialize the buffer space */
 
523
    Vio_initIoPutBuffers(thee);
 
524
 
 
525
    /* SDIO READ/WRITE SETUP */
 
526
    if (thee->type==VIO_SDIO) {
 
527
 
 
528
        if (thee->rwkey==VIO_R) {
 
529
            thee->fp = stdin;
 
530
        } else { /* (thee->rwkey==VIO_W) */
 
531
            thee->fp = stdout;
 
532
        }
 
533
        VJMPERR2( thee->fp != VNULL );
 
534
 
 
535
    /* FILE READ/WRITE SETUP */
 
536
    } else if (thee->type==VIO_FILE) {
 
537
 
 
538
        /* filename is the i/o file name */
 
539
        strncpy(thee->file, filename, 80);
 
540
        if (thee->rwkey==VIO_R) {
 
541
            thee->fp = fopen(thee->file, "r");
 
542
        } else { /* (thee->rwkey==VIO_W) */
 
543
            thee->fp = fopen(thee->file, "w");
 
544
        }
 
545
        VJMPERR2( thee->fp != VNULL );
 
546
 
 
547
    /* BUFF READ/WRITE SETUP */
 
548
    } else if (thee->type==VIO_BUFF) {
 
549
 
 
550
        /* filename is the internal buffer number for the buffer */
 
551
        thee->VIObufferPtr = 0;
 
552
 
 
553
    /* UNIX SOCKET READ/WRITE SETUP */
 
554
    } else if (thee->type==VIO_UNIX) {
 
555
 
 
556
#if defined(HAVE_SYS_UN_H)
 
557
 
 
558
        /* filename is socketName-userName in the directory /tmp */
 
559
 
 
560
        VASSERT( Vnm_getuser(username, sizeof(username)) );
 
561
        sprintf(thee->file, "/tmp/%s-%s", filename, username);
 
562
 
 
563
        /* create the socket address structure */
 
564
        thee->name = (struct sockaddr_un *)
 
565
            calloc( 1, sizeof(struct sockaddr_un) );
 
566
        VJMPERR2( thee->name != VNULL );
 
567
 
 
568
        /* Get a socket structure */
 
569
        if ((thee->so=socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
 
570
            fprintf(stderr,"Vio_ctor2: fail to find UNIX sock dueto <%s>.\n",
 
571
                VIOstrerrno(errno));
 
572
            VJMPERR2( 0 );
 
573
        } else {
 
574
 
 
575
            /* set REUSEADDR so sockets can be closed and reopened */
 
576
            ival = 1;  /* just need a nonzero value */
 
577
            if ( setsockopt(thee->so,SOL_SOCKET,SO_REUSEADDR,
 
578
              (void*)&ival,sizeof(ival)) < 0 ) {
 
579
                fprintf(stderr, "Vio_ctor2: Setsockopt1 fail UNIX sock <%s>"
 
580
                   " dueto <%s>\n", thee->file, VIOstrerrno(errno));
 
581
                VJMPERR2( 0 );
 
582
            }
 
583
 
 
584
            /* turn on LINGER so WRITES complete before socks close */
 
585
            ling.l_onoff  = 1;   /* just need a nonzero value */
 
586
            ling.l_linger = 30;  /* linger time in seconds */
 
587
            if ( setsockopt(thee->so,SOL_SOCKET,SO_LINGER,
 
588
              (void*)&ling,sizeof(ling)) < 0) {
 
589
                fprintf(stderr, "Vio_ctor2: Setsockopt2 fail UNIX sock <%s>"
 
590
                   " dueto <%s>\n", thee->file, VIOstrerrno(errno));
 
591
                VJMPERR2( 0 );
 
592
            }
 
593
 
 
594
            /* Setup for the socket */
 
595
            memset(thee->name, '\0', sizeof(struct sockaddr_un));
 
596
            ((struct sockaddr_un *)(thee->name))->sun_family = AF_UNIX;
 
597
            strcpy(((struct sockaddr_un *)(thee->name))->sun_path,
 
598
                thee->file);
 
599
 
 
600
            /* if we are reader, WE are responsible for creating socket */
 
601
            /* the reader must do: (unlink/)setsockopt/bind/listen */
 
602
            if (thee->rwkey==VIO_R) {
 
603
 
 
604
                /* define socket file; remove previous socket */
 
605
                unlink(thee->file);
 
606
 
 
607
                /* determine structure size; AF_UNIX is variable length */
 
608
                len = sizeof(((struct sockaddr_un *)
 
609
                              (thee->name))->sun_family) 
 
610
                    + strlen(((struct sockaddr_un *)
 
611
                              (thee->name))->sun_path);
 
612
 
 
613
                /* Bind socket to address (must setsockopts before bind) */
 
614
                if (bind(thee->so,(struct sockaddr *)(thee->name),len)<0) {
 
615
                    fprintf(stderr,
 
616
                        "Vio_ctor2: Bind fail UNIX sock <%s> dueto <%s>\n",
 
617
                        thee->file, VIOstrerrno(errno));
 
618
                    VJMPERR2( 0 );
 
619
                } else {
 
620
 
 
621
                    /* Tell socket to start listening for connections */
 
622
                    if (listen(thee->so,5) < 0) {
 
623
                        fprintf(stderr,
 
624
                        "Vio_ctor2: List fail UNIX sock <%s> dueto <%s>\n",
 
625
                        thee->file, VIOstrerrno(errno));
 
626
                        VJMPERR2( 0 );
 
627
                    }
 
628
                }
 
629
            /*
 
630
             * if we got to here, we can assume reader has done
 
631
             * all of: (unlink/)setsockopt/bind/listen
 
632
             */
 
633
            }
 
634
        }
 
635
#endif
 
636
 
 
637
    /* INET SOCKET READ/WRITE SETUP */
 
638
    } else if (thee->type==VIO_INET) {
 
639
 
 
640
        /* filename is the port number for the socket */
 
641
        strncpy(thee->file, filename, 80);
 
642
 
 
643
        /* create the socket address structure */
 
644
        thee->name = (struct sockaddr_in *)
 
645
            calloc( 1, sizeof(struct sockaddr_in) );
 
646
        VJMPERR2( thee->name != VNULL );
 
647
 
 
648
        /* Look for sockets */
 
649
        if ((thee->so=socket(AF_INET, SOCK_STREAM, 0)) < 0) {
 
650
            fprintf(stderr,"Vio_ctor2: fail to find INET sock dueto <%s>\n",
 
651
                VIOstrerrno(errno));
 
652
            VJMPERR2( 0 );
 
653
        } else {
 
654
 
 
655
            /* set REUSEADDR so sockets can be closed and reopened */
 
656
            ival = 1;  /* just need a nonzero value */
 
657
            if ( setsockopt(thee->so,SOL_SOCKET,SO_REUSEADDR,
 
658
              (void*)&ival,sizeof(ival)) < 0 ) {
 
659
                fprintf(stderr, "Vio_ctor2: Setsockopt3 fail INET sock <%s>"
 
660
                   " dueto <%s>\n", thee->file, VIOstrerrno(errno));
 
661
                VJMPERR2( 0 );
 
662
            }
 
663
 
 
664
            /* turn on LINGER so WRITES complete before sockets close */
 
665
            ling.l_onoff  = 1;   /* just need a nonzero value */
 
666
            ling.l_linger = 30;  /* linger time in seconds */
 
667
            if ( setsockopt(thee->so,SOL_SOCKET,SO_LINGER,
 
668
              (void*)&ling,sizeof(ling)) < 0 ) {
 
669
                fprintf(stderr, "Vio_ctor2: Setsockopt4 fail INET sock <%s>"
 
670
                   " dueto <%s>\n", thee->file, VIOstrerrno(errno));
 
671
                VJMPERR2( 0 );
 
672
            }
 
673
 
 
674
            /* Setup for the socket */
 
675
            memset(thee->name, '\0', sizeof(struct sockaddr_in));
 
676
            ((struct sockaddr_in *)(thee->name))->sin_family = AF_INET;
 
677
            ((struct sockaddr_in *)(thee->name))->sin_port
 
678
                = htons( (unsigned short) (VPORTNUMBER + atoi(thee->file)) );
 
679
 
 
680
            /* if we are the reader, WE must create the socket */
 
681
            /* the reader must do: setsockopt/bind/listen */
 
682
            if (thee->rwkey==VIO_R) {
 
683
 
 
684
                /* use wildcard address */
 
685
                n = INADDR_ANY;
 
686
                memcpy(&((struct sockaddr_in *)(thee->name))->sin_addr,
 
687
                    &n, sizeof(long));
 
688
 
 
689
                /* determine structure size; AF_INET is fixed length */
 
690
                len = sizeof(struct sockaddr_in);
 
691
 
 
692
                /* Bind socket to address (must setsockopts before bind) */
 
693
                if (bind(thee->so,(struct sockaddr *)(thee->name),len)<0) {
 
694
                    fprintf(stderr,
 
695
                        "Vio_ctor2: Bind fail INET sock <%s> dueto <%s>\n",
 
696
                        thee->file, VIOstrerrno(errno));
 
697
                    VJMPERR2( 0 );
 
698
                } else {
 
699
 
 
700
                    /* Tell socket to start listening for connections */
 
701
                    if (listen(thee->so,5) < 0) {
 
702
                        fprintf(stderr,
 
703
                            "Vio_ctor2: List fail INET sock <%s> dueto <%s>\n",
 
704
                            thee->file, VIOstrerrno(errno));
 
705
                        VJMPERR2( 0 );
 
706
                    }
 
707
                }
 
708
 
 
709
            /* assume reader has done: setsockopt/bind/listen */
 
710
            } else {
 
711
 
 
712
                /* network address of port -- "localhost" means WE have port */
 
713
                if (!strcmp(hostname,"localhost")) {
 
714
                    strcpy(host,thee->lhost);
 
715
                } else {
 
716
                    strcpy(host,hostname);
 
717
                }
 
718
 
 
719
                /* get IP address corresponding to this server hostname */
 
720
                if ((hpTmp=gethostbyname(host))==VNULL) {
 
721
                    fprintf(stderr,
 
722
                        "Vio_ctor2: Gethostbyname fail INET sock <%s>"
 
723
                        " dueto <%s>\n", thee->file, VIOstrerrno(errno));
 
724
                    VJMPERR2( 0 );
 
725
                } else {
 
726
 
 
727
                    /* just need to save address of host that has socket */
 
728
                    memcpy(
 
729
                        &(((struct sockaddr_in *)(thee->name))->sin_addr),
 
730
                        hpTmp->h_addr_list[0], (unsigned int)hpTmp->h_length);
 
731
 
 
732
                    /* save the hostname for the port for later i/o */
 
733
                    strcpy(thee->rhost,hpTmp->h_name);
 
734
                }
 
735
            }
 
736
        }
 
737
    }
 
738
 
 
739
    /* initialize <asc,xdr> datastructures; must do almost at the end */
 
740
    if (thee->frmt==VIO_ASC) {
 
741
        thee->axdr = (ASC*)calloc( 1, sizeof(ASC) );
 
742
        VJMPERR2( thee->axdr != VNULL );
 
743
        if (thee->rwkey==VIO_R) {
 
744
            ascmem_create(thee->axdr, thee->ioBuffer, VMAX_BUFSIZE, ASC_DECODE);
 
745
        } else { /* if (thee->rwkey==VIO_W) */
 
746
            ascmem_create(thee->axdr, thee->ioBuffer, VMAX_BUFSIZE, ASC_ENCODE);
 
747
        }
 
748
    } else if (thee->frmt==VIO_XDR) {
 
749
        thee->axdr = (XDR*)calloc( 1, sizeof(XDR) );
 
750
        VJMPERR2( thee->axdr != VNULL );
 
751
        if (thee->rwkey==VIO_R) {
 
752
            xdrmem_create(thee->axdr, thee->ioBuffer, VMAX_BUFSIZE, XDR_DECODE);
 
753
        } else { /* if (thee->rwkey==VIO_W) */
 
754
            xdrmem_create(thee->axdr, thee->ioBuffer, VMAX_BUFSIZE, XDR_ENCODE);
 
755
        }
 
756
    }
 
757
 
 
758
    /* lastly: default white/comment char sets (careful! propogates to axdr) */
 
759
    Vio_setWhiteChars(thee, VIOwhiteChars);
 
760
    Vio_setCommChars(thee,  VIOcommChars);
 
761
 
 
762
    /* return without error */
 
763
    return 1;
 
764
 
 
765
  VERROR1:
 
766
    fprintf(stderr,"Vio_ctor2: Vio library has not been started.\n");
 
767
    return 0;
 
768
 
 
769
  VERROR2:
 
770
    fprintf(stderr,"Vio_ctor2: some error occurred.\n");
 
771
    return 0;
 
772
}
 
773
 
 
774
/*
 
775
 * ***************************************************************************
 
776
 * Routine:  Vio_dtor
 
777
 *
 
778
 * Purpose:  Destroy the [sdio/file/buff/unix/inet] container object.
 
779
 *
 
780
 * Author:   Michael Holst
 
781
 * ***************************************************************************
 
782
 */
 
783
VPUBLIC void Vio_dtor(Vio **thee)
 
784
{
 
785
    if ((*thee) != VNULL) {
 
786
        if ((*thee)->VIObuffer != VNULL) {
 
787
            free( (*thee)->VIObuffer );
 
788
            (*thee)->VIObuffer = VNULL;
 
789
        }
 
790
        Vio_dtor2(*thee);
 
791
        free( (*thee) );
 
792
        (*thee) = VNULL;
 
793
    }
 
794
}
 
795
 
 
796
/*
 
797
 * ***************************************************************************
 
798
 * Routine:  Vio_dtor2
 
799
 *
 
800
 * Purpose:  Destroy the [sdio/file/buff/unix/inet] container object.
 
801
 *
 
802
 * Author:   Michael Holst
 
803
 * ***************************************************************************
 
804
 */
 
805
VPUBLIC void Vio_dtor2(Vio *thee)
 
806
{
 
807
    if (thee != VNULL) {
 
808
 
 
809
        /* free the <ASC,XDR> structures */
 
810
        if ( thee->axdr != VNULL ) {
 
811
            if ( thee->frmt == VIO_ASC ) {
 
812
                asc_destroy( (ASC*)(thee->axdr) );
 
813
            } else if ( thee->frmt == VIO_XDR ) {
 
814
                xdr_destroy( (XDR*)(thee->axdr) );
 
815
            }
 
816
            free( thee->axdr );
 
817
            thee->axdr = VNULL;
 
818
        }
 
819
 
 
820
        /* finish up */
 
821
        if (thee->type==VIO_SDIO) {
 
822
            /* no-op */
 
823
        } else if (thee->type==VIO_FILE) {
 
824
            if ( thee->fp != VNULL ) {
 
825
                if ( fclose(thee->fp) != 0 ) {
 
826
                    fprintf(stderr, "Vio_dtor2: fclose fail device <%s>"
 
827
                        " dueto <%s>\n", thee->file,VIOstrerrno(errno));
 
828
                }
 
829
            }
 
830
        } else if (thee->type==VIO_BUFF) {
 
831
            /* CMIKE: WHAT ABOUT FREEING THE BUFFER SPACE??? */
 
832
            thee->VIObufferPtr = 0;
 
833
        } else if ( (thee->type==VIO_UNIX)
 
834
                 || (thee->type==VIO_INET) ) {
 
835
            if ( thee->soc >= 0 ) {
 
836
#if defined(HAVE_WINSOCK_H)
 
837
                if ( closesocket(thee->soc) != 0 ) {
 
838
                    fprintf(stderr, "Vio_dtor2: closesocket1 fail device <%s>"
 
839
                        " dueto <%s>\n", thee->file,
 
840
                        VIOstrerrno(errno));
 
841
                }
 
842
#else
 
843
                if ( close(thee->soc) != 0 ) {
 
844
                    fprintf(stderr, "Vio_dtor2: close1 fail device <%s>"
 
845
                        " dueto <%s>\n", thee->file,
 
846
                    VIOstrerrno(errno));
 
847
                }
 
848
#endif
 
849
            }
 
850
            if ( thee->so >= 0 ) {
 
851
#if defined(HAVE_WINSOCK_H)
 
852
                if ( closesocket(thee->so) != 0 ) {
 
853
                    fprintf(stderr, "Vio_dtor2: closesocket2 fail device <%s>"
 
854
                        " dueto <%s>\n", thee->file,
 
855
                        VIOstrerrno(errno));
 
856
                }
 
857
#else
 
858
                if ( close(thee->so) != 0 ) {
 
859
                    fprintf(stderr, "Vio_dtor2: close2 fail device <%s>"
 
860
                        " dueto <%s>\n", thee->file,
 
861
                        VIOstrerrno(errno));
 
862
                }
 
863
#endif
 
864
            }
 
865
 
 
866
            /* remove the device file for domain sockets */
 
867
            if (thee->type==VIO_UNIX)
 
868
                if (thee->rwkey==VIO_R)
 
869
                    unlink(thee->file);
 
870
 
 
871
        } else {
 
872
            fprintf(stderr,"Vio_dtor2: Bad type found <%d>\n", thee->type);
 
873
        }
 
874
 
 
875
        if ( (thee->type==VIO_UNIX)
 
876
          || (thee->type==VIO_INET) ) {
 
877
            if (thee->name != VNULL) {
 
878
                free( thee->name );
 
879
            }
 
880
            thee->name = VNULL;
 
881
        }
 
882
 
 
883
        /* we called WSAStartup() in constructor; must always be paired */
 
884
#if defined(HAVE_WINSOCK_H)
 
885
        WSACleanup();
 
886
#endif
 
887
    }
 
888
}
 
889
 
 
890
/*
 
891
 * ***************************************************************************
 
892
 * Routine:  Vio_setWhiteChars
 
893
 *
 
894
 * Purpose:  Define the white character set.
 
895
 *
 
896
 * Author:   Michael Holst
 
897
 * ***************************************************************************
 
898
 */
 
899
VPUBLIC void Vio_setWhiteChars(Vio *thee, char *whiteChars)
 
900
{
 
901
    if (thee != VNULL) {
 
902
        strncpy(thee->whiteChars, whiteChars, VMAX_ARGNUM);
 
903
 
 
904
        /* propogate the character set down to the ASC structure */
 
905
        VASSERT( thee->axdr != VNULL );
 
906
        if (thee->frmt == VIO_ASC) {
 
907
            asc_setWhiteChars(thee->axdr, whiteChars);
 
908
        } else if (thee->frmt == VIO_XDR) {
 
909
#if !defined(HAVE_XDR)
 
910
            asc_setWhiteChars(thee->axdr, whiteChars);
 
911
#endif
 
912
        } else { VASSERT( 0 ); }
 
913
    }
 
914
}
 
915
 
 
916
/*
 
917
 * ***************************************************************************
 
918
 * Routine:  Vio_setCommChars
 
919
 *
 
920
 * Purpose:  Define the comment character set.
 
921
 *
 
922
 * Author:   Michael Holst
 
923
 * ***************************************************************************
 
924
 */
 
925
VPUBLIC void Vio_setCommChars(Vio *thee, char *commChars)
 
926
{
 
927
    if (thee != VNULL) {
 
928
        strncpy(thee->commChars, commChars, VMAX_ARGNUM);
 
929
 
 
930
        /* propogate the character set down to the ASC structure */
 
931
        VASSERT( thee->axdr != VNULL );
 
932
        if (thee->frmt == VIO_ASC) {
 
933
            asc_setCommChars(thee->axdr, commChars);
 
934
        } else if (thee->frmt == VIO_XDR) {
 
935
#if !defined(HAVE_XDR)
 
936
            asc_setCommChars(thee->axdr, commChars);
 
937
#endif
 
938
        } else { VASSERT( 0 ); }
 
939
    }
 
940
}
 
941
 
 
942
/*
 
943
 * ***************************************************************************
 
944
 * Routine:  Vio_accept
 
945
 *
 
946
 * Purpose:  Accept any waiting connect attempt to our socket on our machine.
 
947
 *
 
948
 * Notes:    The nonblock parameter has the following interpretation:
 
949
 *           (Only for <UNIX/INET>; othewise it is ignored.)
 
950
 *
 
951
 *               nonblock==0  ==> block until a connect is attempted
 
952
 *               nonblock==1  ==> DO NOT block at all
 
953
 *
 
954
 * Author:   Michael Holst
 
955
 * ***************************************************************************
 
956
 */
 
957
VPUBLIC int Vio_accept(Vio *thee, int nonblock)
 
958
{
 
959
    int rc;
 
960
 
 
961
#if defined(HAVE_WINSOCK_H)
 
962
    unsigned long  blockKey;
 
963
#else
 
964
    int flags = 0;
 
965
    struct sockaddr_in peer;
 
966
    struct hostent *hpTmp;
 
967
#endif
 
968
 
 
969
#if defined(ACCEPT_USES_ULONG)
 
970
    unsigned long len;
 
971
#elif defined(ACCEPT_USES_UINT)
 
972
    unsigned int len;
 
973
#elif defined(ACCEPT_USES_INT)
 
974
    int len;
 
975
#else
 
976
    unsigned int len;
 
977
#endif
 
978
 
 
979
    /* reset error tag */
 
980
    thee->error = 0;
 
981
 
 
982
    thee->soc = -1;
 
983
    rc = -1;
 
984
 
 
985
    Vio_initIoPutBuffers(thee);
 
986
    VJMPERR2( thee->rwkey == VIO_R );
 
987
 
 
988
    if ( (thee->type==VIO_SDIO)
 
989
      || (thee->type==VIO_FILE)
 
990
      || (thee->type==VIO_BUFF) ) {
 
991
 
 
992
        /* ONLY for file i/o, we need to look at and set the dirty bit */
 
993
        /* (this keeps us from reading the file twice) */
 
994
        if (thee->type==VIO_FILE) {
 
995
            if ((!thee->dirty) && (!feof(thee->fp))) {
 
996
                thee->dirty = 1;
 
997
                rc = 1;
 
998
            }
 
999
        } else {
 
1000
            rc = 1;
 
1001
        }
 
1002
 
 
1003
    } else if (thee->type==VIO_UNIX) {
 
1004
 
 
1005
#if defined(HAVE_SYS_UN_H)
 
1006
        /* Make this a non-blocking socket just for the accept call */
 
1007
        if (nonblock) {
 
1008
            flags = fcntl( thee->so, F_GETFL, 0 );
 
1009
            fcntl( thee->so, F_SETFL, flags | VO_NONBLOCK );
 
1010
        }
 
1011
 
 
1012
        /* accept */
 
1013
        len = sizeof(struct sockaddr_un);
 
1014
        rc = accept(thee->so,(struct sockaddr *)(thee->name),&len);
 
1015
        thee->soc = rc;
 
1016
        if ((!nonblock) && (rc < 0)) {
 
1017
            fprintf(stderr, "Vio_accept: Accept fail UNIX sock <%s>"
 
1018
                " dueto <%s>\n", thee->file, VIOstrerrno(errno));
 
1019
            VJMPERR2( 0 );
 
1020
        }
 
1021
 
 
1022
        /* restore blocking -- must nonblock for LINGER to work! */
 
1023
        if (nonblock) {
 
1024
            fcntl( thee->so, F_SETFL, flags );
 
1025
        }
 
1026
#endif
 
1027
 
 
1028
    } else if (thee->type==VIO_INET) {
 
1029
 
 
1030
        /* Make this non-blocking socket just for accept call */
 
1031
        if (nonblock) {
 
1032
#if defined(HAVE_WINSOCK_H)
 
1033
            blockKey = 1;
 
1034
            if ( ioctlsocket( thee->so, FIONBIO, &blockKey ) != 0 ) {
 
1035
                fprintf(stderr, "Vio_accept: Ioctlsocket1 fail INET sock <%s>"
 
1036
                   " dueto <%s>\n", thee->file, VIOstrerrno(errno));
 
1037
                VJMPERR2( 0 );
 
1038
            }
 
1039
#else
 
1040
            flags = fcntl( thee->so, F_GETFL, 0 );
 
1041
            fcntl( thee->so, F_SETFL, flags | VO_NONBLOCK );
 
1042
#endif
 
1043
        }
 
1044
 
 
1045
        len = sizeof(struct sockaddr_in);
 
1046
        rc = accept(thee->so, (struct sockaddr *)(thee->name), &len);
 
1047
        thee->soc = rc;
 
1048
        if ((!nonblock) && (rc < 0)) {
 
1049
            fprintf(stderr, "Vio_accept: Accept fail INET sock <%s>"
 
1050
                " dueto <%s>\n", thee->file, VIOstrerrno(errno));
 
1051
            VJMPERR2( 0 );
 
1052
        }
 
1053
 
 
1054
        /* restore blocking -- must nonblock for LINGER to work! */
 
1055
        if (nonblock) {
 
1056
#if defined(HAVE_WINSOCK_H)
 
1057
            blockKey = 0;
 
1058
            if ( ioctlsocket( thee->so, FIONBIO, &blockKey ) != 0 ) {
 
1059
                fprintf(stderr, "Vio_accept: Ioctlsocket2 fail INET sock <%s>"
 
1060
                   " dueto <%s>\n", thee->file, VIOstrerrno(errno));
 
1061
                VJMPERR2( 0 );
 
1062
            }
 
1063
#else
 
1064
            fcntl( thee->so, F_SETFL, flags );
 
1065
#endif
 
1066
        }
 
1067
 
 
1068
        /* if we found a writer, get his hostname (just for i/o) */
 
1069
        if (rc >= 0) {
 
1070
#if defined(HAVE_WINSOCK_H)
 
1071
            strcpy(thee->rhost,"unknown");
 
1072
#else
 
1073
            len = sizeof(struct sockaddr_in);
 
1074
            if (getpeername(thee->soc,(struct sockaddr *)(&peer),&len)<0) {
 
1075
                fprintf(stderr, "Vio_accept: Getpeername fail INET <%s>"
 
1076
                    " dueto <%s>\n", thee->file, VIOstrerrno(errno));
 
1077
                VJMPERR2( 0 );
 
1078
            } else if (VNULL==(hpTmp=gethostbyname(inet_ntoa(peer.sin_addr)))){
 
1079
                fprintf(stderr, "Vio_accept: Gethostbyname fail INET <%s>"
 
1080
                    " dueto <%s>\n", thee->file, VIOstrerrno(errno));
 
1081
                VJMPERR2( 0 );
 
1082
            } else {
 
1083
                strcpy(thee->rhost,hpTmp->h_name);
 
1084
            }
 
1085
#endif
 
1086
        }
 
1087
 
 
1088
    } else {
 
1089
        fprintf(stderr,"Vio_accept: Bad type found <%d>\n", thee->type);
 
1090
        VJMPERR2( 0 );
 
1091
    }
 
1092
 
 
1093
    /* normal return */
 
1094
    return rc;
 
1095
 
 
1096
  VERROR2:
 
1097
    thee->error = 1;
 
1098
    return -1;
 
1099
}
 
1100
 
 
1101
/*
 
1102
 * ***************************************************************************
 
1103
 * Routine:  Vio_acceptFree
 
1104
 *
 
1105
 * Purpose:  Free the socket child that was used for the last accept.
 
1106
 *
 
1107
 * Author:   Michael Holst
 
1108
 * ***************************************************************************
 
1109
 */
 
1110
VPUBLIC void Vio_acceptFree(Vio *thee)
 
1111
{
 
1112
    /* VJMPERR2( !thee->error ); */  /* Need to close the socket... */
 
1113
    VJMPERR2( thee->rwkey == VIO_R );
 
1114
 
 
1115
    if ( (thee->type==VIO_SDIO)
 
1116
      || (thee->type==VIO_FILE)
 
1117
      || (thee->type==VIO_BUFF) ) {
 
1118
        /* no-op */
 
1119
    } else if ( (thee->type==VIO_UNIX)
 
1120
             || (thee->type==VIO_INET) ) {
 
1121
        if ( thee->soc >= 0 ) {
 
1122
#if defined(HAVE_WINSOCK_H)
 
1123
            if ( closesocket(thee->soc) != 0 ) {
 
1124
                fprintf(stderr, "Vio_acceptFree: closesocket fail device <%s>"
 
1125
                    " dueto <%s>\n", thee->file,VIOstrerrno(errno));
 
1126
                VJMPERR2( 0 );
 
1127
            }
 
1128
#else
 
1129
            if ( close(thee->soc) != 0 ) {
 
1130
                fprintf(stderr, "Vio_acceptFree: close fail device <%s>"
 
1131
                    " dueto <%s>\n", thee->file,VIOstrerrno(errno));
 
1132
                VJMPERR2( 0 );
 
1133
            }
 
1134
#endif
 
1135
        }
 
1136
    } else {
 
1137
        fprintf(stderr,"Vio_acceptFree: Bad type found <%d>\n", thee->type);
 
1138
        VJMPERR2( 0 );
 
1139
    }
 
1140
 
 
1141
    thee->soc = -1;
 
1142
 
 
1143
    /* normal return */
 
1144
    Vio_initIoPutBuffers(thee);
 
1145
    return;
 
1146
 
 
1147
  VERROR2:
 
1148
    Vio_initIoPutBuffers(thee);
 
1149
    thee->error = 1;
 
1150
    return;
 
1151
}
 
1152
 
 
1153
/*
 
1154
 * ***************************************************************************
 
1155
 * Routine:  Vio_connect
 
1156
 *
 
1157
 * Purpose:  Connect to some socket on a remote machine (or on our machine).
 
1158
 *
 
1159
 * Notes:    The nonblock parameter has the following interpretation:
 
1160
 *           (Only for <UNIX/INET>; othewise it is ignored.)
 
1161
 *
 
1162
 *               nonblock==0  ==> block until our connection is accepted
 
1163
 *               nonblock==1  ==> DO NOT block at all
 
1164
 *
 
1165
 * Author:   Michael Holst
 
1166
 * ***************************************************************************
 
1167
 */
 
1168
VPUBLIC int Vio_connect(Vio *thee, int nonblock)
 
1169
{
 
1170
    int rc;
 
1171
#if defined(HAVE_WINSOCK_H)
 
1172
    unsigned long len;
 
1173
#else
 
1174
    int len;
 
1175
    int flags = 0;
 
1176
#endif
 
1177
 
 
1178
    /* reset error tag */
 
1179
    thee->error = 0;
 
1180
 
 
1181
    rc = -1;
 
1182
 
 
1183
    Vio_initIoPutBuffers(thee);
 
1184
    VJMPERR2( thee->rwkey == VIO_W );
 
1185
 
 
1186
    if ( (thee->type==VIO_SDIO)
 
1187
      || (thee->type==VIO_FILE)
 
1188
      || (thee->type==VIO_BUFF) ) {
 
1189
        rc = 1;
 
1190
    } else if (thee->type==VIO_UNIX) {
 
1191
 
 
1192
#if defined(HAVE_SYS_UN_H)
 
1193
        /* Make this a non-blocking socket just for the connect call */
 
1194
        if (nonblock) {
 
1195
            flags = fcntl( thee->so, F_GETFL, 0 );
 
1196
            fcntl( thee->so, F_SETFL, flags | VO_NONBLOCK );
 
1197
        }
 
1198
 
 
1199
        /* blocking connect */
 
1200
        len = sizeof(struct sockaddr_un);
 
1201
        rc = connect(thee->so, (struct sockaddr *)(thee->name),len);
 
1202
        if ((!nonblock) && (rc < 0)) {
 
1203
            fprintf(stderr, "Vio_connect: Conn fail UNIX sock <%s>"
 
1204
                " dueto <%s>\n", thee->file, VIOstrerrno(errno));
 
1205
            VJMPERR2( 0 );
 
1206
        }
 
1207
 
 
1208
        /* restore blocking -- must nonblock for LINGER to work! */
 
1209
        if (nonblock) {
 
1210
            fcntl( thee->so, F_SETFL, flags );
 
1211
        }
 
1212
#endif
 
1213
 
 
1214
    } else if (thee->type==VIO_INET) {
 
1215
 
 
1216
        /* make this a non-blocking socket just for the connect call */
 
1217
        if (nonblock) {
 
1218
#if defined(HAVE_WINSOCK_H)
 
1219
            len = 1;
 
1220
            if ( ioctlsocket( thee->so, FIONBIO, &len ) != 0 ) {
 
1221
                fprintf(stderr, "Vio_connect: Ioctlsocket1 fail INET sock <%s>"
 
1222
                   " dueto <%s>\n", thee->file, VIOstrerrno(errno));
 
1223
                VJMPERR2( 0 );
 
1224
            }
 
1225
#else
 
1226
            flags = fcntl( thee->so, F_GETFL, 0 );
 
1227
            fcntl( thee->so, F_SETFL, flags | VO_NONBLOCK );
 
1228
#endif
 
1229
        }
 
1230
 
 
1231
        /* blocking connect */
 
1232
        len = sizeof(struct sockaddr_in);
 
1233
        rc = connect(thee->so, (struct sockaddr *)(thee->name),len);
 
1234
        if ((!nonblock) && (rc < 0)) {
 
1235
            fprintf(stderr, "Vio_connect: Conn fail INET sock <%s>"
 
1236
                 " dueto <%s>\n", thee->file, VIOstrerrno(errno));
 
1237
            VJMPERR2( 0 );
 
1238
        }
 
1239
 
 
1240
        /* restore blocking -- must nonblock for LINGER to work! */
 
1241
        if (nonblock) {
 
1242
#if defined(HAVE_WINSOCK_H)
 
1243
            len = 0;
 
1244
            if ( ioctlsocket( thee->so, FIONBIO, &len ) != 0 ) {
 
1245
                fprintf(stderr, "Vio_connect: Ioctlsocket2 fail INET sock <%s>"
 
1246
                   " dueto <%s>\n", thee->file, VIOstrerrno(errno));
 
1247
                VJMPERR2( 0 );
 
1248
            }
 
1249
#else
 
1250
            fcntl( thee->so, F_SETFL, flags );
 
1251
#endif
 
1252
        }
 
1253
 
 
1254
    } else {
 
1255
        fprintf(stderr,"Vio_connect: Bad type found <%d>\n", thee->type);
 
1256
        VJMPERR2( 0 );
 
1257
    }
 
1258
 
 
1259
    /* normal return */
 
1260
    return rc;
 
1261
 
 
1262
  VERROR2:
 
1263
    thee->error = 1;
 
1264
    return -1;
 
1265
}
 
1266
 
 
1267
/*
 
1268
 * ***************************************************************************
 
1269
 * Routine:  Vio_connectFree
 
1270
 *
 
1271
 * Purpose:  Purge any output buffers (for <UNIX/INET>, else a no-op).
 
1272
 *
 
1273
 * Author:   Michael Holst
 
1274
 * ***************************************************************************
 
1275
 */
 
1276
VPUBLIC void Vio_connectFree(Vio *thee)
 
1277
{
 
1278
    /* VJMPERR2( !thee->error ); */  /* Need to close the socket... */
 
1279
    VJMPERR2( thee->rwkey == VIO_W );
 
1280
 
 
1281
    if ( (thee->type==VIO_SDIO)
 
1282
      || (thee->type==VIO_FILE)
 
1283
      || (thee->type==VIO_BUFF) ) {
 
1284
        /* no-op */
 
1285
    } else if ( (thee->type==VIO_UNIX)
 
1286
             || (thee->type==VIO_INET) ) {
 
1287
        Vio_purgePutBuffer(thee);
 
1288
    } else {
 
1289
        fprintf(stderr,"Vio_connectFree: Bad type found <%d>\n", thee->type);
 
1290
        VJMPERR2( 0 );
 
1291
    }
 
1292
 
 
1293
    /* normal return */
 
1294
    Vio_initIoPutBuffers(thee);
 
1295
    return;
 
1296
 
 
1297
  VERROR2:
 
1298
    Vio_initIoPutBuffers(thee);
 
1299
    thee->error = 1;
 
1300
    return;
 
1301
}
 
1302
 
 
1303
/*
 
1304
 * ***************************************************************************
 
1305
 * Routine:  Vio_scanf
 
1306
 *
 
1307
 * Purpose:  Mimic "scanf" from an arbitrary Vio device.
 
1308
 *
 
1309
 * Author:   Michael Holst
 
1310
 * ***************************************************************************
 
1311
 */
 
1312
VPUBLIC int Vio_scanf(Vio *thee, char *parms, ... )
 
1313
{
 
1314
    va_list ap;
 
1315
    char arg0, arg1, arg2, *cval, *sval, buf[VMAX_BUFSIZE];
 
1316
    int i, len, tokCount, *ival;
 
1317
    float *fval;
 
1318
    double *dval;
 
1319
 
 
1320
    VJMPERR2( !thee->error );
 
1321
    VJMPERR2( thee->rwkey == VIO_R );
 
1322
 
 
1323
    /* get the value of the current pointer that points into the ioBuffer */
 
1324
    len = 0;
 
1325
    if (thee->frmt == VIO_ASC) {
 
1326
        len = asc_getpos((ASC*)thee->axdr);
 
1327
    } else if (thee->frmt == VIO_XDR) {
 
1328
        len = xdr_getpos((XDR*)thee->axdr);
 
1329
    } else { VASSERT( 0 ); }
 
1330
 
 
1331
    /* if the buffer is completely empty (i.e., first time here) fill it up */
 
1332
    if ( thee->ioBufferLen == 0 ) {
 
1333
 
 
1334
        /* read the data */
 
1335
        thee->ioBufferLen = Vio_read( thee, thee->ioBuffer, VMAX_BUFSIZE );
 
1336
 
 
1337
        /* set the buffer point to 0 */
 
1338
        if (thee->frmt == VIO_ASC) {
 
1339
            VJMPERR1( asc_setpos((ASC*)thee->axdr, 0) );
 
1340
        } else if (thee->frmt == VIO_XDR) {
 
1341
            VJMPERR1( xdr_setpos((XDR*)thee->axdr, 0) );
 
1342
        } else { VASSERT( 0 ); }
 
1343
 
 
1344
    /* if current point is more than halfway through buf, read in more data */
 
1345
    } else if ( len > (VMAX_BUFSIZE/2) ) {
 
1346
 
 
1347
        /* sanity check */
 
1348
        VJMPERR1( len <= thee->ioBufferLen );
 
1349
 
 
1350
        /* copy unread part of ioBuffer into temp buf and clear ioBuffer */
 
1351
        for (i=len; i<thee->ioBufferLen; i++)
 
1352
            buf[i-len] = thee->ioBuffer[i];
 
1353
        memset(thee->ioBuffer,  '\0', sizeof(thee->ioBuffer));
 
1354
 
 
1355
        /* read temp buffer back, reseting to the beginning of ioBuffer */
 
1356
        thee->ioBufferLen = thee->ioBufferLen - len;
 
1357
        for (i=0; i<thee->ioBufferLen; i++)
 
1358
            thee->ioBuffer[i] = buf[i];
 
1359
 
 
1360
        /* reset the buffer point to 0 */
 
1361
        if (thee->frmt == VIO_ASC) {
 
1362
            VJMPERR1( asc_setpos((ASC*)thee->axdr, 0) );
 
1363
        } else if (thee->frmt == VIO_XDR) {
 
1364
            VJMPERR1( xdr_setpos((XDR*)thee->axdr, 0) );
 
1365
        } else { VASSERT( 0 ); }
 
1366
 
 
1367
        /* finally, read in the new data, starting at end of current data */
 
1368
        thee->ioBufferLen += Vio_read(thee,
 
1369
            thee->ioBuffer+thee->ioBufferLen, VMAX_BUFSIZE-thee->ioBufferLen );
 
1370
 
 
1371
    /* we (hopefully?) have enough in buffer to work with; do nothing here */
 
1372
    } else {
 
1373
        /* no-op */
 
1374
    }
 
1375
 
 
1376
    /* we ALWAYS have to pick the format specifier apart <ASC,XDR> ... */
 
1377
    tokCount = 0;
 
1378
    len = strlen(parms);
 
1379
    va_start(ap, parms);
 
1380
    i = 0;
 
1381
    while ( i < len ) {
 
1382
        arg0 = parms[i];
 
1383
        if ( arg0 == ' ' ) {
 
1384
            i+=1;
 
1385
        } else if ( arg0 == '\n' ) {
 
1386
            i+=1;
 
1387
        } else if ( i+1 < len ) {
 
1388
            arg1 = parms[i+1];
 
1389
            if ( arg1 == 's' ) {
 
1390
                sval = va_arg(ap, char*);
 
1391
                if ((i == len-3) && ( parms[len-1] == '\n' )) {
 
1392
                    if (thee->frmt == VIO_ASC) {
 
1393
                        VASSERT( 0 ); /* is this ever executed??? */
 
1394
                    } else if (thee->frmt == VIO_XDR) {
 
1395
                        VASSERT( 0 ); /* is this ever executed??? */
 
1396
                    } else { VASSERT( 0 ); }
 
1397
                } else {
 
1398
                    if (thee->frmt == VIO_ASC) {
 
1399
                        VJMPERR1( asc_string(thee->axdr, &sval, VMAX_BUFSIZE) );
 
1400
                    } else if (thee->frmt == VIO_XDR) {
 
1401
                        VJMPERR1( xdr_string(thee->axdr, &sval, VMAX_BUFSIZE) );
 
1402
                    } else { VASSERT( 0 ); }
 
1403
                }
 
1404
                tokCount++;
 
1405
                i+=2;
 
1406
            } else if ( arg1 == 'c' ) {
 
1407
                cval = va_arg(ap, char*);
 
1408
                if (thee->frmt == VIO_ASC) {
 
1409
                    VJMPERR1( asc_char( thee->axdr, cval ) );
 
1410
                } else if (thee->frmt == VIO_XDR) {
 
1411
                    VJMPERR1( xdr_char( thee->axdr, cval ) );
 
1412
                } else { VASSERT( 0 ); }
 
1413
                tokCount++;
 
1414
                i+=2;
 
1415
            } else if ( arg1 == 'd' ) {
 
1416
                ival = va_arg(ap, int*);
 
1417
                if (thee->frmt == VIO_ASC) {
 
1418
                    VJMPERR1( asc_int( thee->axdr, ival ) );
 
1419
                } else if (thee->frmt == VIO_XDR) {
 
1420
                    VJMPERR1( xdr_int( thee->axdr, ival ) );
 
1421
                } else { VASSERT( 0 ); }
 
1422
                tokCount++;
 
1423
                i+=2;
 
1424
            } else if ( arg1 == 'f' ) {
 
1425
                fval = va_arg(ap, float*);
 
1426
                if (thee->frmt == VIO_ASC) {
 
1427
                    VJMPERR1( asc_float( thee->axdr, fval ) );
 
1428
                } else if (thee->frmt == VIO_XDR) {
 
1429
                    VJMPERR1( xdr_float( thee->axdr, fval ) );
 
1430
                } else { VASSERT( 0 ); }
 
1431
                tokCount++;
 
1432
                i+=2;
 
1433
            } else if ( arg1 == 'e' ) {
 
1434
                fval = va_arg(ap, float*);
 
1435
                if (thee->frmt == VIO_ASC) {
 
1436
                    VJMPERR1( asc_float( thee->axdr, fval ) );
 
1437
                } else if (thee->frmt == VIO_XDR) {
 
1438
                    VJMPERR1( xdr_float( thee->axdr, fval ) );
 
1439
                } else { VASSERT( 0 ); }
 
1440
                tokCount++;
 
1441
                i+=2;
 
1442
            } else if (( arg1 == 'l' ) && ( i+2 < len )) {
 
1443
                arg2 = parms[i+2];
 
1444
                if ( arg2 == 'e' ) {
 
1445
                    dval = va_arg(ap, double*);
 
1446
                    if (thee->frmt == VIO_ASC) {
 
1447
                        VJMPERR1( asc_double( thee->axdr, dval ) );
 
1448
                    } else if (thee->frmt == VIO_XDR) {
 
1449
                        VJMPERR1( xdr_double( thee->axdr, dval ) );
 
1450
                    } else { VASSERT( 0 ); }
 
1451
                    tokCount++;
 
1452
                    i+=3;
 
1453
                } else { VJMPERR1( 0 ); }
 
1454
            } else { VJMPERR1( 0 ); }
 
1455
        } else { VJMPERR1( 0 ); }
 
1456
    }
 
1457
    va_end(ap);
 
1458
 
 
1459
    /* return without error */
 
1460
    return tokCount;
 
1461
 
 
1462
  VERROR1:
 
1463
    va_end(ap);
 
1464
    fprintf(stderr,"Vio_scanf: Format problem with input.\n");
 
1465
  VERROR2:
 
1466
    thee->error = 1;
 
1467
    return 0;
 
1468
}
 
1469
 
 
1470
/*
 
1471
 * ***************************************************************************
 
1472
 * Routine:  Vio_printf
 
1473
 *
 
1474
 * Purpose:  Mimic "printf" to an arbitrary Vio device.
 
1475
 *
 
1476
 * Author:   Michael Holst
 
1477
 * ***************************************************************************
 
1478
 */
 
1479
VPUBLIC int Vio_printf(Vio *thee, char *parms, ... )
 
1480
{
 
1481
    va_list ap;
 
1482
    char buf[VMAX_BUFSIZE];
 
1483
    int len;
 
1484
 
 
1485
    char arg0, arg1, arg2, cval, *sval;
 
1486
    int i, tokCount, ival;
 
1487
    float fval;
 
1488
    double dval;
 
1489
 
 
1490
    VJMPERR2( !thee->error );
 
1491
    VJMPERR2( thee->rwkey == VIO_W );
 
1492
 
 
1493
    /* if ASCII data then use vsprintf to handle format specifier exactly */
 
1494
    if (thee->frmt == VIO_ASC) {
 
1495
        va_start(ap, parms);
 
1496
        vsprintf(buf, parms, ap);
 
1497
        va_end(ap);
 
1498
        len = strlen(buf);
 
1499
        return Vio_writePutBuffer(thee,buf,len);
 
1500
    }
 
1501
 
 
1502
    /* if XDR data then we have to pick the format specifier apart... */
 
1503
    len = strlen(parms);
 
1504
    va_start(ap, parms);
 
1505
    tokCount = 0;
 
1506
    i = 0;
 
1507
    while ( i < len ) {
 
1508
        arg0 = parms[i];
 
1509
        if ((arg0 == '%') && (i+1 < len)) {
 
1510
            arg1 = parms[i+1];
 
1511
            if ( arg1 == '%' ) {
 
1512
                i+=2;
 
1513
            } else {
 
1514
                while (!strchr("scdfel",arg1)) {
 
1515
                    i+=1;
 
1516
                    arg1 = parms[i+1];
 
1517
                    VJMPERR1( i+1 < len );
 
1518
                }
 
1519
                if ( arg1 == 's' ) {
 
1520
                    sval = va_arg(ap, char*);
 
1521
                    /* don't put comment strings into xdr files */
 
1522
                    if (!strchr(thee->commChars,sval[0])) {
 
1523
                        VJMPERR1( xdr_string(thee->axdr, &sval, strlen(sval)) );
 
1524
                        tokCount++;
 
1525
                    }
 
1526
                    i+=2;
 
1527
                } else if ( arg1 == 'c' ) {
 
1528
                    /* are char args always passed as int? ... */
 
1529
                    cval = (char)va_arg(ap, int);  /* CAST FROM INT */
 
1530
                    VJMPERR1( xdr_char( thee->axdr, &cval ) );
 
1531
                    tokCount++;
 
1532
                    i+=2;
 
1533
                } else if ( arg1 == 'd' ) {
 
1534
                    ival = va_arg(ap, int);
 
1535
                    VJMPERR1( xdr_int( thee->axdr, &ival ) );
 
1536
                    tokCount++;
 
1537
                    i+=2;
 
1538
                } else if ( arg1 == 'f' ) {
 
1539
                    /* are float args always passed as double? ... */
 
1540
                    fval = (float)va_arg(ap, double);  /* CAST FROM DOUBLE */
 
1541
                    VJMPERR1( xdr_float( thee->axdr, &fval ) );
 
1542
                    tokCount++;
 
1543
                    i+=2;
 
1544
                } else if ( arg1 == 'e' ) {
 
1545
                    /* are float args always passed as double? ... */
 
1546
                    fval = (float)va_arg(ap, double);  /* CAST FROM DOUBLE */
 
1547
                    VJMPERR1( xdr_float( thee->axdr, &fval ) );
 
1548
                    tokCount++;
 
1549
                    i+=2;
 
1550
                } else if (( arg1 == 'l' ) && ( i+2 < len )) {
 
1551
                    arg2 = parms[i+2];
 
1552
                    if ( arg2 == 'e' ) {
 
1553
                        dval = va_arg(ap, double);
 
1554
                        VJMPERR1( xdr_double( thee->axdr, &dval ) );
 
1555
                        tokCount++;
 
1556
                        i+=3;
 
1557
                    } else { VJMPERR1( 0 ); }
 
1558
                } else { VJMPERR1( 0 ); }
 
1559
            }
 
1560
        } else {
 
1561
            i+=1;
 
1562
        }
 
1563
    }
 
1564
    va_end(ap);
 
1565
 
 
1566
    /* finally write out the XDR buffer */
 
1567
    VJMPERR1( 0<=(len=xdr_getpos((XDR*)thee->axdr)) );
 
1568
    VJMPERR1( Vio_writePutBuffer(thee,thee->ioBuffer,len) == len );
 
1569
    VJMPERR1( xdr_setpos((XDR*)thee->axdr, 0) );
 
1570
 
 
1571
    /* return without error */
 
1572
    return len;
 
1573
 
 
1574
  VERROR1:
 
1575
    va_end(ap);
 
1576
    fprintf(stderr,"Vio_printf: Format problem with output.\n");
 
1577
 
 
1578
  VERROR2:
 
1579
    thee->error = 1;
 
1580
    return 0;
 
1581
}
 
1582
 
 
1583
/*
 
1584
 * ***************************************************************************
 
1585
 * Routine:  Vio_read
 
1586
 *
 
1587
 * Purpose:  Read (up to) bufsize characters into buf from input device.
 
1588
 *
 
1589
 * Notes:    The number of bytes read is returned.
 
1590
 *
 
1591
 *           It is not necessarily an error if the number of bytes read
 
1592
 *           is less than bufsize (EOF may have been encountered).
 
1593
 *
 
1594
 *           Acts exactly like fread() or read().
 
1595
 *
 
1596
 * Author:   Michael Holst
 
1597
 * ***************************************************************************
 
1598
 */
 
1599
VPUBLIC int Vio_read(Vio *thee, char *buf, int bufsize)
 
1600
{
 
1601
    int rc, i, ilen;
 
1602
 
 
1603
    VJMPERR2( !thee->error );
 
1604
    VJMPERR2( thee->rwkey == VIO_R );
 
1605
 
 
1606
    rc = 0;
 
1607
    if (bufsize > 0) {
 
1608
        if ( (thee->type==VIO_SDIO)
 
1609
          || (thee->type==VIO_FILE) ) {
 
1610
            rc = fread(buf, sizeof(char), (unsigned int)bufsize, thee->fp);
 
1611
            /* MIKE: if (rc!=bufsize), make SURE EOF was reached! */
 
1612
        } else if (thee->type==VIO_BUFF) {
 
1613
            ilen = VMIN2( bufsize, thee->VIObufferLen - thee->VIObufferPtr );
 
1614
            for (i=0; i<ilen; i++)
 
1615
                buf[i] = thee->VIObuffer[thee->VIObufferPtr + i];
 
1616
            thee->VIObufferPtr += ilen;
 
1617
            rc = ilen;
 
1618
        } else if ( (thee->type==VIO_UNIX)
 
1619
                 || (thee->type==VIO_INET) ) {
 
1620
            rc = readn(thee->soc, buf, (unsigned int)bufsize);
 
1621
            /* MIKE: if (rc!=bufsize), make SURE EOF was reached! */
 
1622
        } else {
 
1623
            fprintf(stderr,"Vio_read: Bad type found <%d>\n", thee->type);
 
1624
            rc = 0;
 
1625
            VJMPERR2( 0 );
 
1626
        }
 
1627
    }
 
1628
 
 
1629
    /* return without error */
 
1630
    return rc;
 
1631
 
 
1632
  VERROR2:
 
1633
    thee->error = 1;
 
1634
    return 0;
 
1635
}
 
1636
 
 
1637
/*
 
1638
 * ***************************************************************************
 
1639
 * Routine:  Vio_write
 
1640
 *
 
1641
 * Purpose:  Write bufsize characters from buf to output device.
 
1642
 *
 
1643
 * Notes:    The number of bytes written is returned.
 
1644
 *
 
1645
 *           On success, the returned bytecount is the same as the number
 
1646
 *           of bytes in the input buffer.
 
1647
 *
 
1648
 *           On failure, the returned bytecount is less than the number
 
1649
 *           of bytes in the input buffer.
 
1650
 *
 
1651
 *           Acts exactly like fwrite() or write().
 
1652
 *
 
1653
 * Author:   Michael Holst
 
1654
 * ***************************************************************************
 
1655
 */
 
1656
VPUBLIC int Vio_write(Vio *thee, char *buf, int bufsize)
 
1657
{
 
1658
    int rc, i, isize;
 
1659
    char *tmpBuf;
 
1660
 
 
1661
    VJMPERR2( !thee->error );
 
1662
    VJMPERR2( thee->rwkey == VIO_W );
 
1663
 
 
1664
    rc = 0;
 
1665
    if (bufsize > 0) {
 
1666
        if ( (thee->type==VIO_SDIO)
 
1667
          || (thee->type==VIO_FILE) ) {
 
1668
            rc = fwrite(buf, sizeof(char), (unsigned int)bufsize, thee->fp);
 
1669
            VJMPERR1( rc == bufsize );
 
1670
        } else if (thee->type==VIO_BUFF) {
 
1671
            while ( bufsize > (thee->VIObufferLen - thee->VIObufferPtr) ) {
 
1672
                isize = VMAX2( 1, 2*(thee->VIObufferLen) );
 
1673
                tmpBuf = (char*)calloc( isize, sizeof(char) );
 
1674
                VJMPERR1( tmpBuf != VNULL );
 
1675
                for (i=0; i<thee->VIObufferLen; i++)
 
1676
                    tmpBuf[i] = thee->VIObuffer[i];
 
1677
                free( thee->VIObuffer );
 
1678
                thee->VIObuffer = tmpBuf;
 
1679
                thee->VIObufferLen = isize;
 
1680
            }
 
1681
            for (i=0; i<bufsize; i++)
 
1682
                thee->VIObuffer[thee->VIObufferPtr + i] = buf[i];
 
1683
            thee->VIObufferPtr += bufsize;
 
1684
            rc = bufsize;
 
1685
            VJMPERR1( rc == bufsize );
 
1686
        } else if ( (thee->type==VIO_UNIX)
 
1687
                 || (thee->type==VIO_INET) ) {
 
1688
            rc = writen(thee->so, buf, (unsigned int)bufsize);
 
1689
            VJMPERR1( rc == bufsize );
 
1690
        } else {
 
1691
            fprintf(stderr,"Vio_write: Bad type found <%d>\n", thee->type);
 
1692
            rc = 0;
 
1693
            VJMPERR2( 0 );
 
1694
        }
 
1695
    }
 
1696
 
 
1697
    /* return without error */
 
1698
    return rc;
 
1699
 
 
1700
  VERROR1:
 
1701
    fprintf(stderr,"Vio_write: Error occurred (bailing out).\n");
 
1702
  VERROR2:
 
1703
    thee->error = 1;
 
1704
    return 0;
 
1705
}
 
1706
 
 
1707
/*
 
1708
 * ***************************************************************************
 
1709
 * Routine:  Vio_initIoPutBuffers
 
1710
 *
 
1711
 * Purpose:  Initialize the internal buffer.
 
1712
 *
 
1713
 * Author:   Michael Holst
 
1714
 * ***************************************************************************
 
1715
 */
 
1716
VPRIVATE void Vio_initIoPutBuffers(Vio *thee)
 
1717
{
 
1718
    /* initialize the buffer space */
 
1719
    memset(thee->ioBuffer,  '\0', sizeof(thee->ioBuffer));
 
1720
    memset(thee->putBuffer, '\0', sizeof(thee->putBuffer));
 
1721
    thee->ioBufferLen = 0;
 
1722
    thee->putBufferLen = 0;
 
1723
}
 
1724
 
 
1725
/*
 
1726
 * ***************************************************************************
 
1727
 * Routine:  Vio_purgePutBuffer
 
1728
 *
 
1729
 * Purpose:  Purge the internal buffer.
 
1730
 *
 
1731
 * Author:   Michael Holst
 
1732
 * ***************************************************************************
 
1733
 */
 
1734
VPRIVATE void Vio_purgePutBuffer(Vio *thee)
 
1735
{
 
1736
    int len;
 
1737
 
 
1738
    VJMPERR2( !thee->error );
 
1739
    VJMPERR2( thee->rwkey == VIO_W );
 
1740
 
 
1741
    len = thee->putBufferLen;
 
1742
    if ( (thee->type==VIO_UNIX)
 
1743
      || (thee->type==VIO_INET) ) {
 
1744
        if ( Vio_write(thee,thee->putBuffer,len) != len ) {
 
1745
            fprintf(stderr,
 
1746
               "Vio_purgePutBuffer: Vio_write fail UNIX/INET sock <%s>"
 
1747
               " dueto <%s>\n", thee->file, VIOstrerrno(errno));
 
1748
            VJMPERR2( 0 );
 
1749
        }
 
1750
        memset(thee->putBuffer, '\0', sizeof(thee->putBuffer));
 
1751
    } else {
 
1752
        fprintf(stderr,"Vio_purgePutBuffer: Bad type found <%d>\n",thee->type);
 
1753
        VJMPERR2( 0 );
 
1754
    }
 
1755
 
 
1756
    /* return without error */
 
1757
    return;
 
1758
 
 
1759
  VERROR2:
 
1760
    thee->error = 1;
 
1761
    return;
 
1762
}
 
1763
 
 
1764
/*
 
1765
 * ***************************************************************************
 
1766
 * Routine:  Vio_writePutBuffer
 
1767
 *
 
1768
 * Purpose:  Write bufsize characters from buf to output device.
 
1769
 *
 
1770
 * Notes:    The number of bytes written is returned.
 
1771
 *
 
1772
 *           On success, the returned bytecount is the same as the number
 
1773
 *           of bytes in the input buffer.
 
1774
 *
 
1775
 *           On failure, the returned bytecount is less than the number
 
1776
 *           of bytes in the input buffer.
 
1777
 *
 
1778
 *           Acts exactly like fwrite() or write().
 
1779
 *
 
1780
 * Comment:  This is simply a buffered version of Vio_write().
 
1781
 *           The Vio object maintains the buffer safely internally.
 
1782
 *
 
1783
 * Author:   Michael Holst
 
1784
 * ***************************************************************************
 
1785
 */
 
1786
VPRIVATE int Vio_writePutBuffer(Vio *thee, char *buf, int bufsize)
 
1787
{
 
1788
    int i, curLen;
 
1789
 
 
1790
    VJMPERR2( !thee->error );
 
1791
    VJMPERR2( thee->rwkey == VIO_W );
 
1792
 
 
1793
    /* attempt to buffer the i/o to get some speed */
 
1794
    if ( (thee->type==VIO_SDIO)
 
1795
      || (thee->type==VIO_FILE)
 
1796
      || (thee->type==VIO_BUFF) ) {
 
1797
 
 
1798
        if ( Vio_write(thee,buf,bufsize) != bufsize ) {
 
1799
            fprintf(stderr,
 
1800
                "Vio_writePutBuffer: Vio_write(1) fail FILE sock <%s>"
 
1801
                " dueto <%s>\n", thee->file, VIOstrerrno(errno));
 
1802
            VJMPERR2( 0 );
 
1803
        }
 
1804
 
 
1805
    } else if ( (thee->type==VIO_UNIX)
 
1806
             || (thee->type==VIO_INET) ) {
 
1807
 
 
1808
        /* incoming data is larger than our buffer */
 
1809
        if (bufsize > (int)sizeof(thee->putBuffer)) {
 
1810
 
 
1811
            /* just do a normal unbuffered socket write */
 
1812
            if ( Vio_write(thee,buf,bufsize) != bufsize ) {
 
1813
                fprintf(stderr, "Vio_writePutBuffer: Vio_write(2) fail"
 
1814
                    " UNIX/INET sock <%s>"
 
1815
                    " dueto <%s>\n", thee->file, VIOstrerrno(errno));
 
1816
                VJMPERR2( 0 );
 
1817
            }
 
1818
 
 
1819
        /* incoming data will fit in our buffer */
 
1820
        } else {
 
1821
 
 
1822
            curLen = thee->putBufferLen;
 
1823
 
 
1824
            /* it fits in now -- just cat it to the end of the buffer */
 
1825
            if ( (curLen + bufsize) <= (int)sizeof(thee->putBuffer) ) {
 
1826
                for (i=0; i<bufsize; i++)
 
1827
                    thee->putBuffer[curLen+i] = buf[i];
 
1828
                thee->putBufferLen += bufsize;
 
1829
 
 
1830
            /* it won't fit until we write out the existing buffer */
 
1831
            } else {
 
1832
                if ( Vio_write(thee,thee->putBuffer,curLen) != curLen ) {
 
1833
                    fprintf(stderr, "Vio_writePutBuffer: Vio_write(3)"
 
1834
                     " fail UNIX/INET sock <%s>"
 
1835
                     " dueto <%s>\n", thee->file, VIOstrerrno(errno));
 
1836
                    VJMPERR2( 0 );
 
1837
                }
 
1838
                thee->putBufferLen = 0;
 
1839
                memset(thee->putBuffer, '\0', sizeof(thee->putBuffer));
 
1840
                for (i=0; i<bufsize; i++)
 
1841
                    thee->putBuffer[i] = buf[i];
 
1842
                thee->putBufferLen += bufsize;
 
1843
            }
 
1844
        }
 
1845
 
 
1846
    } else {
 
1847
        fprintf(stderr,"Vio_writePutBuffer: Bad type found <%d>\n",thee->type);
 
1848
        VJMPERR2( 0 );
 
1849
    }
 
1850
 
 
1851
    /* return without error */
 
1852
    return bufsize;
 
1853
 
 
1854
  VERROR2:
 
1855
    thee->error = 1;
 
1856
    return 0;
 
1857
}
 
1858
 
 
1859
/*
 
1860
 * ***************************************************************************
 
1861
 * Routine:  ascmem_create, asc_destroy, asc_getpos, asc_setpos
 
1862
 *           asc_string, asc_char, asc_int, asc_float, asc_double
 
1863
 *           asc_setWhiteChars, asc_setCommChars, asc_getToken
 
1864
 *
 
1865
 * Purpose:  An ASC (i.e. ASCII) dual to the XDR routines.
 
1866
 *
 
1867
 * Notes:    These routines basically function idential to the XDR routines,
 
1868
 *           except that after calling the constructor <ascmem_create>, one
 
1869
 *           must call two additional routines, <asc_setWhiteChars> and
 
1870
 *           <asc_setCommChars>, to specify the strings representing the
 
1871
 *           whitespace in the ASCII stream separating the tokens, and a set
 
1872
 *           of possible comment characters which generate skips to a newline.
 
1873
 *
 
1874
 *           The only complicated routine is <asc_genToken>, on which
 
1875
 *           most of the other things rest.
 
1876
 *
 
1877
 *           Both ASC_ENCODE (write) and ASC_DECODE (read) directions work.
 
1878
 *           In ASC_ENCODE mode, the tokens are separated by a single newline
 
1879
 *           (for lack of anything more intelligent to do...).
 
1880
 *
 
1881
 * Author:   Michael Holst
 
1882
 * ***************************************************************************
 
1883
 */
 
1884
 
 
1885
/*
 
1886
 * ***************************************************************************
 
1887
 * Routine:  ascmem_create
 
1888
 *
 
1889
 * Purpose:  Create the ASC structure.
 
1890
 *
 
1891
 * Author:   Michael Holst
 
1892
 * ***************************************************************************
 
1893
 */
 
1894
VPRIVATE void ascmem_create(ASC *thee, char *buf, int size, ASCmode mode)
 
1895
{
 
1896
    thee->mode = mode;
 
1897
    thee->pos  = 0;
 
1898
    thee->size = size;
 
1899
    thee->buf  = buf;
 
1900
    memset(thee->whiteChars, '\0', VMAX_ARGNUM);
 
1901
    memset(thee->commChars,  '\0', VMAX_ARGNUM);
 
1902
}
 
1903
 
 
1904
/*
 
1905
 * ***************************************************************************
 
1906
 * Routine:  asc_destroy
 
1907
 *
 
1908
 * Purpose:  Destroy the ASC structure.
 
1909
 *
 
1910
 * Author:   Michael Holst
 
1911
 * ***************************************************************************
 
1912
 */
 
1913
VPRIVATE void asc_destroy(ASC *thee)
 
1914
{
 
1915
    thee->mode = ASC_NO_MODE;
 
1916
    thee->pos  = 0;
 
1917
    thee->size = 0;
 
1918
    thee->buf  = VNULL;
 
1919
    memset(thee->whiteChars, '\0', VMAX_ARGNUM);
 
1920
    memset(thee->commChars,  '\0', VMAX_ARGNUM);
 
1921
}
 
1922
 
 
1923
/*
 
1924
 * ***************************************************************************
 
1925
 * Routine:  asc_getpos
 
1926
 *
 
1927
 * Purpose:  Return the current position in the ASC stream.
 
1928
 *
 
1929
 * Author:   Michael Holst
 
1930
 * ***************************************************************************
 
1931
 */
 
1932
VPRIVATE int asc_getpos(ASC *thee)
 
1933
{
 
1934
    return thee->pos;
 
1935
}
 
1936
 
 
1937
/*
 
1938
 * ***************************************************************************
 
1939
 * Routine:  asc_setpos
 
1940
 *
 
1941
 * Purpose:  Set the current position in the ASC stream.
 
1942
 *
 
1943
 * Author:   Michael Holst
 
1944
 * ***************************************************************************
 
1945
 */
 
1946
VPRIVATE int asc_setpos(ASC *thee, int pos)
 
1947
{
 
1948
    thee->pos = pos;
 
1949
    return 1;
 
1950
}
 
1951
 
 
1952
/*
 
1953
 * ***************************************************************************
 
1954
 * Routine:  asc_string
 
1955
 *
 
1956
 * Purpose:  DECODE or ENCODE a string.
 
1957
 *
 
1958
 * Author:   Michael Holst
 
1959
 * ***************************************************************************
 
1960
 */
 
1961
VPRIVATE int asc_string(ASC *thee, char **sval, int size)
 
1962
{
 
1963
    int i, len;
 
1964
    char tok[VMAX_BUFSIZE];
 
1965
 
 
1966
    if (thee->mode == ASC_DECODE) {
 
1967
        VJMPERR1( VNULL != asc_getToken(thee, tok, VMAX_BUFSIZE) );
 
1968
        sscanf(tok,"%s",(*sval));
 
1969
    } else if (thee->mode == ASC_ENCODE) {
 
1970
        sprintf(tok,"%s\n",*sval);
 
1971
        len = strlen(tok);
 
1972
        for (i=0; i<len; i++)
 
1973
            thee->buf[thee->pos+i] = tok[i];
 
1974
        thee->pos += len;
 
1975
    }
 
1976
    return 1;
 
1977
 
 
1978
  VERROR1:
 
1979
    return 0;
 
1980
}
 
1981
 
 
1982
/*
 
1983
 * ***************************************************************************
 
1984
 * Routine:  asc_char
 
1985
 *
 
1986
 * Purpose:  DECODE or ENCODE a char.
 
1987
 *
 
1988
 * Author:   Michael Holst
 
1989
 * ***************************************************************************
 
1990
 */
 
1991
VPRIVATE int asc_char(ASC *thee, char *cval)
 
1992
{
 
1993
    int i, len;
 
1994
    char tok[VMAX_BUFSIZE];
 
1995
 
 
1996
    if (thee->mode == ASC_DECODE) {
 
1997
        VJMPERR1( VNULL != asc_getToken(thee, tok, VMAX_BUFSIZE) );
 
1998
        sscanf(tok,"%c",cval);
 
1999
    } else if (thee->mode == ASC_ENCODE) {
 
2000
        sprintf(tok,"%c\n",*cval);
 
2001
        len = strlen(tok);
 
2002
        for (i=0; i<len; i++)
 
2003
            thee->buf[thee->pos+i] = tok[i];
 
2004
        thee->pos += len;
 
2005
    }
 
2006
    return 1;
 
2007
 
 
2008
  VERROR1:
 
2009
    return 0;
 
2010
}
 
2011
 
 
2012
/*
 
2013
 * ***************************************************************************
 
2014
 * Routine:  asc_int
 
2015
 *
 
2016
 * Purpose:  DECODE or ENCODE an int.
 
2017
 *
 
2018
 * Author:   Michael Holst
 
2019
 * ***************************************************************************
 
2020
 */
 
2021
VPRIVATE int asc_int(ASC *thee, int *ival)
 
2022
{
 
2023
    int i, len;
 
2024
    char tok[VMAX_BUFSIZE];
 
2025
 
 
2026
    if (thee->mode == ASC_DECODE) {
 
2027
        VJMPERR1( VNULL != asc_getToken(thee, tok, VMAX_BUFSIZE) );
 
2028
        sscanf(tok,"%d",ival);
 
2029
    } else if (thee->mode == ASC_ENCODE) {
 
2030
        sprintf(tok,"%d\n",*ival);
 
2031
        len = strlen(tok);
 
2032
        for (i=0; i<len; i++)
 
2033
            thee->buf[thee->pos+i] = tok[i];
 
2034
        thee->pos += len;
 
2035
    }
 
2036
    return 1;
 
2037
 
 
2038
  VERROR1:
 
2039
    return 0;
 
2040
}
 
2041
 
 
2042
/*
 
2043
 * ***************************************************************************
 
2044
 * Routine:  asc_float
 
2045
 *
 
2046
 * Purpose:  DECODE or ENCODE a float.
 
2047
 *
 
2048
 * Author:   Michael Holst
 
2049
 * ***************************************************************************
 
2050
 */
 
2051
VPRIVATE int asc_float(ASC *thee, float *fval)
 
2052
{
 
2053
    int i, len;
 
2054
    char tok[VMAX_BUFSIZE];
 
2055
 
 
2056
    if (thee->mode == ASC_DECODE) {
 
2057
        VJMPERR1( VNULL != asc_getToken(thee, tok, VMAX_BUFSIZE) );
 
2058
        sscanf(tok,"%e",fval);
 
2059
    } else if (thee->mode == ASC_ENCODE) {
 
2060
        sprintf(tok,"%e\n",*fval);
 
2061
        len = strlen(tok);
 
2062
        for (i=0; i<len; i++)
 
2063
            thee->buf[thee->pos+i] = tok[i];
 
2064
        thee->pos += len;
 
2065
    }
 
2066
    return 1;
 
2067
 
 
2068
  VERROR1:
 
2069
    return 0;
 
2070
}
 
2071
 
 
2072
/*
 
2073
 * ***************************************************************************
 
2074
 * Routine:  asc_double
 
2075
 *
 
2076
 * Purpose:  DECODE or ENCODE a double.
 
2077
 *
 
2078
 * Author:   Michael Holst
 
2079
 * ***************************************************************************
 
2080
 */
 
2081
VPRIVATE int asc_double(ASC *thee, double *dval)
 
2082
{
 
2083
    int i, len;
 
2084
    char tok[VMAX_BUFSIZE];
 
2085
 
 
2086
    if (thee->mode == ASC_DECODE) {
 
2087
        VJMPERR1( VNULL != asc_getToken(thee, tok, VMAX_BUFSIZE) );
 
2088
        sscanf(tok,"%le",dval);
 
2089
    } else if (thee->mode == ASC_ENCODE) {
 
2090
        sprintf(tok,"%e\n",*dval);
 
2091
        len = strlen(tok);
 
2092
        for (i=0; i<len; i++)
 
2093
            thee->buf[thee->pos+i] = tok[i];
 
2094
        thee->pos += len;
 
2095
    }
 
2096
    return 1;
 
2097
 
 
2098
  VERROR1:
 
2099
    return 0;
 
2100
}
 
2101
 
 
2102
/*
 
2103
 * ***************************************************************************
 
2104
 * Routine:  asc_setWhiteChars
 
2105
 *
 
2106
 * Purpose:  Define the white character set.
 
2107
 *
 
2108
 * Author:   Michael Holst
 
2109
 * ***************************************************************************
 
2110
 */
 
2111
VPRIVATE void asc_setWhiteChars(ASC *thee, char *whiteChars)
 
2112
{
 
2113
    strncpy(thee->whiteChars, whiteChars, VMAX_ARGNUM);
 
2114
}
 
2115
 
 
2116
/*
 
2117
 * ***************************************************************************
 
2118
 * Routine:  asc_setCommChars
 
2119
 *
 
2120
 * Purpose:  Define the comment character set.
 
2121
 *
 
2122
 * Author:   Michael Holst
 
2123
 * ***************************************************************************
 
2124
 */
 
2125
VPRIVATE void asc_setCommChars(ASC *thee, char *commChars)
 
2126
{
 
2127
    strncpy(thee->commChars, commChars, VMAX_ARGNUM);
 
2128
}
 
2129
 
 
2130
/*
 
2131
 * ***************************************************************************
 
2132
 * Routine:  asc_getToken
 
2133
 *
 
2134
 * Purpose:  Get the next token from the input stream.
 
2135
 *
 
2136
 * Author:   Michael Holst
 
2137
 * ***************************************************************************
 
2138
 */
 
2139
VPRIVATE char* asc_getToken(ASC *thee, char *tok, int toksize)
 
2140
{
 
2141
    int i, ii, jj, done;
 
2142
    if (thee->mode == ASC_DECODE) {
 
2143
 
 
2144
        /* first clear the token buffer */
 
2145
        memset(tok, '\0', toksize);
 
2146
 
 
2147
        /* set "ii" ptr to the first token character */
 
2148
        ii = thee->pos;
 
2149
        done = 0;
 
2150
        while ( !done ) {
 
2151
 
 
2152
            /* if whiteChar then just skip that character */
 
2153
            if ( strchr(thee->whiteChars,thee->buf[ii]) ) {
 
2154
                ii++;
 
2155
                VJMPERR1( ii < thee->size );
 
2156
 
 
2157
            /* if commChar then skip to the next newline and keep going */
 
2158
            } else if ( strchr(thee->commChars,thee->buf[ii]) ) {
 
2159
                ii++;
 
2160
                VJMPERR1( ii < thee->size );
 
2161
                while ( thee->buf[ii] != '\n' ) {
 
2162
                    ii++;
 
2163
                    VJMPERR1( ii < thee->size );
 
2164
                }
 
2165
 
 
2166
            /* this must be the first token character */
 
2167
            } else {
 
2168
                done = 1;
 
2169
            }
 
2170
        }
 
2171
 
 
2172
        /* set "jj" ptr to the first character (white or comm) after token */
 
2173
        jj = ii+1;
 
2174
        done = 0;
 
2175
        while ( !done ) {
 
2176
            VJMPERR1( jj < thee->size );
 
2177
 
 
2178
            /* if whiteChar then we are done */
 
2179
            if ( strchr(thee->whiteChars,thee->buf[jj]) ) {
 
2180
                done = 1;
 
2181
 
 
2182
            /* if commChar then we are done */
 
2183
            } else if ( strchr(thee->commChars,thee->buf[jj]) ) {
 
2184
                done = 1;
 
2185
 
 
2186
            /* this must be another token character */
 
2187
            } else {
 
2188
                jj++;
 
2189
            }
 
2190
        }
 
2191
 
 
2192
        /* error control */
 
2193
        VJMPERR1( (jj-ii) <= toksize );
 
2194
        VJMPERR1( jj <= thee->size );
 
2195
 
 
2196
        /* copy the characters between ii and jj to the output string */
 
2197
        for (i=ii; i<jj; i++)
 
2198
            tok[i-ii] = thee->buf[i];
 
2199
        tok[jj] = '\0';
 
2200
 
 
2201
        /* update the position pointer */
 
2202
        thee->pos = jj;
 
2203
 
 
2204
    } else if (thee->mode == ASC_ENCODE) {
 
2205
        fprintf(stderr,"asc_getToken: Don't know how to ENCODE yet!\n");
 
2206
    }
 
2207
 
 
2208
    return tok;
 
2209
 
 
2210
  VERROR1:
 
2211
    fprintf(stderr,"asc_getToken: Error occurred (bailing out).\n");
 
2212
    return VNULL;
 
2213
}
 
2214
 
 
2215
/*
 
2216
 * ***************************************************************************
 
2217
 * Routine:  readn
 
2218
 *
 
2219
 * Purpose:  A fixed-up file-descriptor read (for UNIX/INET).
 
2220
 *
 
2221
 * Notes:    Fixes the "short read" problem if the operating system
 
2222
 *           is interrupted during the read.  Calls the usual 
 
2223
 *           file-descriptor read repeatedly until n characters are 
 
2224
 *           actually read in.  Returns the number of characters 
 
2225
 *           actually read in.  Returns -1 on error.
 
2226
 *
 
2227
 *           Includes my WINSOCK fixes (err, rather hacks).
 
2228
 *
 
2229
 * Author:   Michael Holst (first of two jewels from Rick Stevens' book)
 
2230
 * ***************************************************************************
 
2231
 */
 
2232
VPRIVATE int readn(int fd, void *vptr, unsigned int n)
 
2233
{
 
2234
    char *ptr;
 
2235
    unsigned int nleft;
 
2236
    int  nread;
 
2237
 
 
2238
    ptr = vptr;
 
2239
    nleft = n;
 
2240
    while (nleft > 0) {
 
2241
        if ((nread = recv(fd,ptr,nleft,0)) < 0) {
 
2242
#if defined(HAVE_WINSOCK_H)
 
2243
            if (WSAGetLastError() == WSAEINTR) {
 
2244
                nread = 0;
 
2245
            } else if (WSAGetLastError() == WSAEWOULDBLOCK) {
 
2246
                nread = 0;
 
2247
            } else { return(-1); }
 
2248
#else
 
2249
            if (errno == EINTR) {
 
2250
                nread = 0;
 
2251
            } else if (errno == EWOULDBLOCK) {
 
2252
                nread = 0;
 
2253
            } else { return(-1); }
 
2254
#endif
 
2255
        } else if (nread == 0) {
 
2256
            break;
 
2257
        }
 
2258
        nleft -= nread;
 
2259
        ptr += nread;
 
2260
    }
 
2261
    return (n-nleft);
 
2262
}
 
2263
 
 
2264
/*
 
2265
 * ***************************************************************************
 
2266
 * Routine:  writen
 
2267
 *
 
2268
 * Purpose:  A fixed-up file-descriptor write (for UNIX/INET).
 
2269
 *
 
2270
 * Notes:    Fixes the "short write" problem if the operating system
 
2271
 *           has buffer overflow problems.  Calls the usual 
 
2272
 *           file-descriptor write repeatedly until the input buffer 
 
2273
 *           actually gets written out.  Returns the number of 
 
2274
 *           characters actually written out.  Returns -1 on error.
 
2275
 *
 
2276
 * Author:   Michael Holst (second of two jewels from Rick Stevens' book)
 
2277
 * ***************************************************************************
 
2278
 */
 
2279
VPRIVATE int writen(int fd, void *vptr, unsigned int n)
 
2280
{
 
2281
    char *ptr;
 
2282
    unsigned int nleft;
 
2283
    int  nwritten;
 
2284
 
 
2285
    ptr = vptr;
 
2286
    nleft = n;
 
2287
    while (nleft > 0) {
 
2288
        if ((nwritten = send(fd,ptr,nleft,0)) <= 0) {
 
2289
            if (errno == EINTR) {
 
2290
                nwritten = 0;
 
2291
            } else {
 
2292
                return(-1);
 
2293
            }
 
2294
        }
 
2295
        nleft -= nwritten;
 
2296
        ptr += nwritten;
 
2297
    }
 
2298
    return(n);
 
2299
}
 
2300
 
 
2301
/*
 
2302
 * ***************************************************************************
 
2303
 * Routine:  Vio_bufTake
 
2304
 *
 
2305
 * Purpose:  Set the pointer to the internal buffer.
 
2306
 *
 
2307
 * Author:   Michael Holst
 
2308
 * ***************************************************************************
 
2309
 */
 
2310
VPUBLIC void Vio_bufTake(Vio *thee, char *buf, int bufsize)
 
2311
{
 
2312
    /* make sure Vio was started */
 
2313
    VJMPERR1( VIOstarted );
 
2314
 
 
2315
    /* clear the internal buffer */
 
2316
    if (thee->VIObuffer != VNULL) {
 
2317
        free( thee->VIObuffer );
 
2318
        thee->VIObuffer = VNULL;
 
2319
    }
 
2320
 
 
2321
    /* now set the buffer */
 
2322
    thee->VIObuffer    = buf;
 
2323
    thee->VIObufferLen = bufsize;
 
2324
    thee->VIObufferPtr = 0;
 
2325
 
 
2326
    /* return without error */
 
2327
    return;
 
2328
 
 
2329
  VERROR1:
 
2330
    fprintf(stderr,"Vio_bufTake: Vio library has not been started.\n");
 
2331
    return;
 
2332
}
 
2333
 
 
2334
/*
 
2335
 * ***************************************************************************
 
2336
 * Routine:  Vio_bufGive
 
2337
 *
 
2338
 * Purpose:  Return the pointer to the internal buffer.
 
2339
 *
 
2340
 * Author:   Michael Holst
 
2341
 * ***************************************************************************
 
2342
 */
 
2343
VPUBLIC char* Vio_bufGive(Vio *thee)
 
2344
{
 
2345
    char *tmp;
 
2346
 
 
2347
    /* make sure Vio was started */
 
2348
    VJMPERR1( VIOstarted );
 
2349
 
 
2350
    /* grab the pointer */
 
2351
    tmp = thee->VIObuffer;
 
2352
 
 
2353
    /* reset things for the hand-off */
 
2354
    thee->VIObufferLen = 0;
 
2355
    thee->VIObuffer = VNULL;
 
2356
 
 
2357
    /* return without error */
 
2358
    return tmp;
 
2359
 
 
2360
  VERROR1:
 
2361
    fprintf(stderr,"Vio_bufGive: Vio library has not been started.\n");
 
2362
    return VNULL;
 
2363
}
 
2364
 
 
2365
/*
 
2366
 * ***************************************************************************
 
2367
 * Routine:  Vio_bufSize
 
2368
 *
 
2369
 * Purpose:  Return the length of the internal buffer.
 
2370
 *
 
2371
 * Author:   Michael Holst
 
2372
 * ***************************************************************************
 
2373
 */
 
2374
VPUBLIC int Vio_bufSize(Vio *thee)
 
2375
{
 
2376
    /* make sure Vio was started */
 
2377
    VJMPERR1( VIOstarted );
 
2378
 
 
2379
    /* return without error */
 
2380
    return thee->VIObufferLen;
 
2381
 
 
2382
  VERROR1:
 
2383
    fprintf(stderr,"Vio_bufSize: Vio library has not been started.\n");
 
2384
    return 0;
 
2385
}
 
2386
 
 
2387
/*
 
2388
 * ***************************************************************************
 
2389
 * Routine:  Vio_socketOpen
 
2390
 *
 
2391
 * Purpose:  Socket open for read or write.
 
2392
 *
 
2393
 * Author:   Michael Holst
 
2394
 * ***************************************************************************
 
2395
 */
 
2396
VPUBLIC Vio *Vio_socketOpen(char *key,
 
2397
    const char *iodev, const char *iofmt,
 
2398
    const char *iohost, const char *iofile)
 
2399
{
 
2400
    static Vio *sock;
 
2401
 
 
2402
    /* make sure Vio was started */
 
2403
    VJMPERR1( VIOstarted );
 
2404
 
 
2405
    /* setup for a read */
 
2406
    if (!strcmp("r",key)) {
 
2407
 
 
2408
        /* Open device for READ */
 
2409
        if ( VNULL == (sock=Vio_ctor(iodev,iofmt,iohost,iofile,"r")) ) {
 
2410
            fprintf(stderr,"Vio_socketOpen: Problem opening(read) <%s>\n",
 
2411
                iofile);
 
2412
            VJMPERR2( 0 );
 
2413
        }
 
2414
 
 
2415
        /* START READ (blocking accept) */
 
2416
        if ( 0 > Vio_accept(sock,0) ) {
 
2417
            fprintf(stderr,"Vio_socketOpen: Problem accepting(read) <%s>\n",
 
2418
                iofile);
 
2419
            /* destroy the socket before we return */
 
2420
            Vio_dtor( &sock );
 
2421
            VJMPERR2( 0 );
 
2422
        }
 
2423
 
 
2424
    /* setup for a write */
 
2425
    } else if (!strcmp("w",key)) {
 
2426
 
 
2427
        /* Open device for WRITE */
 
2428
        if ( VNULL == (sock=Vio_ctor(iodev,iofmt,iohost,iofile,"w")) ) {
 
2429
            fprintf(stderr,"Vio_socketOpen: Problem opening(write) <%s>\n",
 
2430
                iofile);
 
2431
            VJMPERR2( 0 );
 
2432
        }
 
2433
 
 
2434
        /* START WRITE (blocking connect) */
 
2435
        if ( 0 > Vio_connect(sock,0) ) {
 
2436
            fprintf(stderr,"Vio_socketOpen: Problem connecting(write) <%s>\n",
 
2437
                iofile);
 
2438
            /* destroy the socket before we return */
 
2439
            Vio_dtor( &sock );
 
2440
            VJMPERR2( 0 );
 
2441
        }
 
2442
 
 
2443
    } else {
 
2444
        fprintf(stderr,"Vio_socketOpen: Internal logic error.\n");
 
2445
        VJMPERR2( 0 );
 
2446
    }
 
2447
 
 
2448
    /* some i/o */
 
2449
#if 0
 
2450
    fprintf(stderr,"Vio_socketOpen: iodev =<%s>\n", iodev);
 
2451
    fprintf(stderr,"Vio_socketOpen: iofmt =<%s>\n", iofmt);
 
2452
    fprintf(stderr,"Vio_socketOpen: iohost=<%s>\n", iohost);
 
2453
    fprintf(stderr,"Vio_socketOpen: iofile=<%s>\n", iofile);
 
2454
#endif
 
2455
 
 
2456
    /* return without error */
 
2457
    return sock;
 
2458
 
 
2459
  VERROR1:
 
2460
    fprintf(stderr,"Vio_socketOpen: Vio library has not been started.\n");
 
2461
    return VNULL;
 
2462
 
 
2463
  VERROR2: 
 
2464
    fprintf(stderr,"Vio_socketOpen: bailing out.\n");
 
2465
    return VNULL; 
 
2466
}
 
2467
 
 
2468
/*
 
2469
 * ***************************************************************************
 
2470
 * Routine:  Vio_socketClose
 
2471
 *
 
2472
 * Purpose:  Socket close from read or write.
 
2473
 *
 
2474
 * Author:   Michael Holst
 
2475
 * ***************************************************************************
 
2476
 */
 
2477
VPUBLIC void Vio_socketClose(Vio **sock)
 
2478
{
 
2479
    /* make sure Vio was started */
 
2480
    VJMPERR1( VIOstarted );
 
2481
 
 
2482
    VJMPERR2( VNULL != *sock );
 
2483
 
 
2484
    /* FINISH READ (release subsocket if we had one) */
 
2485
    if ((*sock)->rwkey == VIO_R) {
 
2486
        Vio_acceptFree(*sock);
 
2487
 
 
2488
    /* FINISH WRITE */
 
2489
    } else if ((*sock)->rwkey == VIO_W) {
 
2490
        Vio_connectFree(*sock);
 
2491
 
 
2492
    /* Problems... */
 
2493
    } else {
 
2494
        VJMPERR2( 0 );
 
2495
    }
 
2496
 
 
2497
    /* return without error */
 
2498
    Vio_dtor(sock);
 
2499
    return;
 
2500
 
 
2501
  VERROR1:
 
2502
    fprintf(stderr,"Vio_socketClose: Vio library has not been started.\n");
 
2503
    return;
 
2504
 
 
2505
  VERROR2: 
 
2506
    fprintf(stderr,"Vio_socketClose: bailing out.\n");
 
2507
    return; 
 
2508
}
 
2509