|
1 //init.c - main loop and initialization routines |
|
2 // |
|
3 // © Portions Copyright (c) Symbian Software Ltd 2007-2008. All rights reserved. |
|
4 // |
|
5 /* |
|
6 * This file is part of zsh, the Z shell. |
|
7 * |
|
8 * Copyright (c) 1992-1997 Paul Falstad |
|
9 * All rights reserved. |
|
10 * |
|
11 * Permission is hereby granted, without written agreement and without |
|
12 * license or royalty fees, to use, copy, modify, and distribute this |
|
13 * software and to distribute modified versions of this software for any |
|
14 * purpose, provided that the above copyright notice and the following |
|
15 * two paragraphs appear in all copies of this software. |
|
16 * |
|
17 * In no event shall Paul Falstad or the Zsh Development Group be liable |
|
18 * to any party for direct, indirect, special, incidental, or consequential |
|
19 * damages arising out of the use of this software and its documentation, |
|
20 * even if Paul Falstad and the Zsh Development Group have been advised of |
|
21 * the possibility of such damage. |
|
22 * |
|
23 * Paul Falstad and the Zsh Development Group specifically disclaim any |
|
24 * warranties, including, but not limited to, the implied warranties of |
|
25 * merchantability and fitness for a particular purpose. The software |
|
26 * provided hereunder is on an "as is" basis, and Paul Falstad and the |
|
27 * Zsh Development Group have no obligation to provide maintenance, |
|
28 * support, updates, enhancements, or modifications. |
|
29 * |
|
30 */ |
|
31 #include "zsh.mdh" |
|
32 |
|
33 #include "zshpaths.h" |
|
34 #include "zshxmods.h" |
|
35 |
|
36 #include "init.pro" |
|
37 |
|
38 #include "version.h" |
|
39 |
|
40 #ifdef __SYMBIAN32__ |
|
41 #ifdef __WINSCW__ |
|
42 #pragma warn_unusedarg off |
|
43 #pragma warn_possunwant off |
|
44 #endif//__WINSCW__ |
|
45 #endif//__SYMBIAN32__ |
|
46 |
|
47 #ifdef __SYMBIAN32__ |
|
48 #include "dummy.h" |
|
49 char getSystemDriveChar(void); |
|
50 #endif //__SYMBIAN32__ |
|
51 |
|
52 /**/ |
|
53 int noexitct = 0; |
|
54 |
|
55 int pipeUsed; |
|
56 /* buffer for $_ and its length */ |
|
57 |
|
58 /**/ |
|
59 char *underscore; |
|
60 |
|
61 /**/ |
|
62 int underscorelen, underscoreused; |
|
63 |
|
64 /* what level of sourcing we are at */ |
|
65 |
|
66 /**/ |
|
67 int sourcelevel; |
|
68 |
|
69 /* the shell tty fd */ |
|
70 |
|
71 /**/ |
|
72 mod_export int SHTTY; |
|
73 |
|
74 /* the FILE attached to the shell tty */ |
|
75 |
|
76 /**/ |
|
77 mod_export FILE *shout; |
|
78 |
|
79 /* termcap strings */ |
|
80 |
|
81 /**/ |
|
82 mod_export char *tcstr[TC_COUNT]; |
|
83 |
|
84 /* lengths of each termcap string */ |
|
85 |
|
86 /**/ |
|
87 mod_export int tclen[TC_COUNT]; |
|
88 |
|
89 /* Values of the li, co and am entries */ |
|
90 |
|
91 /**/ |
|
92 int tclines, tccolumns; |
|
93 /**/ |
|
94 mod_export int hasam; |
|
95 |
|
96 /* Pointer to read-key function from zle */ |
|
97 |
|
98 /**/ |
|
99 mod_export int (*getkeyptr) _((int)); |
|
100 |
|
101 /* SIGCHLD mask */ |
|
102 |
|
103 /**/ |
|
104 mod_export sigset_t sigchld_mask; |
|
105 |
|
106 /**/ |
|
107 mod_export struct hookdef zshhooks[] = { |
|
108 HOOKDEF("exit", NULL, HOOKF_ALL), |
|
109 HOOKDEF("before_trap", NULL, HOOKF_ALL), |
|
110 HOOKDEF("after_trap", NULL, HOOKF_ALL), |
|
111 }; |
|
112 |
|
113 /* keep executing lists until EOF found */ |
|
114 |
|
115 /**/ |
|
116 void |
|
117 loop(int toplevel, int justonce) |
|
118 { |
|
119 Eprog prog; |
|
120 |
|
121 pushheap(); |
|
122 for (;;) { |
|
123 freeheap(); |
|
124 if (stophist == 3) /* re-entry via preprompt() */ |
|
125 hend(NULL); |
|
126 hbegin(1); /* init history mech */ |
|
127 if (isset(SHINSTDIN)) { |
|
128 setblock_stdin(); |
|
129 if (interact) { |
|
130 int hstop = stophist; |
|
131 stophist = 3; |
|
132 preprompt(); |
|
133 if (stophist != 3) |
|
134 hbegin(1); |
|
135 else |
|
136 stophist = hstop; |
|
137 errflag = 0; |
|
138 } |
|
139 } |
|
140 intr(); /* interrupts on */ |
|
141 lexinit(); /* initialize lexical state */ |
|
142 if (!(prog = parse_event())) { /* if we couldn't parse a list */ |
|
143 hend(NULL); |
|
144 if ((tok == ENDINPUT && !errflag) || |
|
145 (tok == LEXERR && (!isset(SHINSTDIN) || !toplevel)) || |
|
146 justonce) |
|
147 break; |
|
148 if (tok == LEXERR && !lastval) |
|
149 lastval = 1; |
|
150 continue; |
|
151 } |
|
152 if (hend(prog)) { |
|
153 int toksav = tok; |
|
154 Eprog preprog; |
|
155 |
|
156 if (toplevel && (preprog = getshfunc("preexec")) != &dummy_eprog) { |
|
157 LinkList args; |
|
158 int osc = sfcontext; |
|
159 char *cmdstr; |
|
160 |
|
161 args = znewlinklist(); |
|
162 zaddlinknode(args, "preexec"); |
|
163 /* If curline got dumped from the history, we don't know |
|
164 * what the user typed. */ |
|
165 if (hist_ring && curline.histnum == curhist) |
|
166 zaddlinknode(args, hist_ring->text); |
|
167 else |
|
168 zaddlinknode(args, ""); |
|
169 zaddlinknode(args, getjobtext(prog, NULL)); |
|
170 zaddlinknode(args, cmdstr = getpermtext(prog, NULL)); |
|
171 |
|
172 sfcontext = SFC_HOOK; |
|
173 doshfunc("preexec", preprog, args, 0, 1); |
|
174 sfcontext = osc; |
|
175 zsfree(cmdstr); |
|
176 freelinklist(args, (FreeFunc) NULL); |
|
177 errflag = 0; |
|
178 } |
|
179 if (stopmsg) /* unset 'you have stopped jobs' flag */ |
|
180 stopmsg--; |
|
181 execode(prog, 0, 0); |
|
182 tok = toksav; |
|
183 if (toplevel) |
|
184 noexitct = 0; |
|
185 } |
|
186 if (ferror(stderr)) { |
|
187 zerr("write error", NULL, 0); |
|
188 clearerr(stderr); |
|
189 } |
|
190 if (subsh) /* how'd we get this far in a subshell? */ |
|
191 exit(lastval); |
|
192 if (((!interact || sourcelevel) && errflag) || retflag) |
|
193 break; |
|
194 if (trapreturn) { |
|
195 lastval = trapreturn; |
|
196 trapreturn = 0; |
|
197 } |
|
198 if (isset(SINGLECOMMAND) && toplevel) { |
|
199 if (sigtrapped[SIGEXIT]) |
|
200 dotrap(SIGEXIT); |
|
201 exit(lastval); |
|
202 } |
|
203 if (justonce) |
|
204 break; |
|
205 } |
|
206 popheap(); |
|
207 } |
|
208 |
|
209 static char *cmd; |
|
210 static int restricted; |
|
211 |
|
212 /**/ |
|
213 void |
|
214 parseargs(char **argv) |
|
215 { |
|
216 int optionbreak = 0; |
|
217 char **x; |
|
218 int action, optno; |
|
219 LinkList paramlist; |
|
220 |
|
221 argzero = *argv++; |
|
222 SHIN = 0; |
|
223 |
|
224 /* There's a bit of trickery with opts[INTERACTIVE] here. It starts * |
|
225 * at a value of 2 (instead of 1) or 0. If it is explicitly set on * |
|
226 * the command line, it goes to 1 or 0. If input is coming from * |
|
227 * somewhere that normally makes the shell non-interactive, we do * |
|
228 * "opts[INTERACTIVE] &= 1", so that only a *default* on state will * |
|
229 * be changed. At the end of the function, a value of 2 gets * |
|
230 * changed to 1. */ |
|
231 |
|
232 #ifdef __SYMBIAN32__ |
|
233 opts[INTERACTIVE] = 2; /*consider pipe end also as interative*/ |
|
234 #else |
|
235 opts[INTERACTIVE] = isatty(0) ? 2 : 0; |
|
236 #endif |
|
237 |
|
238 opts[SHINSTDIN] = 0; |
|
239 opts[SINGLECOMMAND] = 0; |
|
240 |
|
241 /* loop through command line options (begins with "-" or "+") */ |
|
242 while (!optionbreak && *argv && (**argv == '-' || **argv == '+')) { |
|
243 char *args = *argv; |
|
244 action = (**argv == '-'); |
|
245 if (!argv[0][1]) |
|
246 *argv = "--"; |
|
247 while (*++*argv) { |
|
248 if (**argv == '-') { |
|
249 if(!argv[0][1]) { |
|
250 /* The pseudo-option `--' signifies the end of options. */ |
|
251 argv++; |
|
252 goto doneoptions; |
|
253 } |
|
254 if(*argv != args+1 || **argv != '-') |
|
255 goto badoptionstring; |
|
256 /* GNU-style long options */ |
|
257 ++*argv; |
|
258 if (!strcmp(*argv, "version")) { |
|
259 printf("zsh %s (%s-%s-%s)\n", |
|
260 ZSH_VERSION, MACHTYPE, VENDOR, OSTYPE); |
|
261 exit(0); |
|
262 } |
|
263 if (!strcmp(*argv, "help")) { |
|
264 printhelp(); |
|
265 exit(0); |
|
266 } |
|
267 /* `-' characters are allowed in long options */ |
|
268 for(args = *argv; *args; args++) |
|
269 if(*args == '-') |
|
270 *args = '_'; |
|
271 goto longoptions; |
|
272 } |
|
273 |
|
274 if (unset(SHOPTIONLETTERS) && **argv == 'b') { |
|
275 /* -b ends options at the end of this argument */ |
|
276 optionbreak = 1; |
|
277 } else if (**argv == 'c') { |
|
278 /* -c command */ |
|
279 cmd = *argv; |
|
280 opts[INTERACTIVE] &= 1; |
|
281 opts[SHINSTDIN] = 0; |
|
282 scriptname = ztrdup("zsh"); |
|
283 } else if (**argv == 'o') { |
|
284 if (!*++*argv) |
|
285 argv++; |
|
286 if (!*argv) { |
|
287 zerr("string expected after -o", NULL, 0); |
|
288 exit(1); |
|
289 } |
|
290 longoptions: |
|
291 if (!(optno = optlookup(*argv))) { |
|
292 zerr("no such option: %s", *argv, 0); |
|
293 exit(1); |
|
294 } else if (optno == RESTRICTED) |
|
295 restricted = action; |
|
296 else |
|
297 dosetopt(optno, action, 1); |
|
298 break; |
|
299 } else if (isspace(STOUC(**argv))) { |
|
300 /* zsh's typtab not yet set, have to use ctype */ |
|
301 while (*++*argv) |
|
302 if (!isspace(STOUC(**argv))) { |
|
303 badoptionstring: |
|
304 zerr("bad option string: `%s'", args, 0); |
|
305 exit(1); |
|
306 } |
|
307 break; |
|
308 } else { |
|
309 if (!(optno = optlookupc(**argv))) { |
|
310 zerr("bad option: -%c", NULL, **argv); |
|
311 exit(1); |
|
312 } else if (optno == RESTRICTED) |
|
313 restricted = action; |
|
314 else |
|
315 dosetopt(optno, action, 1); |
|
316 } |
|
317 } |
|
318 argv++; |
|
319 } |
|
320 doneoptions: |
|
321 paramlist = znewlinklist(); |
|
322 if (cmd) { |
|
323 if (!*argv) { |
|
324 zerr("string expected after -%s", cmd, 0); |
|
325 exit(1); |
|
326 } |
|
327 cmd = *argv++; |
|
328 } |
|
329 if (*argv) { |
|
330 if (unset(SHINSTDIN)) { |
|
331 argzero = *argv; |
|
332 if (!cmd) |
|
333 SHIN = movefd(open(unmeta(argzero), O_RDONLY | O_NOCTTY)); |
|
334 if (SHIN == -1) { |
|
335 zerr("can't open input file: %s", argzero, 0); |
|
336 exit(1); |
|
337 } |
|
338 opts[INTERACTIVE] &= 1; |
|
339 argv++; |
|
340 } |
|
341 while (*argv) |
|
342 zaddlinknode(paramlist, ztrdup(*argv++)); |
|
343 } else |
|
344 opts[SHINSTDIN] = 1; |
|
345 if(isset(SINGLECOMMAND)) |
|
346 opts[INTERACTIVE] &= 1; |
|
347 opts[INTERACTIVE] = !!opts[INTERACTIVE]; |
|
348 pparams = x = (char **) zshcalloc((countlinknodes(paramlist) + 1) * sizeof(char *)); |
|
349 |
|
350 while ((*x++ = (char *)getlinknode(paramlist))); |
|
351 free(paramlist); |
|
352 argzero = ztrdup(argzero); |
|
353 } |
|
354 |
|
355 /**/ |
|
356 static void |
|
357 printhelp(void) |
|
358 { |
|
359 printf("Usage: %s [<options>] [<argument> ...]\n", argzero); |
|
360 printf("\nSpecial options:\n"); |
|
361 printf(" --help show this message, then exit\n"); |
|
362 printf(" --version show zsh version number, then exit\n"); |
|
363 if(unset(SHOPTIONLETTERS)) |
|
364 printf(" -b end option processing, like --\n"); |
|
365 printf(" -c take first argument as a command to execute\n"); |
|
366 printf(" -o OPTION set an option by name (see below)\n"); |
|
367 printf("\nNormal options are named. An option may be turned on by\n"); |
|
368 printf("`-o OPTION', `--OPTION', `+o no_OPTION' or `+-no-OPTION'. An\n"); |
|
369 printf("option may be turned off by `-o no_OPTION', `--no-OPTION',\n"); |
|
370 printf("`+o OPTION' or `+-OPTION'. Options are listed below only in\n"); |
|
371 printf("`--OPTION' or `--no-OPTION' form.\n"); |
|
372 printoptionlist(); |
|
373 } |
|
374 |
|
375 /**/ |
|
376 mod_export void |
|
377 init_io(void) |
|
378 { |
|
379 static char outbuf[BUFSIZ], errbuf[BUFSIZ]; |
|
380 |
|
381 #ifdef RSH_BUG_WORKAROUND |
|
382 int i; |
|
383 #endif |
|
384 |
|
385 /* stdout, stderr fully buffered */ |
|
386 #ifdef _IOFBF |
|
387 setvbuf(stdout, outbuf, _IOFBF, BUFSIZ); |
|
388 setvbuf(stderr, errbuf, _IOFBF, BUFSIZ); |
|
389 #else |
|
390 setbuffer(stdout, outbuf, BUFSIZ); |
|
391 setbuffer(stderr, errbuf, BUFSIZ); |
|
392 #endif |
|
393 |
|
394 /* This works around a bug in some versions of in.rshd. * |
|
395 * Currently this is not defined by default. */ |
|
396 #ifdef RSH_BUG_WORKAROUND |
|
397 if (cmd) { |
|
398 for (i = 3; i < 10; i++) |
|
399 close(i); |
|
400 } |
|
401 #endif |
|
402 |
|
403 if (shout) { |
|
404 /* |
|
405 * Check if shout was set to stderr, if so don't close it. |
|
406 * We do this if we are interactive but don't have a |
|
407 * terminal. |
|
408 */ |
|
409 if (shout != stderr) |
|
410 fclose(shout); |
|
411 shout = 0; |
|
412 } |
|
413 if (SHTTY != -1) { |
|
414 zclose(SHTTY); |
|
415 SHTTY = -1; |
|
416 } |
|
417 |
|
418 /* Send xtrace output to stderr -- see execcmd() */ |
|
419 xtrerr = stderr; |
|
420 |
|
421 /* Make sure the tty is opened read/write. */ |
|
422 if (isatty(0)) { |
|
423 zsfree(ttystrname); |
|
424 if ((ttystrname = ztrdup((char*)ttyname(0)))) { |
|
425 SHTTY = movefd(open(ttystrname, O_RDWR | O_NOCTTY)); |
|
426 #ifdef TIOCNXCL |
|
427 /* |
|
428 * See if the terminal claims to be busy. If so, and fd 0 |
|
429 * is a terminal, try and set non-exclusive use for that. |
|
430 * This is something to do with Solaris over-cleverness. |
|
431 */ |
|
432 if (SHTTY == -1 && errno == EBUSY) |
|
433 ioctl(0, TIOCNXCL, 0); |
|
434 #endif |
|
435 } |
|
436 /* |
|
437 * xterm, rxvt and probably all terminal emulators except |
|
438 * dtterm on Solaris 2.6 & 7 have a bug. Applications are |
|
439 * unable to open /dev/tty or /dev/pts/<terminal number here> |
|
440 * because something in Sun's STREAMS modules doesn't like |
|
441 * it. The open() call fails with EBUSY which is not even |
|
442 * listed as a possibility in the open(2) man page. So we'll |
|
443 * try to outsmart The Company. -- <dave@srce.hr> |
|
444 * |
|
445 * Presumably there's no harm trying this on any OS, given that |
|
446 * isatty(0) worked but opening the tty didn't. Possibly we won't |
|
447 * get the tty read/write, but it's the best we can do -- pws |
|
448 * |
|
449 * Try both stdin and stdout before trying /dev/tty. -- Bart |
|
450 */ |
|
451 #if defined(HAVE_FCNTL_H) && defined(F_GETFL) |
|
452 #define rdwrtty(fd) ((fcntl(fd, F_GETFL, 0) & O_RDWR) == O_RDWR) |
|
453 #else |
|
454 #define rdwrtty(fd) 1 |
|
455 #endif |
|
456 if (SHTTY == -1 && rdwrtty(0)) { |
|
457 SHTTY = movefd(dup(0)); |
|
458 } |
|
459 } |
|
460 if (SHTTY == -1 && isatty(1) && rdwrtty(1) && |
|
461 (SHTTY = movefd(dup(1))) != -1) { |
|
462 zsfree(ttystrname); |
|
463 ttystrname = ztrdup((char*)ttyname((1))); |
|
464 } |
|
465 if (SHTTY == -1 && |
|
466 (SHTTY = movefd(open("/dev/tty", O_RDWR | O_NOCTTY))) != -1) { |
|
467 zsfree(ttystrname); |
|
468 ttystrname = ztrdup((char*)ttyname(SHTTY)); |
|
469 } |
|
470 if (SHTTY == -1) { |
|
471 zsfree(ttystrname); |
|
472 ttystrname = ztrdup(""); |
|
473 } else if (!ttystrname) { |
|
474 ttystrname = ztrdup("/dev/tty"); |
|
475 } |
|
476 |
|
477 /* We will only use zle if shell is interactive, * |
|
478 * SHTTY != -1, and shout != 0 */ |
|
479 if (interact) { |
|
480 init_shout(); |
|
481 if(!SHTTY || !shout) |
|
482 opts[USEZLE] = 0; |
|
483 } else |
|
484 opts[USEZLE] = 0; |
|
485 |
|
486 #ifdef JOB_CONTROL |
|
487 /* If interactive, make sure the shell is in the foreground and is the |
|
488 * process group leader. |
|
489 */ |
|
490 mypid = (zlong)getpid(); |
|
491 if (opts[MONITOR] && interact && (SHTTY != -1)) { |
|
492 origpgrp = GETPGRP(); |
|
493 acquire_pgrp(); /* might also clear opts[MONITOR] */ |
|
494 } else |
|
495 opts[MONITOR] = 0; |
|
496 #else |
|
497 opts[MONITOR] = 0; |
|
498 #endif |
|
499 } |
|
500 |
|
501 /**/ |
|
502 mod_export void |
|
503 init_shout(void) |
|
504 { |
|
505 static char shoutbuf[BUFSIZ]; |
|
506 #if defined(JOB_CONTROL) && defined(TIOCSETD) && defined(NTTYDISC) |
|
507 int ldisc; |
|
508 #endif |
|
509 |
|
510 if (SHTTY == -1) |
|
511 { |
|
512 /* Since we're interative, it's nice to have somewhere to write. */ |
|
513 shout = stderr; |
|
514 return; |
|
515 } |
|
516 |
|
517 #if defined(JOB_CONTROL) && defined(TIOCSETD) && defined(NTTYDISC) |
|
518 ldisc = NTTYDISC; |
|
519 ioctl(SHTTY, TIOCSETD, (char *)&ldisc); |
|
520 #endif |
|
521 |
|
522 /* Associate terminal file descriptor with a FILE pointer */ |
|
523 shout = fdopen(SHTTY, "w"); |
|
524 #ifdef _IOFBF |
|
525 setvbuf(shout, shoutbuf, _IOFBF, BUFSIZ); |
|
526 #endif |
|
527 |
|
528 gettyinfo(&shttyinfo); /* get tty state */ |
|
529 #if defined(__sgi) |
|
530 if (shttyinfo.tio.c_cc[VSWTCH] <= 0) /* hack for irises */ |
|
531 shttyinfo.tio.c_cc[VSWTCH] = CSWTCH; |
|
532 #endif |
|
533 } |
|
534 |
|
535 /* names of the termcap strings we want */ |
|
536 |
|
537 static char *tccapnams[TC_COUNT] = { |
|
538 "cl", "le", "LE", "nd", "RI", "up", "UP", "do", |
|
539 "DO", "dc", "DC", "ic", "IC", "cd", "ce", "al", "dl", "ta", |
|
540 "md", "so", "us", "me", "se", "ue", "ch", |
|
541 "ku", "kd", "kl", "kr" |
|
542 }; |
|
543 |
|
544 /* Initialise termcap */ |
|
545 |
|
546 /**/ |
|
547 mod_export int |
|
548 init_term(void) |
|
549 { |
|
550 #ifndef TGETENT_ACCEPTS_NULL |
|
551 static char termbuf[2048]; /* the termcap buffer */ |
|
552 #endif |
|
553 |
|
554 if (!*term) { |
|
555 termflags |= TERM_UNKNOWN; |
|
556 return 0; |
|
557 } |
|
558 |
|
559 /* unset zle if using zsh under emacs */ |
|
560 if (!strcmp(term, "emacs")) |
|
561 opts[USEZLE] = 0; |
|
562 |
|
563 #ifdef TGETENT_ACCEPTS_NULL |
|
564 /* If possible, we let tgetent allocate its own termcap buffer */ |
|
565 if (tgetent(NULL, term) != TGETENT_SUCCESS) |
|
566 #else |
|
567 if (tgetent(termbuf, term) != TGETENT_SUCCESS) |
|
568 #endif |
|
569 { |
|
570 if (isset(INTERACTIVE)) |
|
571 zerr("can't find terminal definition for %s", term, 0); |
|
572 errflag = 0; |
|
573 termflags |= TERM_BAD; |
|
574 return 0; |
|
575 } else { |
|
576 char tbuf[1024], *pp; |
|
577 int t0; |
|
578 |
|
579 termflags &= ~TERM_BAD; |
|
580 termflags &= ~TERM_UNKNOWN; |
|
581 for (t0 = 0; t0 != TC_COUNT; t0++) { |
|
582 pp = tbuf; |
|
583 zsfree(tcstr[t0]); |
|
584 /* AIX tgetstr() ignores second argument */ |
|
585 if (!(pp = tgetstr(tccapnams[t0], &pp))) |
|
586 tcstr[t0] = NULL, tclen[t0] = 0; |
|
587 else { |
|
588 tclen[t0] = strlen(pp); |
|
589 tcstr[t0] = (char *) zalloc(tclen[t0] + 1); |
|
590 memcpy(tcstr[t0], pp, tclen[t0] + 1); |
|
591 } |
|
592 } |
|
593 |
|
594 /* check whether terminal has automargin (wraparound) capability */ |
|
595 hasam = tgetflag("am"); |
|
596 |
|
597 tclines = tgetnum("li"); |
|
598 tccolumns = tgetnum("co"); |
|
599 |
|
600 /* if there's no termcap entry for cursor up, use single line mode: * |
|
601 * this is flagged by termflags which is examined in zle_refresh.c * |
|
602 */ |
|
603 if (tccan(TCUP)) |
|
604 termflags &= ~TERM_NOUP; |
|
605 else { |
|
606 tcstr[TCUP] = NULL; |
|
607 termflags |= TERM_NOUP; |
|
608 } |
|
609 |
|
610 /* if there's no termcap entry for cursor left, use \b. */ |
|
611 if (!tccan(TCLEFT)) { |
|
612 tcstr[TCLEFT] = ztrdup("\b"); |
|
613 tclen[TCLEFT] = 1; |
|
614 } |
|
615 |
|
616 /* if the termcap entry for down is \n, don't use it. */ |
|
617 if (tccan(TCDOWN) && tcstr[TCDOWN][0] == '\n') { |
|
618 tclen[TCDOWN] = 0; |
|
619 zsfree(tcstr[TCDOWN]); |
|
620 tcstr[TCDOWN] = NULL; |
|
621 } |
|
622 |
|
623 /* if there's no termcap entry for clear, use ^L. */ |
|
624 if (!tccan(TCCLEARSCREEN)) { |
|
625 tcstr[TCCLEARSCREEN] = ztrdup("\14"); |
|
626 tclen[TCCLEARSCREEN] = 1; |
|
627 } |
|
628 } |
|
629 return 1; |
|
630 } |
|
631 |
|
632 /* Initialize lots of global variables and hash tables */ |
|
633 |
|
634 /**/ |
|
635 void |
|
636 setupvals(void) |
|
637 { |
|
638 #ifdef HAVE_GETPWUID |
|
639 struct passwd *pswd; |
|
640 #endif |
|
641 struct timezone dummy_tz; |
|
642 char *ptr; |
|
643 int i, j; |
|
644 #if defined(SITEFPATH_DIR) || defined(FPATH_DIR) |
|
645 char **fpathptr; |
|
646 # if defined(FPATH_DIR) && defined(FPATH_SUBDIRS) |
|
647 char *fpath_subdirs[] = FPATH_SUBDIRS; |
|
648 # endif |
|
649 # ifdef SITEFPATH_DIR |
|
650 int fpathlen = 1; |
|
651 # else |
|
652 int fpathlen = 0; |
|
653 # endif |
|
654 #endif |
|
655 int close_fds[10], tmppipe[2]; |
|
656 |
|
657 /* |
|
658 * Workaround a problem with NIS (in one guise or another) which |
|
659 * grabs file descriptors and keeps them for future reference. |
|
660 * We don't want these to be in the range where the user can |
|
661 * open fd's, i.e. 0 to 9 inclusive. So we make sure all |
|
662 * fd's in that range are in use. |
|
663 */ |
|
664 memset(close_fds, 0, 10*sizeof(int)); |
|
665 if (pipe(tmppipe) == 0) { |
|
666 /* |
|
667 * Strategy: Make sure we have at least fd 0 open (hence |
|
668 * the pipe). From then on, keep dup'ing until we are |
|
669 * up to 9. If we go over the top, close immediately, else |
|
670 * mark for later closure. |
|
671 */ |
|
672 i = -1; /* max fd we have checked */ |
|
673 while (i < 9) { |
|
674 /* j is current fd */ |
|
675 if (i < tmppipe[0]) |
|
676 j = tmppipe[0]; |
|
677 else if (i < tmppipe[1]) |
|
678 j = tmppipe[1]; |
|
679 else { |
|
680 j = dup(0); |
|
681 if (j == -1) |
|
682 break; |
|
683 } |
|
684 if (j < 10) |
|
685 close_fds[j] = 1; |
|
686 else |
|
687 close(j); |
|
688 if (i < j) |
|
689 i = j; |
|
690 } |
|
691 if (i < tmppipe[0]) |
|
692 close(tmppipe[0]); |
|
693 if (i < tmppipe[1]) |
|
694 close(tmppipe[1]); |
|
695 } |
|
696 |
|
697 addhookdefs(argzero, zshhooks, sizeof(zshhooks)/sizeof(*zshhooks)); |
|
698 |
|
699 init_eprog(); |
|
700 |
|
701 zero_mnumber.type = MN_INTEGER; |
|
702 zero_mnumber.u.l = 0; |
|
703 |
|
704 getkeyptr = NULL; |
|
705 |
|
706 lineno = 1; |
|
707 noeval = 0; |
|
708 curhist = 0; |
|
709 histsiz = DEFAULT_HISTSIZE; |
|
710 inithist(); |
|
711 |
|
712 cmdstack = (unsigned char *) zalloc(CMDSTACKSZ); |
|
713 cmdsp = 0; |
|
714 |
|
715 bangchar = '!'; |
|
716 hashchar = '#'; |
|
717 hatchar = '^'; |
|
718 termflags = TERM_UNKNOWN; |
|
719 curjob = prevjob = coprocin = coprocout = -1; |
|
720 gettimeofday(&shtimer, &dummy_tz); /* init $SECONDS */ |
|
721 srand((unsigned int)(shtimer.tv_sec + shtimer.tv_usec)); /* seed $RANDOM */ |
|
722 |
|
723 /* Set default path */ |
|
724 #ifndef __SYMBIAN32__ |
|
725 path = (char **) zalloc(sizeof(*path) * 5); |
|
726 path[0] = ztrdup("/bin"); |
|
727 path[1] = ztrdup("/usr/bin"); |
|
728 path[2] = ztrdup("/usr/ucb"); |
|
729 path[3] = ztrdup("/usr/local/bin"); |
|
730 path[4] = NULL; |
|
731 #else |
|
732 path = (char **) zalloc(sizeof(*path) * 1); |
|
733 path[0] = NULL; |
|
734 #endif |
|
735 cdpath = mkarray(NULL); |
|
736 manpath = mkarray(NULL); |
|
737 fignore = mkarray(NULL); |
|
738 |
|
739 #if defined(SITEFPATH_DIR) || defined(FPATH_DIR) |
|
740 # ifdef FPATH_DIR |
|
741 # ifdef FPATH_SUBDIRS |
|
742 fpathlen += sizeof(fpath_subdirs)/sizeof(char *); |
|
743 # else |
|
744 fpathlen++; |
|
745 # endif |
|
746 # endif |
|
747 fpath = fpathptr = (char **)zalloc((fpathlen+1)*sizeof(char *)); |
|
748 # ifdef SITEFPATH_DIR |
|
749 *fpathptr++ = ztrdup(SITEFPATH_DIR); |
|
750 fpathlen--; |
|
751 # endif |
|
752 # ifdef FPATH_DIR |
|
753 # ifdef FPATH_SUBDIRS |
|
754 for (j = 0; j < fpathlen; j++) |
|
755 *fpathptr++ = tricat(FPATH_DIR, "/", fpath_subdirs[j]); |
|
756 # else |
|
757 *fpathptr++ = ztrdup(FPATH_DIR); |
|
758 # endif |
|
759 # endif |
|
760 *fpathptr = NULL; |
|
761 #else |
|
762 fpath = mkarray(NULL); |
|
763 #endif |
|
764 |
|
765 mailpath = mkarray(NULL); |
|
766 watch = mkarray(NULL); |
|
767 psvar = mkarray(NULL); |
|
768 module_path = mkarray(ztrdup(MODULE_DIR)); |
|
769 modules = znewlinklist(); |
|
770 linkedmodules = znewlinklist(); |
|
771 |
|
772 /* Set default prompts */ |
|
773 if(unset(INTERACTIVE)) { |
|
774 prompt = ztrdup(""); |
|
775 prompt2 = ztrdup(""); |
|
776 } else if (emulation == EMULATE_KSH || emulation == EMULATE_SH) { |
|
777 prompt = ztrdup(privasserted() ? "# " : "$ "); |
|
778 prompt2 = ztrdup("> "); |
|
779 } else { |
|
780 prompt = ztrdup("%m%# "); |
|
781 prompt2 = ztrdup("%_> "); |
|
782 } |
|
783 prompt3 = ztrdup("?# "); |
|
784 prompt4 = (emulation == EMULATE_KSH || emulation == EMULATE_SH) |
|
785 ? ztrdup("+ ") : ztrdup("+%N:%i> "); |
|
786 sprompt = ztrdup("zsh: correct '%R' to '%r' [nyae]? "); |
|
787 |
|
788 ifs = ztrdup(DEFAULT_IFS); |
|
789 wordchars = ztrdup(DEFAULT_WORDCHARS); |
|
790 postedit = ztrdup(""); |
|
791 underscore = (char *) zalloc(underscorelen = 32); |
|
792 underscoreused = 1; |
|
793 *underscore = '\0'; |
|
794 |
|
795 zoptarg = ztrdup(""); |
|
796 zoptind = 1; |
|
797 |
|
798 ppid = (zlong) getppid(); |
|
799 mypid = (zlong) getpid(); |
|
800 term = ztrdup(""); |
|
801 |
|
802 nullcmd = ztrdup("cat"); |
|
803 readnullcmd = ztrdup("more"); |
|
804 |
|
805 /* We cache the uid so we know when to * |
|
806 * recheck the info for `USERNAME' */ |
|
807 cached_uid = getuid(); |
|
808 |
|
809 /* Get password entry and set info for `HOME' and `USERNAME' */ |
|
810 #ifdef HAVE_GETPWUID |
|
811 if ((pswd = getpwuid(cached_uid))) { |
|
812 #ifdef __SYMBIAN32__ |
|
813 char sysDrv[2 +1]; |
|
814 sprintf(sysDrv, "%c:", getSystemDriveChar()); |
|
815 home = metafy(sysDrv, -1, META_DUP); |
|
816 |
|
817 //change the pwd to the system drive. |
|
818 chdir(sysDrv); |
|
819 #else |
|
820 home = metafy(pswd->pw_dir, -1, META_DUP); |
|
821 #endif |
|
822 cached_username = ztrdup(pswd->pw_name); |
|
823 } else |
|
824 #endif /* HAVE_GETPWUID */ |
|
825 { |
|
826 home = ztrdup("/"); |
|
827 cached_username = ztrdup(""); |
|
828 } |
|
829 |
|
830 /* Try a cheap test to see if we can * |
|
831 * initialize `PWD' from `HOME' */ |
|
832 if (ispwd(home)) |
|
833 pwd = ztrdup(home); |
|
834 else if ((ptr = zgetenv("PWD")) && (strlen(ptr) < PATH_MAX) && |
|
835 (ptr = metafy(ptr, -1, META_STATIC), ispwd(ptr))) |
|
836 pwd = ztrdup(ptr); |
|
837 else |
|
838 pwd = metafy(zgetcwd(), -1, META_DUP); |
|
839 |
|
840 oldpwd = ztrdup(pwd); /* initialize `OLDPWD' = `PWD' */ |
|
841 |
|
842 inittyptab(); /* initialize the ztypes table */ |
|
843 initlextabs(); /* initialize lexing tables */ |
|
844 |
|
845 createreswdtable(); /* create hash table for reserved words */ |
|
846 createaliastables(); /* create hash tables for aliases */ |
|
847 createcmdnamtable(); /* create hash table for external commands */ |
|
848 createshfunctable(); /* create hash table for shell functions */ |
|
849 createbuiltintable(); /* create hash table for builtin commands */ |
|
850 createnameddirtable(); /* create hash table for named directories */ |
|
851 createparamtable(); /* create parameter hash table */ |
|
852 |
|
853 condtab = NULL; |
|
854 wrappers = NULL; |
|
855 |
|
856 #ifdef TIOCGWINSZ |
|
857 adjustwinsize(0); |
|
858 #else |
|
859 /* columns and lines are normally zero, unless something different * |
|
860 * was inhereted from the environment. If either of them are zero * |
|
861 * the setiparam calls below set them to the defaults from termcap */ |
|
862 setiparam("COLUMNS", columns); |
|
863 setiparam("LINES", lines); |
|
864 #endif |
|
865 |
|
866 #ifdef HAVE_GETRLIMIT |
|
867 for (i = 0; i != RLIM_NLIMITS; i++) { |
|
868 getrlimit(i, current_limits + i); |
|
869 limits[i] = current_limits[i]; |
|
870 } |
|
871 #endif |
|
872 |
|
873 breaks = loops = 0; |
|
874 lastmailcheck = time(NULL); |
|
875 locallevel = sourcelevel = 0; |
|
876 sfcontext = SFC_NONE; |
|
877 trapreturn = 0; |
|
878 noerrexit = -1; |
|
879 nohistsave = 1; |
|
880 dirstack = znewlinklist(); |
|
881 bufstack = znewlinklist(); |
|
882 prepromptfns = znewlinklist(); |
|
883 hsubl = hsubr = NULL; |
|
884 lastpid = 0; |
|
885 bshin = SHIN ? fdopen(SHIN, "r") : stdin; |
|
886 if (isset(SHINSTDIN) && !SHIN && unset(INTERACTIVE)) { |
|
887 #ifdef _IONBF |
|
888 setvbuf(stdin, NULL, _IONBF, 0); |
|
889 #else |
|
890 setlinebuf(stdin); |
|
891 #endif |
|
892 } |
|
893 |
|
894 get_usage(); |
|
895 |
|
896 /* Close the file descriptors we opened to block off 0 to 9 */ |
|
897 for (i = 0; i < 10; i++) |
|
898 if (close_fds[i]) |
|
899 close(i); |
|
900 } |
|
901 |
|
902 /* Initialize signal handling */ |
|
903 |
|
904 /**/ |
|
905 void |
|
906 init_signals(void) |
|
907 { |
|
908 #ifndef __SYMBIAN32__ |
|
909 if (interact) { |
|
910 int i; |
|
911 signal_setmask(signal_mask(0)); |
|
912 for (i=0; i<NSIG; ++i) |
|
913 signal_default(i); |
|
914 } |
|
915 sigchld_mask = signal_mask(SIGCHLD); |
|
916 |
|
917 intr(); |
|
918 |
|
919 #ifndef QDEBUG |
|
920 signal_ignore(SIGQUIT); |
|
921 #endif |
|
922 |
|
923 if (signal_ignore(SIGHUP) == SIG_IGN) |
|
924 opts[HUP] = 0; |
|
925 else |
|
926 install_handler(SIGHUP); |
|
927 install_handler(SIGCHLD); |
|
928 #ifdef SIGWINCH |
|
929 install_handler(SIGWINCH); |
|
930 #endif |
|
931 if (interact) { |
|
932 install_handler(SIGALRM); |
|
933 signal_ignore(SIGTERM); |
|
934 } |
|
935 if (jobbing) { |
|
936 signal_ignore(SIGTTOU); |
|
937 signal_ignore(SIGTSTP); |
|
938 signal_ignore(SIGTTIN); |
|
939 } |
|
940 #endif //__SYMBIAN32__ |
|
941 } |
|
942 |
|
943 /* Source the init scripts. If called as "ksh" or "sh" * |
|
944 * then we source the standard sh/ksh scripts instead of * |
|
945 * the standard zsh scripts */ |
|
946 |
|
947 /**/ |
|
948 void |
|
949 run_init_scripts(void) |
|
950 { |
|
951 noerrexit = -1; |
|
952 |
|
953 if (emulation == EMULATE_KSH || emulation == EMULATE_SH) { |
|
954 if (islogin) |
|
955 source("/etc/profile"); |
|
956 if (unset(PRIVILEGED)) { |
|
957 char *s = getsparam("ENV"); |
|
958 if (islogin) |
|
959 sourcehome(".profile"); |
|
960 noerrs = 2; |
|
961 if (s && !parsestr(s)) { |
|
962 singsub(&s); |
|
963 noerrs = 0; |
|
964 source(s); |
|
965 } |
|
966 noerrs = 0; |
|
967 } else |
|
968 source("/etc/suid_profile"); |
|
969 } else { |
|
970 #ifdef GLOBAL_ZSHENV |
|
971 source(GLOBAL_ZSHENV); |
|
972 #endif |
|
973 if (isset(RCS) && unset(PRIVILEGED)) |
|
974 sourcehome(".zshenv"); |
|
975 if (islogin) { |
|
976 #ifdef GLOBAL_ZPROFILE |
|
977 if (isset(RCS) && isset(GLOBALRCS)) |
|
978 source(GLOBAL_ZPROFILE); |
|
979 #endif |
|
980 if (isset(RCS) && unset(PRIVILEGED)) |
|
981 sourcehome(".zprofile"); |
|
982 } |
|
983 if (interact) { |
|
984 #ifdef GLOBAL_ZSHRC |
|
985 if (isset(RCS) && isset(GLOBALRCS)) |
|
986 source(GLOBAL_ZSHRC); |
|
987 #endif |
|
988 if (isset(RCS) && unset(PRIVILEGED)) |
|
989 sourcehome(".zshrc"); |
|
990 } |
|
991 if (islogin) { |
|
992 #ifdef GLOBAL_ZLOGIN |
|
993 if (isset(RCS) && isset(GLOBALRCS)) |
|
994 source(GLOBAL_ZLOGIN); |
|
995 #endif |
|
996 if (isset(RCS) && unset(PRIVILEGED)) |
|
997 sourcehome(".zlogin"); |
|
998 } |
|
999 } |
|
1000 noerrexit = 0; |
|
1001 nohistsave = 0; |
|
1002 } |
|
1003 |
|
1004 /* Miscellaneous initializations that happen after init scripts are run */ |
|
1005 |
|
1006 /**/ |
|
1007 void |
|
1008 init_misc(void) |
|
1009 { |
|
1010 #ifndef RESTRICTED_R |
|
1011 if ( restricted ) |
|
1012 #else |
|
1013 if (*zsh_name == 'r' || restricted) |
|
1014 #endif |
|
1015 dosetopt(RESTRICTED, 1, 0); |
|
1016 if (cmd) { |
|
1017 if (SHIN >= 10) |
|
1018 fclose(bshin); |
|
1019 SHIN = movefd(open("/dev/null", O_RDONLY | O_NOCTTY)); |
|
1020 bshin = fdopen(SHIN, "r"); |
|
1021 execstring(cmd, 0, 1); |
|
1022 stopmsg = 1; |
|
1023 zexit(lastval, 0); |
|
1024 } |
|
1025 |
|
1026 if (interact && isset(RCS)) |
|
1027 readhistfile(NULL, 0, HFILE_USE_OPTIONS); |
|
1028 } |
|
1029 |
|
1030 /* source a file */ |
|
1031 |
|
1032 /**/ |
|
1033 int |
|
1034 source(char *s) |
|
1035 { |
|
1036 Eprog prog; |
|
1037 int tempfd = -1, fd, cj, oldlineno; |
|
1038 int oldshst, osubsh, oloops; |
|
1039 FILE *obshin; |
|
1040 char *old_scriptname = scriptname, *us; |
|
1041 unsigned char *ocs; |
|
1042 int ocsp; |
|
1043 |
|
1044 if (!s || |
|
1045 (!(prog = try_source_file((us = unmeta(s)))) && |
|
1046 (tempfd = movefd(open(us, O_RDONLY | O_NOCTTY))) == -1)) { |
|
1047 return 1; |
|
1048 } |
|
1049 |
|
1050 /* save the current shell state */ |
|
1051 fd = SHIN; /* store the shell input fd */ |
|
1052 obshin = bshin; /* store file handle for buffered shell input */ |
|
1053 osubsh = subsh; /* store whether we are in a subshell */ |
|
1054 cj = thisjob; /* store our current job number */ |
|
1055 oldlineno = lineno; /* store our current lineno */ |
|
1056 oloops = loops; /* stored the # of nested loops we are in */ |
|
1057 oldshst = opts[SHINSTDIN]; /* store current value of this option */ |
|
1058 ocs = cmdstack; |
|
1059 ocsp = cmdsp; |
|
1060 cmdstack = (unsigned char *) zalloc(CMDSTACKSZ); |
|
1061 cmdsp = 0; |
|
1062 |
|
1063 if (!prog) { |
|
1064 SHIN = tempfd; |
|
1065 bshin = fdopen(SHIN, "r"); |
|
1066 } |
|
1067 subsh = 0; |
|
1068 lineno = 1; |
|
1069 loops = 0; |
|
1070 dosetopt(SHINSTDIN, 0, 1); |
|
1071 scriptname = s; |
|
1072 |
|
1073 sourcelevel++; |
|
1074 if (prog) { |
|
1075 pushheap(); |
|
1076 errflag = 0; |
|
1077 execode(prog, 1, 0); |
|
1078 popheap(); |
|
1079 } else |
|
1080 loop(0, 0); /* loop through the file to be sourced */ |
|
1081 sourcelevel--; |
|
1082 |
|
1083 /* restore the current shell state */ |
|
1084 if (prog) |
|
1085 freeeprog(prog); |
|
1086 else { |
|
1087 fclose(bshin); |
|
1088 fdtable[SHIN] = 0; |
|
1089 SHIN = fd; /* the shell input fd */ |
|
1090 bshin = obshin; /* file handle for buffered shell input */ |
|
1091 } |
|
1092 subsh = osubsh; /* whether we are in a subshell */ |
|
1093 thisjob = cj; /* current job number */ |
|
1094 lineno = oldlineno; /* our current lineno */ |
|
1095 loops = oloops; /* the # of nested loops we are in */ |
|
1096 dosetopt(SHINSTDIN, oldshst, 1); /* SHINSTDIN option */ |
|
1097 errflag = 0; |
|
1098 if (!exit_pending) |
|
1099 retflag = 0; |
|
1100 scriptname = old_scriptname; |
|
1101 free(cmdstack); |
|
1102 cmdstack = ocs; |
|
1103 cmdsp = ocsp; |
|
1104 |
|
1105 return 0; |
|
1106 } |
|
1107 |
|
1108 /* Try to source a file in the home directory */ |
|
1109 |
|
1110 /**/ |
|
1111 void |
|
1112 sourcehome(char *s) |
|
1113 { |
|
1114 char *h; |
|
1115 |
|
1116 queue_signals(); |
|
1117 if (emulation == EMULATE_SH || emulation == EMULATE_KSH || |
|
1118 !(h = getsparam("ZDOTDIR"))) |
|
1119 h = home; |
|
1120 |
|
1121 { |
|
1122 /* Let source() complain if path is too long */ |
|
1123 VARARR(char, buf, strlen(h) + strlen(s) + 2); |
|
1124 sprintf(buf, "%s/%s", h, s); |
|
1125 unqueue_signals(); |
|
1126 source(buf); |
|
1127 } |
|
1128 } |
|
1129 |
|
1130 /**/ |
|
1131 void |
|
1132 init_bltinmods(void) |
|
1133 { |
|
1134 |
|
1135 #include "bltinmods.list" |
|
1136 |
|
1137 load_module("zsh/main"); |
|
1138 } |
|
1139 |
|
1140 /**/ |
|
1141 mod_export void |
|
1142 noop_function(void) |
|
1143 { |
|
1144 /* do nothing */ |
|
1145 } |
|
1146 |
|
1147 /**/ |
|
1148 mod_export void |
|
1149 noop_function_int(UNUSED(int nothing)) |
|
1150 { |
|
1151 /* do nothing */ |
|
1152 } |
|
1153 |
|
1154 /* ZLE entry point pointers. They are defined here because the initial * |
|
1155 * values depend on whether ZLE is linked in or not -- if it is, we * |
|
1156 * avoid wasting space with the fallback functions. No other source * |
|
1157 * file needs to know which modules are linked in. */ |
|
1158 |
|
1159 #ifdef LINKED_XMOD_zshQszle |
|
1160 |
|
1161 /**/ |
|
1162 mod_export ZleVoidFn trashzleptr = noop_function; |
|
1163 /**/ |
|
1164 mod_export ZleVoidFn zle_resetpromptptr = noop_function; |
|
1165 /**/ |
|
1166 mod_export ZleVoidFn refreshptr = noop_function; |
|
1167 /**/ |
|
1168 mod_export ZleVoidIntFn spaceinlineptr = noop_function_int; |
|
1169 /**/ |
|
1170 mod_export ZleReadFn zlereadptr = autoload_zleread; |
|
1171 /**/ |
|
1172 mod_export ZleVoidIntFn zlesetkeymapptr = noop_function_int; |
|
1173 |
|
1174 #else /* !LINKED_XMOD_zshQszle */ |
|
1175 |
|
1176 mod_export ZleVoidFn trashzleptr = noop_function; |
|
1177 mod_export ZleVoidFn zle_resetpromptptr = noop_function; |
|
1178 mod_export ZleVoidFn refreshptr = noop_function; |
|
1179 mod_export ZleVoidIntFn spaceinlineptr = noop_function_int; |
|
1180 # ifdef UNLINKED_XMOD_zshQszle |
|
1181 mod_export ZleReadFn zlereadptr = autoload_zleread; |
|
1182 mod_export ZleVoidIntFn zlesetkeymapptr = autoload_zlesetkeymap; |
|
1183 # else /* !UNLINKED_XMOD_zshQszle */ |
|
1184 mod_export ZleReadFn zlereadptr = fallback_zleread; |
|
1185 mod_export ZleVoidIntFn zlesetkeymapptr = noop_function_int; |
|
1186 # endif /* !UNLINKED_XMOD_zshQszle */ |
|
1187 |
|
1188 #endif /* !LINKED_XMOD_zshQszle */ |
|
1189 |
|
1190 /**/ |
|
1191 unsigned char * |
|
1192 autoload_zleread(char **lp, char **rp, int ha, int con) |
|
1193 { |
|
1194 zlereadptr = fallback_zleread; |
|
1195 #ifndef __SYMBIAN32__ |
|
1196 if (load_module("zsh/zle")) |
|
1197 load_module("zsh/compctl"); |
|
1198 #endif |
|
1199 return zleread(lp, rp, ha, con); |
|
1200 } |
|
1201 |
|
1202 /**/ |
|
1203 mod_export unsigned char * |
|
1204 fallback_zleread(char **lp, UNUSED(char **rp), UNUSED(int ha), UNUSED(int con)) |
|
1205 { |
|
1206 char *pptbuf; |
|
1207 int pptlen; |
|
1208 |
|
1209 pptbuf = unmetafy(promptexpand(lp ? *lp : NULL, 0, NULL, NULL), &pptlen); |
|
1210 write(1, (WRITE_ARG_2_T)pptbuf, pptlen); |
|
1211 free(pptbuf); |
|
1212 |
|
1213 return (unsigned char *)shingetline(); |
|
1214 } |
|
1215 |
|
1216 /**/ |
|
1217 static void |
|
1218 autoload_zlesetkeymap(int mode) |
|
1219 { |
|
1220 zlesetkeymapptr = noop_function_int; |
|
1221 load_module("zsh/zle"); |
|
1222 (*zlesetkeymapptr)(mode); |
|
1223 } |
|
1224 |
|
1225 |
|
1226 /* compctl entry point pointers. Similar to the ZLE ones. */ |
|
1227 |
|
1228 /**/ |
|
1229 mod_export CompctlReadFn compctlreadptr = fallback_compctlread; |
|
1230 |
|
1231 /**/ |
|
1232 mod_export int |
|
1233 fallback_compctlread(char *name, UNUSED(char **args), UNUSED(Options ops), UNUSED(char *reply)) |
|
1234 { |
|
1235 zwarnnam(name, "option valid only in functions called from completion", |
|
1236 NULL, 0); |
|
1237 return 1; |
|
1238 } |
|
1239 |
|
1240 |
|
1241 #ifdef __SYMBIAN32__ |
|
1242 //typdef for command function ptr.. |
|
1243 typedef int (*fptr)(char*, char**, Options, int); |
|
1244 |
|
1245 //enumator to be used with zsh_main to located the internal command... |
|
1246 typedef enum |
|
1247 { |
|
1248 CMD=0, |
|
1249 CMDARGS, |
|
1250 OPT_IND, |
|
1251 OPT_ARGS, |
|
1252 OPT_ARGCNT, |
|
1253 OPT_ARGALLOC, |
|
1254 FUNC_ID, |
|
1255 }ARG_SCAN; |
|
1256 |
|
1257 //map of command name to the command function ptr... |
|
1258 typedef struct commandmap |
|
1259 { |
|
1260 char* cmdname; |
|
1261 fptr cmdptr; |
|
1262 }CMD_MAP; |
|
1263 |
|
1264 //fill this table with all the builtin functions.... |
|
1265 static CMD_MAP cmd_tab[]= |
|
1266 { |
|
1267 {"ls", bin_ls}, |
|
1268 {"cp", bin_cp }, |
|
1269 {"more", bin_more}, |
|
1270 {"echo", bin_print}, |
|
1271 {"read", bin_read}, |
|
1272 {"alias", bin_alias}, |
|
1273 {"autoload", bin_functions}, |
|
1274 {"break", bin_break}, |
|
1275 {"cd", bin_cd}, |
|
1276 {"dirs", bin_dirs}, |
|
1277 {"echo", bin_print}, |
|
1278 {"emulate", bin_emulate}, |
|
1279 {"eval", bin_eval}, |
|
1280 {"fc", bin_fc}, |
|
1281 {"history", bin_fc}, |
|
1282 {"let", bin_let}, |
|
1283 {"print", bin_print}, |
|
1284 {"printf", bin_print}, |
|
1285 {"pwd", bin_pwd}, |
|
1286 {"set", bin_set}, |
|
1287 {"setopt", bin_setopt}, |
|
1288 {"shift", bin_shift}, |
|
1289 {"source", bin_dot}, |
|
1290 {"true", bin_true}, |
|
1291 {"type", bin_whence}, |
|
1292 {"typeset", bin_typeset}, |
|
1293 {"unalias", bin_unhash}, |
|
1294 {"whence", bin_whence}, |
|
1295 {"mkdir", bin_mkdir}, |
|
1296 {"mv", bin_ln}, |
|
1297 {"rm", bin_rm}, |
|
1298 {"rmdir", bin_rmdir}, |
|
1299 {"touch", bin_touch}, |
|
1300 {"cat", bin_cat}, |
|
1301 |
|
1302 {NULL, NULL}, |
|
1303 }; |
|
1304 |
|
1305 //map the command string to the function pointer.. |
|
1306 fptr mapCommand(char* cmd) |
|
1307 { |
|
1308 if(cmd==NULL) |
|
1309 return NULL; |
|
1310 |
|
1311 else |
|
1312 { |
|
1313 int idx=0; |
|
1314 while(cmd_tab[idx].cmdname!=NULL) |
|
1315 { |
|
1316 if(strcmp(cmd, cmd_tab[idx].cmdname)==0) |
|
1317 return cmd_tab[idx].cmdptr; |
|
1318 |
|
1319 idx++; |
|
1320 } |
|
1321 } |
|
1322 return NULL; |
|
1323 } |
|
1324 |
|
1325 //get the value for the given var from the env list... |
|
1326 char* get_value(char* var, char** env_list) |
|
1327 { |
|
1328 char* pwd = NULL; |
|
1329 size_t idx=0; |
|
1330 |
|
1331 if(!var || !env_list) |
|
1332 return NULL; |
|
1333 |
|
1334 while(env_list[idx]) |
|
1335 { |
|
1336 char* temp=env_list[idx]; |
|
1337 if(strstr(temp, var)) |
|
1338 { |
|
1339 while(*temp!='='&& temp++); |
|
1340 |
|
1341 if(temp++) |
|
1342 pwd=temp; |
|
1343 break; |
|
1344 } |
|
1345 idx++; |
|
1346 } |
|
1347 return pwd; |
|
1348 } |
|
1349 #endif //__SYMBIAN32__ |
|
1350 |
|
1351 |
|
1352 /* |
|
1353 * This is real main entry point. This has to be mod_export'ed |
|
1354 * so zsh.exe can found it on Cygwin |
|
1355 */ |
|
1356 |
|
1357 /**/ |
|
1358 mod_export int |
|
1359 zsh_main(int argc, char **argv, char** env) |
|
1360 { |
|
1361 char **t; |
|
1362 int t0; |
|
1363 |
|
1364 #ifdef USE_LOCALE |
|
1365 setlocale(LC_ALL, ""); |
|
1366 #endif |
|
1367 |
|
1368 #ifdef __SYMBIAN32__ |
|
1369 { |
|
1370 if(argc>7 && (argv && *argv)) |
|
1371 { |
|
1372 char* command=NULL; |
|
1373 char** cmdargs=NULL; |
|
1374 char* opt_ind=NULL; |
|
1375 char** optargs=NULL; |
|
1376 int optargcnt=0; |
|
1377 int optargalloc=0; |
|
1378 int funcid=0; |
|
1379 ARG_SCAN arg_scan=CMD; |
|
1380 char* path=get_value("PWD", env); |
|
1381 |
|
1382 setupvals(); |
|
1383 if(path) |
|
1384 chdir(path); |
|
1385 |
|
1386 ++argv; //ignore the first argument.. |
|
1387 switch(arg_scan) |
|
1388 { |
|
1389 case CMD: |
|
1390 command=argv[0]; |
|
1391 ++argv; |
|
1392 |
|
1393 //fall thru |
|
1394 case CMDARGS: |
|
1395 { |
|
1396 int idx=0; |
|
1397 int argcnt=atoi(*argv); |
|
1398 cmdargs=(char**)calloc(argcnt+1, sizeof(char*)); |
|
1399 if(cmdargs==NULL) |
|
1400 exit(1); |
|
1401 if(argcnt>0) |
|
1402 { |
|
1403 argzero=argv[1]; |
|
1404 while(idx<argcnt) |
|
1405 { |
|
1406 cmdargs[idx]=argv[idx+1]; |
|
1407 idx++; |
|
1408 } |
|
1409 cmdargs[argcnt]=NULL; |
|
1410 } |
|
1411 argv=argv+argcnt+1; |
|
1412 } |
|
1413 //fall thru |
|
1414 case OPT_IND: |
|
1415 { |
|
1416 int argcnt=atoi(*argv); |
|
1417 if(argcnt>0) |
|
1418 { |
|
1419 opt_ind=argv[1]; |
|
1420 argv++; |
|
1421 } |
|
1422 argv++; |
|
1423 } |
|
1424 |
|
1425 //fall thru |
|
1426 case OPT_ARGS: |
|
1427 { |
|
1428 int idx=0; |
|
1429 int argcnt=atoi(*argv); |
|
1430 optargs=(char**)calloc(argcnt+1, sizeof(char*)); |
|
1431 if(optargs==NULL) |
|
1432 exit(1); |
|
1433 if(argcnt>0) |
|
1434 { |
|
1435 while(idx<argcnt) |
|
1436 { |
|
1437 optargs[idx]=argv[idx+1]; |
|
1438 idx++; |
|
1439 } |
|
1440 optargs[argcnt]=NULL; |
|
1441 } |
|
1442 argv=argv+argcnt+1; |
|
1443 } |
|
1444 //fall thru |
|
1445 case OPT_ARGCNT: |
|
1446 optargcnt=atoi(*argv); |
|
1447 ++argv; |
|
1448 |
|
1449 //fall thru |
|
1450 case OPT_ARGALLOC: |
|
1451 optargalloc=atoi(*argv); |
|
1452 ++argv; |
|
1453 |
|
1454 //fall thru |
|
1455 case FUNC_ID: |
|
1456 funcid=atoi(*argv); |
|
1457 break; |
|
1458 |
|
1459 default: |
|
1460 break; |
|
1461 } |
|
1462 |
|
1463 if(command) |
|
1464 { |
|
1465 fptr cmd=mapCommand(command); |
|
1466 pipeUsed=1; |
|
1467 if(cmd) |
|
1468 { |
|
1469 int idx=0; |
|
1470 char temp[2]; |
|
1471 struct options ops; |
|
1472 memset(ops.ind, 0, MAX_OPS); |
|
1473 while(opt_ind && idx<MAX_OPS) |
|
1474 { |
|
1475 sprintf(temp, "%c", opt_ind[idx]); |
|
1476 ops.ind[idx]=atoi(temp); |
|
1477 |
|
1478 idx++; |
|
1479 } |
|
1480 |
|
1481 ops.args=optargs; |
|
1482 ops.argscount=optargcnt; |
|
1483 ops.argsalloc=optargalloc; |
|
1484 |
|
1485 (*cmd)(command, cmdargs, &ops, funcid); |
|
1486 } |
|
1487 |
|
1488 fflush(stdout); |
|
1489 free(cmdargs); |
|
1490 free(optargs); |
|
1491 exit(0); |
|
1492 } |
|
1493 |
|
1494 free(cmdargs); |
|
1495 free(optargs); |
|
1496 exit(0); |
|
1497 } |
|
1498 } |
|
1499 #endif //__SYMBIAN32__ |
|
1500 |
|
1501 init_jobs(argv, environ); |
|
1502 |
|
1503 /* |
|
1504 * Provisionally set up the type table to allow metafication. |
|
1505 * This will be done properly when we have decided if we are |
|
1506 * interactive |
|
1507 */ |
|
1508 typtab['\0'] |= IMETA; |
|
1509 typtab[STOUC(Meta) ] |= IMETA; |
|
1510 typtab[STOUC(Marker)] |= IMETA; |
|
1511 for (t0 = (int)STOUC(Pound); t0 <= (int)STOUC(Nularg); t0++) |
|
1512 typtab[t0] |= ITOK | IMETA; |
|
1513 |
|
1514 for (t = argv; *t; *t = metafy(*t, -1, META_ALLOC), t++); |
|
1515 |
|
1516 zsh_name = argv[0]; |
|
1517 do { |
|
1518 char *arg0 = zsh_name; |
|
1519 if (!(zsh_name = strrchr(arg0, '\\'))) |
|
1520 zsh_name = arg0; |
|
1521 else |
|
1522 zsh_name++; |
|
1523 if (*zsh_name == '-') |
|
1524 zsh_name++; |
|
1525 if (strcmp(zsh_name, "su") == 0) { |
|
1526 char *sh = zgetenv("SHELL"); |
|
1527 if (sh && *sh && arg0 != sh) |
|
1528 zsh_name = sh; |
|
1529 else |
|
1530 break; |
|
1531 } else |
|
1532 break; |
|
1533 } while (zsh_name); |
|
1534 |
|
1535 fdtable_size = zopenmax(); |
|
1536 fdtable = zshcalloc(fdtable_size); |
|
1537 |
|
1538 createoptiontable(); |
|
1539 emulate(zsh_name, 1); /* initialises most options */ |
|
1540 opts[LOGINSHELL] = (**argv == '-'); |
|
1541 opts[MONITOR] = 1; /* may be unset in init_io() */ |
|
1542 opts[PRIVILEGED] = (getuid() != geteuid() || getgid() != getegid()); |
|
1543 opts[USEZLE] = 1; /* may be unset in init_io() */ |
|
1544 parseargs(argv); /* sets INTERACTIVE, SHINSTDIN and SINGLECOMMAND */ |
|
1545 |
|
1546 SHTTY = -1; |
|
1547 init_io(); |
|
1548 setupvals(); |
|
1549 init_signals(); |
|
1550 init_bltinmods(); |
|
1551 run_init_scripts(); |
|
1552 init_misc(); |
|
1553 |
|
1554 for (;;) { |
|
1555 /* |
|
1556 * See if we can free up some of jobtab. |
|
1557 * We only do this at top level, because if we are |
|
1558 * executing stuff we may refer to them by job pointer. |
|
1559 */ |
|
1560 maybeshrinkjobtab(); |
|
1561 |
|
1562 do |
|
1563 loop(1,0); |
|
1564 while (tok != ENDINPUT && (tok != LEXERR || isset(SHINSTDIN))); |
|
1565 if (tok == LEXERR) { |
|
1566 /* Make sure a parse error exits with non-zero status */ |
|
1567 if (!lastval) |
|
1568 lastval = 1; |
|
1569 stopmsg = 1; |
|
1570 zexit(lastval, 0); |
|
1571 } |
|
1572 if (!(isset(IGNOREEOF) && interact)) { |
|
1573 #if 0 |
|
1574 if (interact) |
|
1575 fputs(islogin ? "logout\n" : "exit\n", shout); |
|
1576 #endif |
|
1577 zexit(lastval, 0); |
|
1578 continue; |
|
1579 } |
|
1580 noexitct++; |
|
1581 if (noexitct >= 10) { |
|
1582 stopmsg = 1; |
|
1583 zexit(lastval, 0); |
|
1584 } |
|
1585 zerrnam("zsh", (!islogin) ? "use 'exit' to exit." |
|
1586 : "use 'logout' to logout.", NULL, 0); |
|
1587 } |
|
1588 } |