~ubuntu-branches/ubuntu/natty/expect/natty

« back to all changes in this revision

Viewing changes to exp_chan.c

  • Committer: Bazaar Package Importer
  • Author(s): Sergei Golovan
  • Date: 2009-10-23 12:24:40 UTC
  • mfrom: (5.1.4 sid)
  • Revision ID: james.westby@ubuntu.com-20091023122440-5uujs2py5bx5v7vs
* Added buid conflict with autoconf2.13 because autoconf 2.50 or newer is
  required to process configure.in template.
* Fixed building with the current config.sub and config.guess from
  autotools-dev package (closes: #551332).
* Fixed cleaning after build is done.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* 
2
 
 * tclUnixChan.c
 
2
 * exp_chan.c
3
3
 *
4
4
 *      Channel driver for Expect channels.
5
5
 *      Based on UNIX File channel from TclUnixChan.c
35
35
#include "exp_prog.h"
36
36
#include "exp_command.h"
37
37
#include "exp_log.h"
 
38
#include "tcldbg.h" /* Dbg_StdinMode */
38
39
 
 
40
extern int              expSetBlockModeProc _ANSI_ARGS_((int fd, int mode));
39
41
static int              ExpBlockModeProc _ANSI_ARGS_((ClientData instanceData,
40
42
                            int mode));
41
43
static int              ExpCloseProc _ANSI_ARGS_((ClientData instanceData,
56
58
 
57
59
Tcl_ChannelType expChannelType = {
58
60
    "exp",                              /* Type name. */
59
 
 
60
 
    /* Tcl_ChannelType was redefined in 8.3.2 but Tcl does not
61
 
       advertise its patch level in a useful way so for simplicity,
62
 
       assume 8.3 is a modern 8.3, i.e. 8.3.2
63
 
    */
64
 
 
65
 
#if (TCL_MAJOR_VERSION > 8) || ((TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 3))
66
 
    TCL_CHANNEL_VERSION_2,
67
 
    ExpCloseProc,                       /* Close proc. */
68
 
    ExpInputProc,                       /* Input proc. */
69
 
    ExpOutputProc,                      /* Output proc. */
70
 
    NULL,                               /* Seek proc. */
71
 
    NULL,                               /* Set option proc. */
72
 
    NULL,                               /* Get option proc. */
73
 
    ExpWatchProc,                       /* Initialize notifier. */
74
 
    ExpGetHandleProc,                   /* Get OS handles out of channel. */
75
 
    NULL,                               /* Close2 proc */
76
 
    ExpBlockModeProc,                   /* Set blocking/nonblocking mode.*/
77
 
    NULL,                               /* Flush proc. */
78
 
    NULL,                               /* Handle channel event proc. */
79
 
#else
80
 
    /* Expect channels are always non-blocking */
81
 
    ExpBlockModeProc,                   /* Set blocking/nonblocking mode.*/
82
 
    ExpCloseProc,                       /* Close proc. */
83
 
    ExpInputProc,                       /* Input proc. */
84
 
    ExpOutputProc,                      /* Output proc. */
85
 
    NULL,                               /* Seek proc. */
86
 
    NULL,                               /* Set option proc. */
87
 
    NULL,                               /* Get option proc. */
88
 
    ExpWatchProc,                       /* Initialize notifier. */
89
 
    ExpGetHandleProc,                   /* Get OS handles out of channel. */
90
 
    NULL,                               /* Close2 proc */
91
 
#endif
 
61
    ExpBlockModeProc,                   /* Set blocking/nonblocking mode.*/
 
62
    ExpCloseProc,                       /* Close proc. */
 
63
    ExpInputProc,                       /* Input proc. */
 
64
    ExpOutputProc,                      /* Output proc. */
 
65
    NULL,                               /* Seek proc. */
 
66
    NULL,                               /* Set option proc. */
 
67
    NULL,                               /* Get option proc. */
 
68
    ExpWatchProc,                       /* Initialize notifier. */
 
69
    ExpGetHandleProc,                   /* Get OS handles out of channel. */
 
70
    NULL,                               /* Close2 proc */
92
71
};
93
72
 
94
73
typedef struct ThreadSpecificData {
131
110
                                         * TCL_MODE_NONBLOCKING. */
132
111
{
133
112
    ExpState *esPtr = (ExpState *) instanceData;
 
113
 
 
114
    if (esPtr->fdin == 0) {
 
115
        /* Forward status to debugger. Required for FIONBIO systems,
 
116
         * which are unable to query the fd for its current state.
 
117
         */
 
118
        Dbg_StdinMode (mode);
 
119
    }
 
120
 
 
121
    /* [Expect SF Bug 1108551] (July 7 2005)
 
122
     * Exclude manipulation of the blocking status for stdin/stderr.
 
123
     *
 
124
     * This is handled by the Tcl core itself and we must absolutely
 
125
     * not pull the rug out from under it. The standard setting to
 
126
     * non-blocking will mess with the core which had them set to
 
127
     * blocking, and makes all its decisions based on that assumption.
 
128
     * Setting to non-blocking can cause hangs and crashes.
 
129
     *
 
130
     * Stdin is ok however, apparently.
 
131
     * (Sep 9 2005) No, it is not.
 
132
     */
 
133
 
 
134
    if ((esPtr->fdin == 0) ||
 
135
        (esPtr->fdin == 1) ||
 
136
        (esPtr->fdin == 2)) {
 
137
      return 0;
 
138
    }
 
139
 
 
140
    return expSetBlockModeProc (esPtr->fdin, mode);
 
141
}
 
142
 
 
143
int
 
144
expSetBlockModeProc(fd, mode)
 
145
    int fd;
 
146
    int mode;                           /* The mode to set. Can be one of
 
147
                                         * TCL_MODE_BLOCKING or
 
148
                                         * TCL_MODE_NONBLOCKING. */
 
149
{
134
150
    int curStatus;
135
151
    /*printf("ExpBlockModeProc(%d)\n",mode);
136
 
      printf("fdin = %d\n",esPtr->fdin);*/
 
152
      printf("fdin = %d\n",fd);*/
137
153
 
138
154
#ifndef USE_FIONBIO
139
 
    curStatus = fcntl(esPtr->fdin, F_GETFL);
 
155
    curStatus = fcntl(fd, F_GETFL);
140
156
    /*printf("curStatus = %d\n",curStatus);*/
141
157
    if (mode == TCL_MODE_BLOCKING) {
142
158
        curStatus &= (~(O_NONBLOCK));
144
160
        curStatus |= O_NONBLOCK;
145
161
    }
146
162
    /*printf("new curStatus %d\n",curStatus);*/
147
 
    if (fcntl(esPtr->fdin, F_SETFL, curStatus) < 0) {
 
163
    if (fcntl(fd, F_SETFL, curStatus) < 0) {
148
164
        return errno;
149
165
    }
150
 
    curStatus = fcntl(esPtr->fdin, F_GETFL);
 
166
    curStatus = fcntl(fd, F_GETFL);
151
167
#else /* USE_FIONBIO */
152
168
    if (mode == TCL_MODE_BLOCKING) {
153
169
        curStatus = 0;
154
170
    } else {
155
171
        curStatus = 1;
156
172
    }
157
 
    if (ioctl(esPtr->fdin, (int) FIONBIO, &curStatus) < 0) {
 
173
    if (ioctl(fd, (int) FIONBIO, &curStatus) < 0) {
158
174
        return errno;
159
175
    }
160
176
#endif /* !USE_FIONBIO */
161
177
    return 0;
162
178
}
163
 
 
164
179
/*
165
180
 *----------------------------------------------------------------------
166
181
 *
248
263
    *errorCodePtr = 0;
249
264
 
250
265
    if (toWrite < 0) Tcl_Panic("ExpOutputProc: called with negative char count");
 
266
    if (toWrite ==0) {
 
267
        return 0;
 
268
    }
251
269
 
252
270
    written = write(esPtr->fdout, buf, (size_t) toWrite);
253
271
    if (written == 0) {
307
325
    Tcl_DeleteFileHandler(esPtr->fdin);
308
326
#endif /*0*/
309
327
 
310
 
    Tcl_DecrRefCount(esPtr->buffer);
 
328
    Tcl_Free((char*)esPtr->input.buffer);
 
329
    Tcl_DecrRefCount (esPtr->input.newchars);
311
330
 
312
331
    /* Actually file descriptor should have been closed earlier. */
313
332
    /* So do nothing here */
428
447
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
429
448
    return tsdPtr->channelCount;
430
449
}
431
 
 
 
450
#if 0 /* Converted to macros */
432
451
int
433
452
expSizeGet(esPtr)
434
453
    ExpState *esPtr;
435
454
{
436
 
    int len;
437
 
    Tcl_GetStringFromObj(esPtr->buffer,&len);
438
 
    return len;
 
455
    return esPtr->input.use;
439
456
}
440
457
 
441
458
int
442
459
expSizeZero(esPtr)
443
460
    ExpState *esPtr;
444
461
{
445
 
    int len;
446
 
    Tcl_GetStringFromObj(esPtr->buffer,&len);
447
 
    return (len == 0);
 
462
    return (esPtr->input.use == 0);
448
463
}
449
 
 
 
464
#endif
450
465
/* return 0 for success or negative for failure */
451
466
int
452
467
expWriteChars(esPtr,buffer,lenBytes)
459
474
  rc = Tcl_WriteChars(esPtr->channel,buffer,lenBytes);
460
475
  if ((rc == -1) && (errno == EAGAIN)) goto retry;
461
476
 
 
477
  if (!exp_strict_write) {
 
478
    /*
 
479
     * 5.41 compatbility behaviour. Ignore any and all write errors
 
480
     * the OS may have thrown.
 
481
     */
 
482
    return 0;
 
483
  }
 
484
 
462
485
  /* just return 0 rather than positive byte counts */
463
486
  return ((rc > 0) ? 0 : rc);
464
487
}
465
488
 
 
489
int
 
490
expWriteCharsUni(esPtr,buffer,lenChars)
 
491
     ExpState *esPtr;
 
492
     Tcl_UniChar *buffer;
 
493
     int lenChars;
 
494
{
 
495
  int rc;
 
496
  Tcl_DString ds;
 
497
 
 
498
  Tcl_DStringInit (&ds);
 
499
  Tcl_UniCharToUtfDString (buffer,lenChars,&ds);
 
500
 
 
501
  rc = expWriteChars(esPtr,Tcl_DStringValue (&ds), Tcl_DStringLength (&ds));
 
502
 
 
503
  Tcl_DStringFree (&ds);
 
504
 
 
505
  return rc;
 
506
}
 
507
 
466
508
void
467
509
expStateFree(esPtr)
468
510
    ExpState *esPtr;
550
592
            return esPtr;
551
593
        }
552
594
    }
 
595
    /* Should not reach this location. If it happens return a value
 
596
     * causing an easy crash */
 
597
    return NULL;
553
598
}
554
599
 
555
600
void
616
661
    Tcl_SetChannelOption(interp,esPtr->channel,"-translation","lf");
617
662
 
618
663
    esPtr->pid = pid;
619
 
    esPtr->msize = 0;
620
 
 
621
 
    /* initialize a dummy buffer */
622
 
    esPtr->buffer = Tcl_NewStringObj("",0);
623
 
    Tcl_IncrRefCount(esPtr->buffer);
 
664
 
 
665
    esPtr->input.max    = 1;
 
666
    esPtr->input.use    = 0;
 
667
    esPtr->input.buffer = (Tcl_UniChar*) Tcl_Alloc (sizeof (Tcl_UniChar));
 
668
    esPtr->input.newchars = Tcl_NewObj();
 
669
    Tcl_IncrRefCount (esPtr->input.newchars);
 
670
 
624
671
    esPtr->umsize = exp_default_match_max;
625
672
    /* this will reallocate object with an appropriate sized buffer */
626
673
    expAdjust(esPtr);
633
680
    esPtr->key = expect_key++;
634
681
    esPtr->force_read = FALSE;
635
682
    esPtr->fg_armed = FALSE;
636
 
    esPtr->channel_orig = 0;
 
683
    esPtr->chan_orig = 0;
637
684
    esPtr->fd_slave = EXP_NOFD;
638
685
#ifdef HAVE_PTYTRAP
639
686
    esPtr->slave_name = 0;