resetting manifest requested domain to floor
[platform/upstream/expect.git] / exp_command.h
1 /* command.h - definitions for expect commands
2
3 Written by: Don Libes, NIST, 2/6/90
4
5 Design and implementation of this program was paid for by U.S. tax
6 dollars.  Therefore it is public domain.  However, the author and NIST
7 would appreciate credit if this program or parts of it are used.
8 */
9
10 #ifdef HAVE_SYS_WAIT_H
11   /* ISC doesn't def WNOHANG unless _POSIX_SOURCE is def'ed */
12 # ifdef WNOHANG_REQUIRES_POSIX_SOURCE
13 #  define _POSIX_SOURCE
14 # endif
15 # include <sys/wait.h>
16 # ifdef WNOHANG_REQUIRES_POSIX_SOURCE
17 #  undef _POSIX_SOURCE
18 # endif
19 #endif
20
21 #ifdef __APPLE__
22 /* From: "Daniel A. Steffen" <steffen@ics.mq.edu.au> */
23 # undef panic
24 #endif
25
26 #include <tclPort.h>
27
28 #define EXP_CHANNELNAMELEN (16 + TCL_INTEGER_SPACE)
29
30 EXTERN char *           exp_get_var _ANSI_ARGS_((Tcl_Interp *,char *));
31
32 EXTERN int exp_default_match_max;
33 EXTERN int exp_default_parity;
34 EXTERN int exp_default_rm_nulls;
35 EXTERN int exp_default_close_on_eof;
36
37 EXTERN int              exp_one_arg_braced _ANSI_ARGS_((Tcl_Obj *));
38
39 EXTERN Tcl_Obj*         exp_eval_with_one_arg _ANSI_ARGS_((ClientData,
40                                 Tcl_Interp *, struct Tcl_Obj * CONST objv[]));
41
42 EXTERN void             exp_lowmemcpy _ANSI_ARGS_((char *,char *,int));
43
44 EXTERN int exp_flageq_code _ANSI_ARGS_((char *,char *,int));
45
46 #define exp_flageq(flag,string,minlen) \
47 (((string)[0] == (flag)[0]) && (exp_flageq_code(((flag)+1),((string)+1),((minlen)-1))))
48
49 /* exp_flageq for single char flags */
50 #define exp_flageq1(flag,string) \
51         ((string[0] == flag) && (string[1] == '\0'))
52
53 #define EXP_SPAWN_ID_USER               0
54 #define EXP_SPAWN_ID_ANY_LIT            "-1"
55
56 #define EXP_CHANNEL_PREFIX "exp"
57 #define EXP_CHANNEL_PREFIX_LENGTH 3
58 #define isExpChannelName(name) \
59     (0 == strncmp(name,EXP_CHANNEL_PREFIX,EXP_CHANNEL_PREFIX_LENGTH))
60
61 #define exp_is_stdinfd(x)       ((x) == 0)
62 #define exp_is_devttyfd(x)      ((x) == exp_dev_tty)
63
64 #define EXP_NOPID       0       /* Used when there is no associated pid to */
65                                 /* wait for.  For example: */
66                                 /* 1) When fd opened by someone else, e.g., */
67                                 /* Tcl's open */
68                                 /* 2) When entry not in use */
69                                 /* 3) To tell user pid of "spawn -open" */
70                                 /* 4) stdin, out, error */
71
72 #define EXP_NOFD        -1
73
74 /* these are occasionally useful to distinguish between various expect */
75 /* commands and are also used as array indices into the per-fd eg[] arrays */
76 #define EXP_CMD_BEFORE  0
77 #define EXP_CMD_AFTER   1
78 #define EXP_CMD_BG      2
79 #define EXP_CMD_FG      3
80
81 /*
82  * This structure describes per-instance state of an Exp channel.
83  */
84
85 typedef struct ExpOrigin {
86   int         refCount;       /* Number of times this channel is used. */
87   Tcl_Channel channel_orig;   /* If opened by someone else, i.e. tcl::open */
88 } ExpOrigin;
89
90
91 typedef struct ExpUniBuf {
92     Tcl_UniChar* buffer;    /* char buffer, holdings unicode chars (fixed width) */
93     int          max;       /* number of CHARS the buffer has space for (== old msize) */
94     int          use;       /* number of CHARS the buffer is currently holding */
95     Tcl_Obj*     newchars;  /* Object to hold newly read characters */
96 } ExpUniBuf;
97
98 typedef struct ExpState {
99     Tcl_Channel channel;        /* Channel associated with this file. */
100     char name[EXP_CHANNELNAMELEN+1]; /* expect and interact set variables
101                                    to channel name, so for efficiency
102                                    cache it here */
103     int fdin;           /* input fd */
104     int fdout;          /* output fd - usually the same as fdin, although
105                            may be different if channel opened by tcl::open */
106     ExpOrigin* chan_orig;   /* If opened by someone else, i.e. tcl::open */
107     int fd_slave;       /* slave fd if "spawn -pty" used */
108
109     /* this may go away if we find it is not needed */
110     /* it might be needed by inherited channels */
111     int validMask;              /* OR'ed combination of TCL_READABLE,
112                                  * TCL_WRITABLE, or TCL_EXCEPTION: indicates
113                                  * which operations are valid on the file. */
114
115     int pid;            /* pid or EXP_NOPID if no pid */
116
117     ExpUniBuf input;    /* input buffer */
118
119     int umsize;         /* # of bytes (min) that is guaranteed to match */
120                         /* this comes from match_max command */
121     int printed;        /* # of characters! written to stdout (if logging on) */
122                         /* but not actually returned via a match yet */
123     int echoed;         /* additional # of characters (beyond "printed" above) */
124                         /* echoed back but not actually returned via a match */
125                         /* yet.  This supports interact -echo */
126
127     int rm_nulls;       /* if nulls should be stripped before pat matching */
128     int open;           /* if fdin/fdout open */
129     int user_waited;    /* if user has issued "wait" command */
130     int sys_waited;     /* if wait() (or variant) has been called */
131     int registered;     /* if channel registered */
132     WAIT_STATUS_TYPE wait;      /* raw status from wait() */
133     int parity;         /* if parity should be preserved */
134     int close_on_eof;   /* if channel should be closed automatically on eof */
135     int key;            /* unique id that identifies what command instance */
136                         /* last touched this buffer */
137     int force_read;     /* force read to occur (even if buffer already has */
138                         /* data).  This supports interact CAN_MATCH */
139     int notified;       /* If Tcl_NotifyChannel has been called and we */
140                         /* have not yet read from the channel. */
141     int notifiedMask;   /* Mask reported when notified. */
142
143     int fg_armed;       /* If we have requested Tk_CreateFileHandler to be */
144                         /* responding to foreground events.  Note that */
145                         /* other handlers can have stolen it away so this */
146                         /* doesn't necessarily mean the handler is set.  */
147                         /* However, if fg_armed is 0, then the handlers */
148                         /* definitely needs to be set.  The significance of */
149                         /* this flag is so we can remember to turn it off. */
150 #ifdef HAVE_PTYTRAP
151     char *slave_name;   /* Full name of slave, i.e., /dev/ttyp0 */
152 #endif /* HAVE_PTYTRAP */
153     /* may go away */
154     int leaveopen;      /* If we should not call Tcl's close when we close - */
155                         /* only relevant if Tcl does the original open */
156
157     Tcl_Interp *bg_interp;      /* interp to process the bg cases */
158     int bg_ecount;              /* number of background ExpStates */
159     enum {
160         blocked,        /* blocked because we are processing the */
161                         /* file handler */
162         armed,          /* normal state when bg handler in use */
163         unarmed,        /* no bg handler in use */
164         disarm_req_while_blocked        /* while blocked, a request */
165                                 /* was received to disarm it.  Rather than */
166                                 /* processing the request immediately, defer */
167                                 /* it so that when we later try to unblock */
168                                 /* we will see at that time that it should */
169                                 /* instead be disarmed */
170     } bg_status;
171
172     /*
173      * If the channel is freed while in the middle of a bg event handler,
174      * remember that and defer freeing of the ExpState structure until
175      * it is safe.
176      */
177     int freeWhenBgHandlerUnblocked;
178
179     /* If channel is closed but not yet waited on, we tie up the fd by
180      * attaching it to /dev/null.  We play this little game so that we
181      * can embed the fd in the channel name.  If we didn't tie up the
182      * fd, we'd get channel name collisions.  I'd consider naming the
183      * channels independently of the fd, but this makes debugging easier.
184      */
185     int fdBusy;
186
187     /* 
188      * stdinout and stderr never go away so that our internal refs to them
189      * don't have to be invalidated.  Having to worry about invalidating them
190      * would be a major pain.  */
191     int keepForever;
192
193     /*  Remember that "reserved" esPtrs are no longer in use. */
194     int valid;
195     
196     struct ExpState *nextPtr;   /* Pointer to next file in list of all
197                                  * file channels. */
198 } ExpState;
199
200 #define EXP_SPAWN_ID_BAD        ((ExpState *)0)
201
202 #define EXP_TIME_INFINITY       -1
203
204 extern Tcl_ChannelType expChannelType;
205
206 #define EXP_TEMPORARY   1       /* expect */
207 #define EXP_PERMANENT   2       /* expect_after, expect_before, expect_bg */
208
209 #define EXP_DIRECT      1
210 #define EXP_INDIRECT    2
211
212 EXTERN void             expAdjust _ANSI_ARGS_((ExpState *));
213 EXTERN int              expWriteChars _ANSI_ARGS_((ExpState *,char *,int));
214 EXTERN int              expWriteCharsUni _ANSI_ARGS_((ExpState *,Tcl_UniChar *,int));
215 EXTERN void             exp_buffer_shuffle _ANSI_ARGS_((Tcl_Interp *,ExpState *,int,char *,char *));
216 EXTERN int              exp_close _ANSI_ARGS_((Tcl_Interp *,ExpState *));
217 EXTERN void             exp_close_all _ANSI_ARGS_((Tcl_Interp *));
218 EXTERN void             exp_ecmd_remove_fd_direct_and_indirect 
219                                 _ANSI_ARGS_((Tcl_Interp *,int));
220 EXTERN void             exp_trap_on _ANSI_ARGS_((int));
221 EXTERN int              exp_trap_off _ANSI_ARGS_((char *));
222
223 EXTERN void             exp_strftime(char *format, const struct tm *timeptr,Tcl_DString *dstring);
224
225 #define exp_deleteProc (void (*)())0
226 #define exp_deleteObjProc (void (*)())0
227
228 EXTERN int expect_key;
229 EXTERN int exp_configure_count; /* # of times descriptors have been closed */
230                                 /* or indirect lists have been changed */
231 EXTERN int exp_nostack_dump;    /* TRUE if user has requested unrolling of */
232                                 /* stack with no trace */
233
234 EXTERN void             exp_init_pty _ANSI_ARGS_((void));
235 EXTERN void             exp_pty_exit _ANSI_ARGS_((void));
236 EXTERN void             exp_init_tty _ANSI_ARGS_((void));
237 EXTERN void             exp_init_stdio _ANSI_ARGS_((void));
238 /*EXTERN void           exp_init_expect _ANSI_ARGS_((Tcl_Interp *));*/
239 EXTERN void             exp_init_spawn_ids _ANSI_ARGS_((Tcl_Interp *));
240 EXTERN void             exp_init_spawn_id_vars _ANSI_ARGS_((Tcl_Interp *));
241 EXTERN void             exp_init_trap _ANSI_ARGS_((void));
242 EXTERN void             exp_init_send _ANSI_ARGS_((void));
243 EXTERN void             exp_init_unit_random _ANSI_ARGS_((void));
244 EXTERN void             exp_init_sig _ANSI_ARGS_((void));
245 EXTERN void             expChannelInit _ANSI_ARGS_((void));
246 EXTERN int              expChannelCountGet _ANSI_ARGS_((void));
247
248 EXTERN int              exp_tcl2_returnvalue _ANSI_ARGS_((int));
249 EXTERN int              exp_2tcl_returnvalue _ANSI_ARGS_((int));
250
251 EXTERN void             exp_rearm_sigchld _ANSI_ARGS_((Tcl_Interp *));
252 EXTERN int              exp_string_to_signal _ANSI_ARGS_((Tcl_Interp *,char *));
253
254 EXTERN char *exp_onexit_action;
255
256 #define exp_new(x)      (x *)malloc(sizeof(x))
257
258 struct exp_state_list {
259         ExpState *esPtr;
260         struct exp_state_list *next;
261 };
262
263 /* describes a -i flag */
264 struct exp_i {
265         int cmdtype;    /* EXP_CMD_XXX.  When an indirect update is */
266                         /* triggered by Tcl, this helps tell us in what */
267                         /* exp_i list to look in. */
268         int direct;     /* if EXP_DIRECT, then the spawn ids have been given */
269                         /* literally, else indirectly through a variable */
270         int duration;   /* if EXP_PERMANENT, char ptrs here had to be */
271                         /* malloc'd because Tcl command line went away - */
272                         /* i.e., in expect_before/after */
273         char *variable;
274         char *value;    /* if type == direct, this is the string that the */
275                         /* user originally supplied to the -i flag.  It may */
276                         /* lose relevance as the fd_list is manipulated */
277                         /* over time.  If type == direct, this is  the */
278                         /* cached value of variable use this to tell if it */
279                         /* has changed or not, and ergo whether it's */
280                         /* necessary to reparse. */
281
282         int ecount;     /* # of ecases this is used by */
283
284         struct exp_state_list *state_list;
285         struct exp_i *next;
286 };
287
288 EXTERN struct exp_i *   exp_new_i_complex _ANSI_ARGS_((Tcl_Interp *,
289                                         char *, int, Tcl_VarTraceProc *));
290 EXTERN struct exp_i *   exp_new_i_simple _ANSI_ARGS_((ExpState *,int));
291 EXTERN struct exp_state_list *exp_new_state _ANSI_ARGS_((ExpState *));
292 EXTERN void             exp_free_i _ANSI_ARGS_((Tcl_Interp *,struct exp_i *,
293                                         Tcl_VarTraceProc *));
294 EXTERN void             exp_free_state _ANSI_ARGS_((struct exp_state_list *));
295 EXTERN void             exp_free_state_single _ANSI_ARGS_((struct exp_state_list *));
296 EXTERN int              exp_i_update _ANSI_ARGS_((Tcl_Interp *,
297                                         struct exp_i *));
298
299 /*
300  * definitions for creating commands
301  */
302
303 #define EXP_NOPREFIX    1       /* don't define with "exp_" prefix */
304 #define EXP_REDEFINE    2       /* stomp on old commands with same name */
305
306 #define exp_proc(cmdproc) 0, cmdproc
307
308 struct exp_cmd_data {
309         char            *name;
310         Tcl_ObjCmdProc  *objproc;
311         Tcl_CmdProc     *proc;
312         ClientData      data;
313         int             flags;
314 };
315
316 EXTERN void             exp_create_commands _ANSI_ARGS_((Tcl_Interp *,
317                                                 struct exp_cmd_data *));
318 EXTERN void             exp_init_main_cmds _ANSI_ARGS_((Tcl_Interp *));
319 EXTERN void             exp_init_expect_cmds _ANSI_ARGS_((Tcl_Interp *));
320 EXTERN void             exp_init_most_cmds _ANSI_ARGS_((Tcl_Interp *));
321 EXTERN void             exp_init_trap_cmds _ANSI_ARGS_((Tcl_Interp *));
322 EXTERN void             exp_init_interact_cmds _ANSI_ARGS_((Tcl_Interp *));
323 EXTERN void             exp_init_tty_cmds();
324
325 EXTERN ExpState *       expStateCheck _ANSI_ARGS_((Tcl_Interp *,ExpState *,int,int,char *));
326 EXTERN ExpState *       expStateCurrent _ANSI_ARGS_((Tcl_Interp *,int,int,int));
327 EXTERN ExpState *       expStateFromChannelName _ANSI_ARGS_((Tcl_Interp *,char *,int,int,int,char *));
328 EXTERN void             expStateFree _ANSI_ARGS_((ExpState *));
329
330 EXTERN ExpState *       expCreateChannel _ANSI_ARGS_((Tcl_Interp *,int,int,int));
331 EXTERN ExpState *       expWaitOnAny _ANSI_ARGS_((void));
332 EXTERN ExpState *       expWaitOnOne _ANSI_ARGS_((void));
333 EXTERN void             expExpectVarsInit _ANSI_ARGS_((void));
334 EXTERN int              expStateAnyIs _ANSI_ARGS_((ExpState *));
335 EXTERN int              expDevttyIs _ANSI_ARGS_((ExpState *));
336 EXTERN int              expStdinoutIs _ANSI_ARGS_((ExpState *));
337 EXTERN ExpState *       expStdinoutGet _ANSI_ARGS_((void));
338 EXTERN ExpState *       expDevttyGet _ANSI_ARGS_((void));
339
340 /* generic functions that really should be provided by Tcl */
341 #if 0 /* Redefined as macros. */
342 EXTERN int              expSizeGet _ANSI_ARGS_((ExpState *));
343 EXTERN int              expSizeZero _ANSI_ARGS_((ExpState *));
344 #else
345 #define expSizeGet(esPtr)  ((esPtr)->input.use)
346 #define expSizeZero(esPtr) (((esPtr)->input.use) == 0)
347 #endif
348
349 #define EXP_CMDINFO_CLOSE  "expect/cmdinfo/close"
350 #define EXP_CMDINFO_RETURN "expect/cmdinfo/return"
351 \f
352 /*
353  * Local Variables:
354  * mode: c
355  * c-basic-offset: 4
356  * fill-column: 78
357  * End:
358  */