OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [expect/] [exp_main_sub.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 markom
/* exp_main_sub.c - miscellaneous subroutines for Expect or Tk main() */
2
 
3
#include "expect_cf.h"
4
#include <stdio.h>
5
#include <errno.h>
6
#ifdef HAVE_INTTYPES_H
7
#  include <inttypes.h>
8
#endif
9
#include <sys/types.h>
10
 
11
#ifdef HAVE_UNISTD_H
12
# include <unistd.h>
13
#endif
14
 
15
#ifdef HAVE_SYS_WAIT_H
16
#include <sys/wait.h>
17
#endif
18
 
19
#include "tcl.h"
20
#include "tclInt.h"
21
#include "exp_rename.h"
22
#include "exp_prog.h"
23
#include "exp_command.h"
24
#include "exp_tty_in.h"
25
#include "exp_log.h"
26
#include "exp_event.h"
27
#ifdef TCL_DEBUGGER
28
#include "Dbg.h"
29
#endif
30
 
31
#ifdef __CENTERLINE__
32
#undef  EXP_VERSION
33
#define EXP_VERSION             "5.0.3"         /* I give up! */
34
                                        /* It is not necessary that number */
35
                                        /* be accurate.  It is just here to */
36
                                        /* pacify Centerline which doesn't */
37
                                        /* seem to be able to get it from */
38
                                        /* the Makefile. */
39
#undef  SCRIPTDIR
40
#define SCRIPTDIR       "example/"
41
#undef  EXECSCRIPTDIR
42
#define EXECSCRIPTDIR   "example/"
43
#endif
44
char exp_version[] = EXP_VERSION;
45
#define NEED_TCL_MAJOR          7
46
#define NEED_TCL_MINOR          5
47
 
48
char *exp_argv0 = "this program";       /* default program name */
49
void (*exp_app_exit)() = 0;
50
void (*exp_event_exit)() = 0;
51
FILE *exp_cmdfile = 0;
52
char *exp_cmdfilename = 0;
53
int exp_cmdlinecmds = FALSE;
54
int exp_interactive =  FALSE;
55
int exp_buffer_command_input = FALSE;/* read in entire cmdfile at once */
56
int exp_fgets();
57
 
58
Tcl_Interp *exp_interp; /* for use by signal handlers who can't figure out */
59
                        /* the interpreter directly */
60
int exp_tcl_debugger_available = FALSE;
61
 
62
int exp_getpid;
63
 
64
static void
65
usage(interp)
66
Tcl_Interp *interp;
67
{
68
        errorlog("usage: expect [-div] [-c cmds] [[-f] cmdfile] [args]\r\n");
69
        exp_exit(interp,1);
70
}
71
 
72
/*ARGSUSED*/
73
void
74
exp_exit(interp,status)
75
Tcl_Interp *interp;     /* historic */
76
int status;
77
{
78
        Tcl_Exit(status);
79
}
80
 
81
/* this clumsiness because pty routines don't know Tcl definitions */
82
static
83
void
84
exp_pty_exit_for_tcl(clientData)
85
ClientData clientData;
86
{
87
        exp_pty_exit();
88
}
89
 
90
static
91
void
92
exp_init_pty_exit()
93
{
94
        Tcl_CreateExitHandler(exp_pty_exit_for_tcl,(ClientData)0);
95
}
96
 
97
/* This can be called twice or even recursively - it's safe. */
98
void
99
exp_exit_handlers(clientData)
100
ClientData clientData;
101
{
102
        extern int exp_forked;
103
 
104
        Tcl_Interp *interp = (Tcl_Interp *)clientData;
105
 
106
        /* use following checks to prevent recursion in exit handlers */
107
        /* if this code ever supports multiple interps, these should */
108
        /* become interp-specific */
109
 
110
        static int did_app_exit = FALSE;
111
        static int did_expect_exit = FALSE;
112
 
113
        /* don't think this code is relevant any longer, but not positive! */
114
        if (!interp) {
115
                /* if no interp handy (i.e., called from interrupt handler) */
116
                /* use last one created - it's a hack but we're exiting */
117
                /* ungracefully to begin with */
118
                interp = exp_interp;
119
        }
120
 
121
        if (!did_expect_exit) {
122
                did_expect_exit = TRUE;
123
                /* called user-defined exit routine if one exists */
124
                if (exp_onexit_action) {
125
                        int result = Tcl_GlobalEval(interp,exp_onexit_action);
126
                        if (result != TCL_OK) Tcl_BackgroundError(interp);
127
                }
128
        } else {
129
                debuglog("onexit handler called recursively - forcing exit\r\n");
130
        }
131
 
132
        if (exp_app_exit) {
133
                if (!did_app_exit) {
134
                        did_app_exit = TRUE;
135
                        (*exp_app_exit)(interp);
136
                } else {
137
                        debuglog("application exit handler called recursively - forcing exit\r\n");
138
                }
139
        }
140
 
141
        if (!exp_disconnected
142
            && !exp_forked
143
            && (exp_dev_tty != -1)
144
            && isatty(exp_dev_tty)
145
            && exp_ioctled_devtty) {
146
                exp_tty_set(interp,&exp_tty_original,exp_dev_tty,0);
147
        }
148
        /* all other files either don't need to be flushed or will be
149
           implicitly closed at exit.  Spawned processes are free to continue
150
           running, however most will shutdown after seeing EOF on stdin.
151
           Some systems also deliver SIGHUP and other sigs to idle processes
152
           which will blow them away if not prepared.
153
        */
154
 
155
        exp_close_all(interp);
156
}
157
 
158
static int
159
history_nextid(interp)
160
Tcl_Interp *interp;
161
{
162
        Interp *iPtr = (Interp *)interp;
163
 
164
#if TCL_MAJOR_VERSION < 8
165
        return iPtr->curEventNum+1;
166
#else
167
        /* unncessarily tricky coding - if nextid isn't defined,
168
           maintain our own static version */
169
 
170
        static int nextid = 0;
171
        char *nextidstr = Tcl_GetVar2(interp,"tcl::history","nextid",0);
172
        if (nextidstr) {
173
                /* intentionally ignore failure */
174
                (void) sscanf(nextidstr,"%d",&nextid);
175
        }
176
        return ++nextid;
177
#endif
178
}
179
 
180
/* this stupidity because Tcl needs commands in writable space */
181
static char prompt1[] = "prompt1";
182
static char prompt2[] = "prompt2";
183
 
184
static char *prompt2_default = "+> ";
185
static char prompt1_default[] = "expect%d.%d> ";
186
 
187
/*ARGSUSED*/
188
int
189
Exp_Prompt1Cmd(clientData, interp, argc, argv)
190
ClientData clientData;
191
Tcl_Interp *interp;
192
int argc;
193
char **argv;
194
{
195
        Interp *iPtr = (Interp *)interp;
196
 
197
        sprintf(interp->result,prompt1_default,
198
                iPtr->numLevels,history_nextid(interp));
199
        return(TCL_OK);
200
}
201
 
202
/*ARGSUSED*/
203
int
204
Exp_Prompt2Cmd(clientData, interp, argc, argv)
205
ClientData clientData;
206
Tcl_Interp *interp;
207
int argc;
208
char **argv;
209
{
210
        strcpy(interp->result,prompt2_default);
211
        return(TCL_OK);
212
}
213
 
214
/*ARGSUSED*/
215
static int
216
ignore_procs(interp,s)
217
Tcl_Interp *interp;
218
char *s;                /* function name */
219
{
220
        return ((s[0] == 'p') &&
221
                (s[1] == 'r') &&
222
                (s[2] == 'o') &&
223
                (s[3] == 'm') &&
224
                (s[4] == 'p') &&
225
                (s[5] == 't') &&
226
                ((s[6] == '1') ||
227
                 (s[6] == '2')) &&
228
                (s[7] == '\0')
229
               );
230
}
231
 
232
/* handle an error from Tcl_Eval or Tcl_EvalFile */
233
static void
234
handle_eval_error(interp,check_for_nostack)
235
Tcl_Interp *interp;
236
int check_for_nostack;
237
{
238
        char *msg;
239
 
240
        /* if errorInfo has something, print it */
241
        /* else use what's in interp->result */
242
 
243
        msg = Tcl_GetVar(interp,"errorInfo",TCL_GLOBAL_ONLY);
244
        if (!msg) msg = interp->result;
245
        else if (check_for_nostack) {
246
                /* suppress errorInfo if generated via */
247
                /* error ... -nostack */
248
                if (0 == strncmp("-nostack",msg,8)) return;
249
 
250
                /*
251
                 * This shouldn't be necessary, but previous test fails
252
                 * because of recent change John made - see eval_trap_action()
253
                 * in exp_trap.c for more info
254
                 */
255
                if (exp_nostack_dump) {
256
                        exp_nostack_dump = FALSE;
257
                        return;
258
                }
259
        }
260
 
261
        /* no \n at end, since ccmd will already have one. */
262
        /* Actually, this is not true if command is last in */
263
        /* file and has no newline after it, oh well */
264
        errorlog("%s\r\n",exp_cook(msg,(int *)0));
265
}
266
 
267
/* user has pressed escape char from interact or somehow requested expect.
268
If a user-supplied command returns:
269
 
270
TCL_ERROR,      assume user is experimenting and reprompt
271
TCL_OK,         ditto
272
TCL_RETURN,     return TCL_OK (assume user just wants to escape() to return)
273
EXP_TCL_RETURN, return TCL_RETURN
274
anything else   return it
275
*/
276
int
277
exp_interpreter(interp)
278
Tcl_Interp *interp;
279
{
280
        int rc;
281
        char *ccmd;             /* pointer to complete command */
282
        char line[BUFSIZ+1];    /* space for partial command */
283
        int newcmd = TRUE;
284
        Tcl_DString dstring;
285
        Interp *iPtr = (Interp *)interp;
286
        int tty_changed = FALSE;
287
 
288
        exp_tty tty_old;
289
        int was_raw, was_echo;
290
 
291
        int dummy;
292
        Tcl_Channel outChannel;
293
        int fd = fileno(stdin);
294
 
295
        expect_key++;
296
 
297
        Tcl_DStringInit(&dstring);
298
 
299
        newcmd = TRUE;
300
        while (TRUE) {
301
                outChannel = Tcl_GetStdChannel(TCL_STDOUT);
302
                if (outChannel) {
303
                        Tcl_Flush(outChannel);
304
                }
305
 
306
                /* force terminal state */
307
                tty_changed = exp_tty_cooked_echo(interp,&tty_old,&was_raw,&was_echo);
308
 
309
                if (newcmd) {
310
                        rc = Tcl_Eval(interp,prompt1);
311
                        if (rc == TCL_OK) exp_log(1,"%s",interp->result);
312
                        else exp_log(1,prompt1_default,iPtr->numLevels,
313
                                     history_nextid(interp));
314
                } else {
315
                        rc = Tcl_Eval(interp,prompt2);
316
                        if (rc == TCL_OK) exp_log(1,"%s",interp->result);
317
                        else exp_log(1,prompt2_default,1);
318
                }
319
 
320
                exp_fs[fd].force_read = 1;
321
                rc = exp_get_next_event(interp,&fd,1,&dummy,EXP_TIME_INFINITY,
322
                        exp_fs[fd].key);
323
                /*  check for rc == EXP_TCLERROR? */
324
 
325
                if (rc != EXP_EOF) {
326
                        rc = read(0,line,BUFSIZ);
327
#ifdef SIMPLE_EVENT
328
                        if (rc == -1 && errno == EINTR) {
329
                                if (Tcl_AsyncReady()) {
330
                                        (void) Tcl_AsyncInvoke(interp,TCL_OK);
331
                                }
332
                                continue;
333
                        }
334
#endif
335
                        if (rc <= 0) {
336
                                if (!newcmd) line[0] = 0;
337
                                else rc = EXP_EOF;
338
                        } else line[rc] = '\0';
339
                }
340
 
341
                if (rc == EXP_EOF) exp_exit(interp,0);
342
 
343
                if (debugfile) fwrite(line,1,strlen(line),debugfile);
344
                /* intentionally always write to logfile */
345
                if (logfile) fwrite(line,1,strlen(line),logfile);
346
                /* no need to write to stdout, since they will see */
347
                /* it just from it having been echoed as they are */
348
                /* typing it */
349
 
350
                ccmd = Tcl_DStringAppend(&dstring,line,rc);
351
                if (!Tcl_CommandComplete(ccmd)) {
352
                        newcmd = FALSE;
353
                        continue;       /* continue collecting command */
354
                }
355
                newcmd = TRUE;
356
 
357
                if (tty_changed) exp_tty_set(interp,&tty_old,was_raw,was_echo);
358
 
359
                rc = Tcl_RecordAndEval(interp,ccmd,0);
360
                Tcl_DStringFree(&dstring);
361
                switch (rc) {
362
                case TCL_OK:
363
                        if (*interp->result != 0)
364
                                exp_log(1,"%s\r\n",exp_cook(interp->result,(int *)0));
365
                        continue;
366
                case TCL_ERROR:
367
                        handle_eval_error(interp,1);
368
                        /* since user is typing by hand, we expect lots */
369
                        /* of errors, and want to give another chance */
370
                        continue;
371
#define finish(x)       {rc = x; goto done;}
372
                case TCL_BREAK:
373
                case TCL_CONTINUE:
374
                        finish(rc);
375
                case EXP_TCL_RETURN:
376
                        finish(TCL_RETURN);
377
                case TCL_RETURN:
378
                        finish(TCL_OK);
379
                default:
380
                        /* note that ccmd has trailing newline */
381
                        errorlog("error %d: %s\r\n",rc,ccmd);
382
                        continue;
383
                }
384
        }
385
        /* cannot fall thru here, must jump to label */
386
 done:
387
        if (tty_changed) exp_tty_set(interp,&tty_old,was_raw,was_echo);
388
 
389
        Tcl_DStringFree(&dstring);
390
 
391
        return(rc);
392
}
393
 
394
/*ARGSUSED*/
395
int
396
Exp_ExpVersionCmd(clientData, interp, argc, argv)
397
ClientData clientData;
398
Tcl_Interp *interp;
399
int argc;
400
char **argv;
401
{
402
        int emajor, umajor;
403
        char *user_version;     /* user-supplied version string */
404
 
405
        if (argc == 1) {
406
                Tcl_SetResult(interp,exp_version,TCL_STATIC);
407
                return(TCL_OK);
408
        }
409
        if (argc > 3) {
410
                exp_error(interp,"usage: expect_version [[-exit] version]");
411
                return(TCL_ERROR);
412
        }
413
 
414
        user_version = argv[argc==2?1:2];
415
        emajor = atoi(exp_version);
416
        umajor = atoi(user_version);
417
 
418
        /* first check major numbers */
419
        if (emajor == umajor) {
420
                int u, e;
421
 
422
                /* now check minor numbers */
423
                char *dot = strchr(user_version,'.');
424
                if (!dot) {
425
                        exp_error(interp,"version number must include a minor version number");
426
                        return TCL_ERROR;
427
                }
428
 
429
                u = atoi(dot+1);
430
                dot = strchr(exp_version,'.');
431
                e = atoi(dot+1);
432
                if (e >= u) return(TCL_OK);
433
        }
434
 
435
        if (argc == 2) {
436
                exp_error(interp,"%s requires Expect version %s (but using %s)",
437
                        exp_argv0,user_version,exp_version);
438
                return(TCL_ERROR);
439
        }
440
        errorlog("%s: requires Expect version %s (but using %s)\r\n",
441
                exp_argv0,user_version,exp_version);
442
        exp_exit(interp,1);
443
        /*NOTREACHED*/
444
}
445
 
446
static char init_auto_path[] = "lappend auto_path $exp_library $exp_exec_library";
447
 
448
int
449
Expect_Init(interp)
450
Tcl_Interp *interp;
451
{
452
        static int first_time = TRUE;
453
 
454
        if (first_time) {
455
                int tcl_major = atoi(TCL_VERSION);
456
                char *dot = strchr(TCL_VERSION,'.');
457
                int tcl_minor = atoi(dot+1);
458
 
459
                if (tcl_major < NEED_TCL_MAJOR ||
460
                    (tcl_major == NEED_TCL_MAJOR && tcl_minor < NEED_TCL_MINOR)) {
461
                        sprintf(interp->result,
462
                           "%s compiled with Tcl %d.%d but needs at least Tcl %d.%d\n",
463
                                exp_argv0,tcl_major,tcl_minor,
464
                                NEED_TCL_MAJOR,NEED_TCL_MINOR);
465
                        return TCL_ERROR;
466
                }
467
 
468
                if (Tcl_PkgRequire(interp, "Tcl", TCL_VERSION, 0) == NULL) {
469
                        return TCL_ERROR;
470
                }
471
                if (Tcl_PkgProvide(interp, "Expect", EXP_VERSION) != TCL_OK) {
472
                        return TCL_ERROR;
473
                }
474
 
475
                exp_getpid = getpid();
476
                exp_init_pty();
477
                exp_init_pty_exit();
478
                exp_init_tty(); /* do this only now that we have looked at */
479
                                /* original tty state */
480
                exp_init_stdio();
481
                exp_init_sig();
482
                exp_init_event();
483
                exp_init_trap();
484
                exp_init_unit_random();
485
                exp_init_spawn_ids();
486
 
487
                Tcl_CreateExitHandler(exp_exit_handlers,(ClientData)interp);
488
 
489
                first_time = FALSE;
490
        }
491
 
492
        /* save last known interp for emergencies */
493
        exp_interp = interp;
494
 
495
        /* initialize commands */
496
        exp_init_most_cmds(interp);     /* add misc     cmds to interpreter */
497
        exp_init_expect_cmds(interp);   /* add expect   cmds to interpreter */
498
        exp_init_main_cmds(interp);     /* add main     cmds to interpreter */
499
        exp_init_trap_cmds(interp);     /* add trap     cmds to interpreter */
500
        exp_init_tty_cmds(interp);      /* add tty      cmds to interpreter */
501
        exp_init_interact_cmds(interp); /* add interact cmds to interpreter */
502
 
503
        exp_init_spawn_id_vars(interp);
504
 
505
        Tcl_SetVar(interp,"expect_library",SCRIPTDIR,0);/* deprecated */
506
        Tcl_SetVar(interp,"exp_library",SCRIPTDIR,0);
507
        Tcl_SetVar(interp,"exp_exec_library",EXECSCRIPTDIR,0);
508
        Tcl_Eval(interp,init_auto_path);
509
        Tcl_ResetResult(interp);
510
 
511
#ifdef TCL_DEBUGGER
512
        Dbg_IgnoreFuncs(interp,ignore_procs);
513
#endif
514
 
515
        return TCL_OK;
516
}
517
 
518
static char sigexit_init_default[] = "trap exit {SIGINT SIGTERM}";
519
static char debug_init_default[] = "trap {exp_debug 1} SIGINT";
520
 
521
void
522
exp_parse_argv(interp,argc,argv)
523
Tcl_Interp *interp;
524
int argc;
525
char **argv;
526
{
527
        char argc_rep[10]; /* enough space for storing literal rep of argc */
528
 
529
        int sys_rc = TRUE;      /* read system rc file */
530
        int my_rc = TRUE;       /* read personal rc file */
531
 
532
        int c;
533
        int rc;
534
 
535
        extern int optind;
536
        extern char *optarg;
537
        char *args;             /* ptr to string-rep of all args */
538
        char *debug_init;
539
 
540
        exp_argv0 = argv[0];
541
 
542
#ifdef TCL_DEBUGGER
543
        Dbg_ArgcArgv(argc,argv,1);
544
#endif
545
 
546
        /* initially, we must assume we are not interactive */
547
        /* this prevents interactive weirdness courtesy of unknown via -c */
548
        /* after handling args, we can change our mind */
549
        Tcl_SetVar(interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
550
 
551
        Tcl_Eval(interp,sigexit_init_default);
552
 
553
        while ((c = getopt(argc, argv, "b:c:dD:f:inN-v")) != EOF) {
554
                switch(c) {
555
                case '-':
556
                        /* getopt already handles -- internally, however */
557
                        /* this allows us to abort getopt when dash is at */
558
                        /* the end of another option which is required */
559
                        /* in order to allow things like -n- on #! line */
560
                        goto abort_getopt;
561
                case 'c': /* command */
562
                        exp_cmdlinecmds = TRUE;
563
                        rc = Tcl_Eval(interp,optarg);
564
                        if (rc != TCL_OK) {
565
                            errorlog("%s\r\n",exp_cook(Tcl_GetVar(interp,"errorInfo",TCL_GLOBAL_ONLY),(int *)0));
566
                        }
567
                        break;
568
                case 'd': exp_is_debugging = TRUE;
569
                        debuglog("expect version %s\r\n",exp_version);
570
                        break;
571
#ifdef TCL_DEBUGGER
572
                case 'D':
573
                        exp_tcl_debugger_available = TRUE;
574
                        if (Tcl_GetInt(interp,optarg,&rc) != TCL_OK) {
575
                                errorlog("%s: -D argument must be 0 or 1\r\n",
576
                                        exp_argv0);
577
                                exp_exit(interp,1);
578
                        }
579
 
580
                        /* set up trap handler before Dbg_On so user does */
581
                        /* not have to see it at first debugger prompt */
582
                        if (0 == (debug_init = getenv("EXPECT_DEBUG_INIT"))) {
583
                                debug_init = debug_init_default;
584
                        }
585
                        Tcl_Eval(interp,debug_init);
586
                        if (rc == 1) Dbg_On(interp,0);
587
                        break;
588
#endif
589
                case 'f': /* name of cmd file */
590
                        exp_cmdfilename = optarg;
591
                        break;
592
                case 'b': /* read cmdfile one part at a time */
593
                        exp_cmdfilename = optarg;
594
                        exp_buffer_command_input = TRUE;
595
                        break;
596
                case 'i': /* interactive */
597
                        exp_interactive = TRUE;
598
                        break;
599
                case 'n': /* don't read personal rc file */
600
                        my_rc = FALSE;
601
                        break;
602
                case 'N': /* don't read system-wide rc file */
603
                        sys_rc = FALSE;
604
                        break;
605
                case 'v':
606
                        printf("expect version %s\n", exp_version);
607
                        exp_exit (interp, 0);
608
                        break;
609
                default: usage(interp);
610
                }
611
        }
612
 
613
 abort_getopt:
614
 
615
        for (c = 0;c<argc;c++) {
616
                debuglog("argv[%d] = %s  ",c,argv[c]);
617
        }
618
        debuglog("\r\n");
619
 
620
        /* if user hasn't explicitly requested we be interactive */
621
        /* look for a file or some other source of commands */
622
        if (!exp_interactive) {
623
                /* get cmd file name, if we haven't got it already */
624
                if (!exp_cmdfilename && (optind < argc)) {
625
                        exp_cmdfilename = argv[optind];
626
                        optind++;
627
                }
628
 
629
                if (exp_cmdfilename) {
630
                        if (streq(exp_cmdfilename,"-")) {
631
                                exp_cmdfile = stdin;
632
                                exp_cmdfilename = 0;
633
                        } else if (exp_buffer_command_input) {
634
                                errno = 0;
635
                                exp_cmdfile = fopen(exp_cmdfilename,"r");
636
                                if (exp_cmdfile) {
637
                                        exp_cmdfilename = 0;
638
                                        exp_close_on_exec(fileno(exp_cmdfile));
639
                                } else {
640
                                        char *msg;
641
 
642
                                        if (errno == 0) {
643
                                                msg = "could not read - odd file name?";
644
                                        } else {
645
                                                msg = Tcl_ErrnoMsg(errno);
646
                                        }
647
                                        errorlog("%s: %s\r\n",exp_cmdfilename,msg);
648
                                        exp_exit(interp,1);
649
                                }
650
                        }
651
                } else if (!exp_cmdlinecmds) {
652
                        if (isatty(0)) {
653
                                /* no other source of commands, force interactive */
654
                                exp_interactive = TRUE;
655
                        } else {
656
                                /* read cmds from redirected stdin */
657
                                exp_cmdfile = stdin;
658
                        }
659
                }
660
        }
661
 
662
        if (exp_interactive) {
663
                Tcl_SetVar(interp, "tcl_interactive","1",TCL_GLOBAL_ONLY);
664
        }
665
 
666
        /* collect remaining args and make into argc, argv0, and argv */
667
        sprintf(argc_rep,"%d",argc-optind);
668
        Tcl_SetVar(interp,"argc",argc_rep,0);
669
        debuglog("set argc %s\r\n",argc_rep);
670
 
671
        if (exp_cmdfilename) {
672
                Tcl_SetVar(interp,"argv0",exp_cmdfilename,0);
673
                debuglog("set argv0 \"%s\"\r\n",exp_cmdfilename);
674
        } else {
675
                Tcl_SetVar(interp,"argv0",exp_argv0,0);
676
                debuglog("set argv0 \"%s\"\r\n",exp_argv0);
677
        }
678
 
679
        args = Tcl_Merge(argc-optind,argv+optind);
680
        debuglog("set argv \"%s\"\r\n",args);
681
        Tcl_SetVar(interp,"argv",args,0);
682
        ckfree(args);
683
 
684
        exp_interpret_rcfiles(interp,my_rc,sys_rc);
685
}
686
 
687
/* read rc files */
688
void
689
exp_interpret_rcfiles(interp,my_rc,sys_rc)
690
Tcl_Interp *interp;
691
int my_rc;
692
int sys_rc;
693
{
694
        int rc;
695
 
696
        if (sys_rc) {
697
            char file[200];
698
            int fd;
699
 
700
            sprintf(file,"%s/expect.rc",SCRIPTDIR);
701
            if (-1 != (fd = open(file,0))) {
702
                if (TCL_ERROR == (rc = Tcl_EvalFile(interp,file))) {
703
                    errorlog("error executing system initialization file: %s\r\n",file);
704
                    if (rc != TCL_ERROR)
705
                                errorlog("Tcl_Eval = %d\r\n",rc);
706
                    if (*interp->result != 0)
707
                                errorlog("%s\r\n",interp->result);
708
                    exp_exit(interp,1);
709
                }
710
                close(fd);
711
            }
712
        }
713
        if (my_rc) {
714
            char file[200];
715
            char *home;
716
            int fd;
717
            char *getenv();
718
 
719
            if ((NULL != (home = getenv("DOTDIR"))) ||
720
                (NULL != (home = getenv("HOME")))) {
721
                sprintf(file,"%s/.expect.rc",home);
722
                if (-1 != (fd = open(file,0))) {
723
                    if (TCL_ERROR == (rc = Tcl_EvalFile(interp,file))) {
724
                        errorlog("error executing file: %s\r\n",file);
725
                        if (rc != TCL_ERROR)
726
                                errorlog("Tcl_Eval = %d\r\n",rc);
727
                        if (*interp->result != 0)
728
                                errorlog("%s\r\n",interp->result);
729
                        exp_exit(interp,1);
730
                    }
731
                    close(fd);
732
                }
733
            }
734
        }
735
}
736
 
737
int
738
exp_interpret_cmdfilename(interp,filename)
739
Tcl_Interp *interp;
740
char *filename;
741
{
742
        int rc;
743
 
744
        debuglog("executing commands from command file %s\r\n",filename);
745
 
746
        Tcl_ResetResult(interp);
747
        if (TCL_OK != (rc = Tcl_EvalFile(interp,filename))) {
748
                /* EvalFile doesn't bother to copy error to errorInfo */
749
                /* so force it */
750
                Tcl_AddErrorInfo(interp, "");
751
                handle_eval_error(interp,0);
752
        }
753
        return rc;
754
}
755
 
756
int
757
exp_interpret_cmdfile(interp,fp)
758
Tcl_Interp *interp;
759
FILE *fp;
760
{
761
        int rc = 0;
762
        int newcmd;
763
        int eof;
764
 
765
        Tcl_DString dstring;
766
        Tcl_DStringInit(&dstring);
767
 
768
        debuglog("executing commands from command file\r\n");
769
 
770
        newcmd = TRUE;
771
        eof = FALSE;
772
        while (1) {
773
                char line[BUFSIZ];/* buffer for partial Tcl command */
774
                char *ccmd;     /* pointer to complete Tcl command */
775
 
776
                if (fgets(line,BUFSIZ,fp) == NULL) {
777
                        if (newcmd) break;
778
                        eof = TRUE;
779
                }
780
                ccmd = Tcl_DStringAppend(&dstring,line,-1);
781
                if (!Tcl_CommandComplete(ccmd) && !eof) {
782
                        newcmd = FALSE;
783
                        continue;       /* continue collecting command */
784
                }
785
                newcmd = TRUE;
786
 
787
                rc = Tcl_Eval(interp,ccmd);
788
                Tcl_DStringFree(&dstring);
789
                if (rc != TCL_OK) {
790
                        handle_eval_error(interp,0);
791
                        break;
792
                }
793
                if (eof) break;
794
        }
795
        Tcl_DStringFree(&dstring);
796
        return rc;
797
}
798
 
799
#ifdef SHARE_CMD_BUFFER
800
/* fgets that shared input buffer with expect_user */
801
int
802
exp_fgets(interp,buf,max)
803
Tcl_Interp *interp;
804
char *buf;
805
int max;
806
{
807
        char *nl;       /* position of newline which signifies end of line */
808
        int write_count;/* length of first line of incoming data */
809
 
810
        int m = fileno(stdin);
811
        struct exp_f *f;
812
        int cc;
813
 
814
        int dummy;
815
 
816
        /* avoid returning no data, just because someone else read it in by */
817
        /* passing most recent key */
818
        cc = exp_get_next_event(interp,&m,1,&dummy,EXP_TIME_INFINITY,exp_fs[m].key);
819
 
820
        if (cc == EXP_DATA_NEW) {
821
                /* try to read it */
822
 
823
                cc = exp_i_read(m,EXP_TIME_INFINITY);
824
 
825
                /* the meaning of 0 from i_read means eof.  Muck with it a */
826
                /* little, so that from now on it means "no new data arrived */
827
                /* but it should be looked at again anyway". */
828
                if (cc == 0) {
829
                        cc = EXP_EOF;
830
                } else if (cc > 0) {
831
                        f = exp_fs + m;
832
                        f->buffer[f->size += cc] = '\0';
833
                }
834
        } else if (cc == EXP_DATA_OLD) {
835
                f = exp_fs + m;
836
                cc = 0;
837
        }
838
 
839
        /* EOF and TIMEOUT return here */
840
        /* In such cases, there is no need to update screen since, if there */
841
        /* was prior data read, it would have been sent to the screen when */
842
        /* it was read. */
843
        if (cc < 0) return (cc);
844
 
845
        /* copy up to end of first line */
846
 
847
        /* calculate end of first line */
848
        nl = strchr(f->buffer,'\n');
849
        if (nl) write_count = 1+nl-f->buffer;
850
        else write_count = f->size;
851
 
852
        /* make sure line fits in buffer area */
853
        if (write_count > max) write_count = max;
854
 
855
        /* copy it */
856
        memcpy(buf,f->buffer,write_count);
857
        buf[write_count] = '\0';
858
 
859
        /* update display and f */
860
 
861
        f->printed = 0;
862
        /* for simplicity force f->printed = 0.  This way, the user gets */
863
        /* to see the commands that are about to be executed.  Not seeing */
864
        /* commands you are supposedly typing sounds very uncomfortable! */
865
 
866
        if (logfile_all || (loguser && logfile)) {
867
                fwrite(f->buffer,1,write_count,logfile);
868
        }
869
        if (debugfile) fwrite(f->buffer,1,write_count,debugfile);
870
 
871
        f->size -= write_count;
872
        memcpy(f->buffer,f->buffer+write_count,1+f->size);
873
        /* copy to lowercase buffer */
874
        exp_lowmemcpy(f->lower,f->buffer,1+f->size);
875
 
876
        return(write_count);
877
}
878
#endif /*SHARE_CMD_BUFFER*/
879
 
880
static struct exp_cmd_data cmd_data[]  = {
881
{"expect_version",exp_proc(Exp_ExpVersionCmd),  0,       0},      /* deprecated */
882
{"exp_version", exp_proc(Exp_ExpVersionCmd),    0,       0},
883
{"prompt1",     exp_proc(Exp_Prompt1Cmd),               0,       EXP_NOPREFIX},
884
{"prompt2",     exp_proc(Exp_Prompt2Cmd),               0,       EXP_NOPREFIX},
885
{0}};
886
 
887
void
888
exp_init_main_cmds(interp)
889
Tcl_Interp *interp;
890
{
891
        exp_create_commands(interp,cmd_data);
892
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.