]>
Commit | Line | Data |
---|---|---|
1 | Submitted By: LFS Book <lfs-book@linuxfromscratch.org> | |
2 | Date: 2003-10-05 | |
3 | Initial Package Version: 5.38 | |
4 | Origin: Redhat RPM (Patch by HJ Lu) | |
5 | Description: NA | |
6 | diff -uNr expect-5.38.orig/exp_chan.c expect-5.38/exp_chan.c | |
7 | --- expect-5.38.orig/exp_chan.c 2002-02-12 13:00:55.000000000 +1100 | |
8 | +++ expect-5.38/exp_chan.c 2003-03-01 10:36:18.000000000 +1100 | |
9 | @@ -519,6 +519,7 @@ | |
10 | esPtr->buffer = Tcl_NewStringObj("",0); | |
11 | Tcl_IncrRefCount(esPtr->buffer); | |
12 | esPtr->umsize = exp_default_match_max; | |
13 | + esPtr->umsize_changed = exp_default_match_max_changed; | |
14 | /* this will reallocate object with an appropriate sized buffer */ | |
15 | expAdjust(esPtr); | |
16 | ||
17 | diff -uNr expect-5.38.orig/exp_command.h expect-5.38/exp_command.h | |
18 | --- expect-5.38.orig/exp_command.h 2002-04-08 08:57:20.000000000 +1000 | |
19 | +++ expect-5.38/exp_command.h 2003-03-01 10:36:18.000000000 +1100 | |
20 | @@ -25,6 +25,7 @@ | |
21 | EXTERN char * exp_get_var _ANSI_ARGS_((Tcl_Interp *,char *)); | |
22 | ||
23 | EXTERN int exp_default_match_max; | |
24 | +EXTERN int exp_default_match_max_changed; | |
25 | EXTERN int exp_default_parity; | |
26 | EXTERN int exp_default_rm_nulls; | |
27 | ||
28 | @@ -97,6 +98,7 @@ | |
29 | int msize; /* # of bytes that buffer can hold (max) */ | |
30 | int umsize; /* # of bytes (min) that is guaranteed to match */ | |
31 | /* this comes from match_max command */ | |
32 | + int umsize_changed; /* is umsize changed by user? */ | |
33 | int printed; /* # of bytes written to stdout (if logging on) */ | |
34 | /* but not actually returned via a match yet */ | |
35 | int echoed; /* additional # of bytes (beyond "printed" above) */ | |
36 | diff -uNr expect-5.38.orig/expect.c expect-5.38/expect.c | |
37 | --- expect-5.38.orig/expect.c 2002-04-08 09:00:33.000000000 +1000 | |
38 | +++ expect-5.38/expect.c 2003-03-01 10:36:18.000000000 +1100 | |
39 | @@ -41,8 +41,17 @@ | |
40 | #include "tcldbg.h" | |
41 | #endif | |
42 | ||
43 | +/* The initial length is 2000. We increment it by 2000. The maximum | |
44 | + is 8MB (0x800000). */ | |
45 | +#define EXP_MATCH_MAX 2000 | |
46 | +#define EXP_MATCH_INC 2000 | |
47 | +#define EXP_MATCH_STEP_LIMIT 0x700000 | |
48 | +#define EXP_MATCH_LIMIT 0x800000 | |
49 | +#define EXP_MATCH_LIMIT_QUOTE "0x800000" | |
50 | + | |
51 | /* initial length of strings that we can guarantee patterns can match */ | |
52 | -int exp_default_match_max = 2000; | |
53 | +int exp_default_match_max = EXP_MATCH_MAX; | |
54 | +int exp_default_match_max_changed = 0; | |
55 | #define INIT_EXPECT_TIMEOUT_LIT "10" /* seconds */ | |
56 | #define INIT_EXPECT_TIMEOUT 10 /* seconds */ | |
57 | int exp_default_parity = TRUE; | |
58 | @@ -1618,6 +1627,76 @@ | |
59 | return newsize; | |
60 | } | |
61 | ||
62 | +/* returns # of bytes until we see a newline at the end or EOF. */ | |
63 | +/*ARGSUSED*/ | |
64 | +static int | |
65 | +expReadNewLine(interp,esPtr,save_flags) /* INTL */ | |
66 | +Tcl_Interp *interp; | |
67 | +ExpState *esPtr; | |
68 | +int save_flags; | |
69 | +{ | |
70 | + int size; | |
71 | + int exp_size; | |
72 | + int full_size; | |
73 | + int count; | |
74 | + char *str; | |
75 | + | |
76 | + count = 0; | |
77 | + for (;;) { | |
78 | + exp_size = expSizeGet(esPtr); | |
79 | + | |
80 | + /* When we reach the limit, we will only read one char at a | |
81 | + time. */ | |
82 | + if (esPtr->umsize >= EXP_MATCH_STEP_LIMIT) | |
83 | + size = TCL_UTF_MAX; | |
84 | + else | |
85 | + size = exp_size; | |
86 | + | |
87 | + if (exp_size + TCL_UTF_MAX >= esPtr->msize) { | |
88 | + if (esPtr->umsize >= EXP_MATCH_LIMIT) { | |
89 | + expDiagLogU("WARNING: interact buffer is full. probably your program\r\n"); | |
90 | + expDiagLogU("is not interactive or has a very long output line. The\r\n"); | |
91 | + expDiagLogU("current limit is " EXP_MATCH_LIMIT_QUOTE ".\r\n"); | |
92 | + expDiagLogU("Dumping first half of buffer in order to continue\r\n"); | |
93 | + expDiagLogU("Recommend you enlarge the buffer.\r\n"); | |
94 | + exp_buffer_shuffle(interp,esPtr,save_flags,EXPECT_OUT,"expect"); | |
95 | + return count; | |
96 | + } | |
97 | + else { | |
98 | + esPtr->umsize += EXP_MATCH_INC; | |
99 | + expAdjust(esPtr); | |
100 | + } | |
101 | + } | |
102 | + | |
103 | + full_size = esPtr->msize - (size / TCL_UTF_MAX); | |
104 | + size = Tcl_ReadChars(esPtr->channel, | |
105 | + esPtr->buffer, | |
106 | + full_size, | |
107 | + 1 /* append */); | |
108 | + if (size > 0) { | |
109 | + count += size; | |
110 | + /* We try again if there are more to read and we haven't | |
111 | + seen a newline at the end. */ | |
112 | + if (size == full_size) { | |
113 | + str = Tcl_GetStringFromObj(esPtr->buffer, &size); | |
114 | + if (str[size - 1] != '\n') | |
115 | + continue; | |
116 | + } | |
117 | + } | |
118 | + else { | |
119 | + /* It is even trickier. We got an error from read. We have | |
120 | + to recover from it. Let's make sure the size of | |
121 | + buffer is correct. It can be corrupted. */ | |
122 | + str = Tcl_GetString(esPtr->buffer); | |
123 | + Tcl_SetObjLength(esPtr->buffer, strlen(str)); | |
124 | + } | |
125 | + | |
126 | + break; | |
127 | + } | |
128 | + | |
129 | + return count; | |
130 | +} | |
131 | + | |
132 | /* returns # of bytes read or (non-positive) error of form EXP_XXX */ | |
133 | /* returns 0 for end of file */ | |
134 | /* If timeout is non-zero, set an alarm before doing the read, else assume */ | |
135 | @@ -1632,6 +1711,8 @@ | |
136 | { | |
137 | int cc = EXP_TIMEOUT; | |
138 | int size = expSizeGet(esPtr); | |
139 | + int full_size; | |
140 | + int count; | |
141 | ||
142 | if (size + TCL_UTF_MAX >= esPtr->msize) | |
143 | exp_buffer_shuffle(interp,esPtr,save_flags,EXPECT_OUT,"expect"); | |
144 | @@ -1648,11 +1729,43 @@ | |
145 | } | |
146 | #endif | |
147 | ||
148 | - | |
149 | + /* FIXME: If we ask less than what is available in the tcl buffer | |
150 | + when tcl has seen EOF, we will throw away the remaining data | |
151 | + since the next read will get EOF. Since expect is line-oriented, | |
152 | + we exand our buffer to get EOF or the next newline at the end of | |
153 | + the input buffer. I don't know if it is the right fix. H.J. */ | |
154 | + count = 0; | |
155 | + full_size = esPtr->msize - (size / TCL_UTF_MAX); | |
156 | cc = Tcl_ReadChars(esPtr->channel, | |
157 | - esPtr->buffer, | |
158 | - esPtr->msize - (size / TCL_UTF_MAX), | |
159 | - 1 /* append */); | |
160 | + esPtr->buffer, | |
161 | + full_size, | |
162 | + 1 /* append */); | |
163 | + if (cc > 0) { | |
164 | + count += cc; | |
165 | + /* It gets very tricky. There are more to read. We will expand | |
166 | + our buffer and get EOF or a newline at the end unless the | |
167 | + buffer length has been changed. */ | |
168 | + if (cc == full_size) { | |
169 | + char *str; | |
170 | + str = Tcl_GetStringFromObj(esPtr->buffer, &size); | |
171 | + if (str[size - 1] != '\n') { | |
172 | + if (esPtr->umsize_changed) { | |
173 | + char buf[20]; /* big enough for 64bit int in hex. */ | |
174 | + snprintf(buf,sizeof(buf),"0x%x", esPtr->umsize); | |
175 | + expDiagLogU("WARNING: interact buffer is not large enough to hold\r\n"); | |
176 | + expDiagLogU("all output. probably your program is not interactive or\r\n"); | |
177 | + expDiagLogU("has a very long output line. The current limit is "); | |
178 | + expDiagLogU(buf); | |
179 | + expDiagLogU(".\r\n"); | |
180 | + } | |
181 | + else { | |
182 | + cc = expReadNewLine(interp,esPtr,save_flags); | |
183 | + if (cc > 0) | |
184 | + count += cc; | |
185 | + } | |
186 | + } | |
187 | + } | |
188 | + } | |
189 | i_read_errno = errno; | |
190 | ||
191 | #ifdef SIMPLE_EVENT | |
192 | @@ -1673,7 +1786,7 @@ | |
193 | } | |
194 | } | |
195 | #endif | |
196 | - return cc; | |
197 | + return count > 0 ? count : cc; | |
198 | } | |
199 | ||
200 | /* | |
201 | @@ -2746,8 +2859,14 @@ | |
202 | return(TCL_ERROR); | |
203 | } | |
204 | ||
205 | - if (Default) exp_default_match_max = size; | |
206 | - else esPtr->umsize = size; | |
207 | + if (Default) { | |
208 | + exp_default_match_max = size; | |
209 | + exp_default_match_max_changed = 1; | |
210 | + } | |
211 | + else { | |
212 | + esPtr->umsize = size; | |
213 | + esPtr->umsize_changed = 1; | |
214 | + } | |
215 | ||
216 | return(TCL_OK); | |
217 | } |