VirtualBox

source: kBuild/trunk/src/kash/shinstance.c@ 1784

Last change on this file since 1784 was 1784, checked in by bird, 16 years ago

kash: hacking.

  • Property svn:eol-style set to LF
  • Property svn:keywords set to Id
File size: 17.5 KB
Line 
1/* $Id: shinstance.c 1784 2008-09-13 03:27:59Z bird $ */
2/** @file
3 *
4 * The shell instance methods.
5 *
6 * Copyright (c) 2007 knut st. osmundsen <[email protected]>
7 *
8 *
9 * This file is part of kBuild.
10 *
11 * kBuild is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * kBuild is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with kBuild; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 *
25 */
26
27/*******************************************************************************
28* Header Files *
29*******************************************************************************/
30#include <string.h>
31#include <stdlib.h>
32#include <assert.h>
33#ifndef _MSC_VER
34# include <unistd.h>
35# include <pwd.h>
36extern char **environ;
37#endif
38#include "shinstance.h"
39
40
41/*******************************************************************************
42* Global Variables *
43*******************************************************************************/
44/** The mutex protecting the the globals and some shell instance members (sigs). */
45static shmtx g_sh_mtx;
46/** The root shell instance. */
47static shinstance *g_sh_root;
48/** The first shell instance. */
49static shinstance *g_sh_head;
50/** The last shell instance. */
51static shinstance *g_sh_tail;
52/** The number of shells. */
53static int g_num_shells;
54/** Per signal state for determining a common denominator.
55 * @remarks defaults and unmasked actions aren't counted. */
56struct shsigstate
57{
58 /** The current signal action. */
59#ifndef _MSC_VER
60 struct sigaction sa;
61#else
62 struct
63 {
64 void (*sa_handler)(int);
65 int sa_flags;
66 shsigset_t sa_mask;
67 } sa;
68#endif
69 /** The number of restarts (siginterrupt / SA_RESTART). */
70 int num_restart;
71 /** The number of ignore handlers. */
72 int num_ignore;
73 /** The number of specific handlers. */
74 int num_specific;
75 /** The number of threads masking it. */
76 int num_masked;
77} g_sig_state[NSIG];
78
79
80
81typedef struct shmtxtmp { int i; } shmtxtmp;
82
83int shmtx_init(shmtx *pmtx)
84{
85 pmtx->b[0] = 0;
86 return 0;
87}
88
89void shmtx_delete(shmtx *pmtx)
90{
91 pmtx->b[0] = 0;
92}
93
94void shmtx_enter(shmtx *pmtx, shmtxtmp *ptmp)
95{
96 pmtx->b[0] = 0;
97 ptmp->i = 0;
98}
99
100void shmtx_leave(shmtx *pmtx, shmtxtmp *ptmp)
101{
102 pmtx->b[0] = 0;
103 ptmp->i = 432;
104}
105
106
107/**
108 * Links the shell instance.
109 *
110 * @param psh The shell.
111 */
112static void sh_int_link(shinstance *psh)
113{
114 shmtxtmp tmp;
115 shmtx_enter(&g_sh_mtx, &tmp);
116
117 if (psh->rootshell)
118 g_sh_root = psh;
119
120 psh->next = NULL;
121 psh->prev = g_sh_tail;
122 if (g_sh_tail)
123 g_sh_tail->next = psh;
124 else
125 g_sh_tail = g_sh_head = psh;
126 g_sh_tail = psh;
127
128 g_num_shells++;
129
130 shmtx_leave(&g_sh_mtx, &tmp);
131}
132
133
134/**
135 * Unlink the shell instance.
136 *
137 * @param psh The shell.
138 */
139static void sh_int_unlink(shinstance *psh)
140{
141 shmtxtmp tmp;
142 shmtx_enter(&g_sh_mtx, &tmp);
143
144 g_num_shells--;
145
146 if (g_sh_tail == psh)
147 g_sh_tail = psh->prev;
148 else
149 psh->next->prev = psh->prev;
150
151 if (g_sh_head == psh)
152 g_sh_head = psh->next;
153 else
154 psh->prev->next = psh->next;
155
156 if (g_sh_root == psh)
157 g_sh_root = 0;
158
159 shmtx_leave(&g_sh_mtx, &tmp);
160}
161
162
163/**
164 * Creates a root shell instance.
165 *
166 * @param inherit The shell to inherit from. If NULL inherit from environment and such.
167 * @param argc The argument count.
168 * @param argv The argument vector.
169 *
170 * @returns pointer to root shell on success, NULL on failure.
171 */
172shinstance *sh_create_root_shell(shinstance *inherit, int argc, char **argv)
173{
174 shinstance *psh;
175 int i;
176
177 psh = calloc(sizeof(*psh), 1);
178 if (psh)
179 {
180 /* the special stuff. */
181#ifdef _MSC_VER
182 psh->pid = _getpid();
183#else
184 psh->pid = getpid();
185#endif
186 /*sh_sigemptyset(&psh->sigrestartset);*/
187 for (i = 0; i < NSIG; i++)
188 psh->sigactions[i].sh_handler = SH_SIG_UNK;
189
190 /* memalloc.c */
191 psh->stacknleft = MINSIZE;
192 psh->herefd = -1;
193 psh->stackp = &psh->stackbase;
194 psh->stacknxt = psh->stackbase.space;
195
196 /* input.c */
197 psh->plinno = 1;
198 psh->init_editline = 0;
199 psh->parsefile = &psh->basepf;
200
201 /* output.c */
202 psh->output.bufsize = OUTBUFSIZ;
203 psh->output.fd = 1;
204 psh->output.psh = psh;
205 psh->errout.bufsize = 100;
206 psh->errout.fd = 2;
207 psh->errout.psh = psh;
208 psh->memout.fd = MEM_OUT;
209 psh->memout.psh = psh;
210 psh->out1 = &psh->output;
211 psh->out2 = &psh->errout;
212
213 /* jobs.c */
214 psh->backgndpid = -1;
215#if JOBS
216 psh->curjob = -1;
217#else
218# error asdf
219#endif
220 psh->ttyfd = -1;
221
222 /* link it. */
223 sh_int_link(psh);
224
225 }
226 return psh;
227}
228
229
230char *sh_getenv(shinstance *psh, const char *var)
231{
232#ifdef SH_PURE_STUB_MODE
233 return NULL;
234#elif defined(SH_STUB_MODE)
235 (void)psh;
236 return getenv(var);
237#else
238#endif
239}
240
241char **sh_environ(shinstance *psh)
242{
243#ifdef SH_PURE_STUB_MODE
244 static char *s_null[2] = {0,0};
245 return &s_null[0];
246#elif defined(SH_STUB_MODE)
247 (void)psh;
248 return environ;
249#else
250#endif
251}
252
253const char *sh_gethomedir(shinstance *psh, const char *user)
254{
255#ifdef SH_PURE_STUB_MODE
256 return NULL;
257#elif defined(SH_STUB_MODE)
258 (void)psh;
259# ifdef _MSC_VER
260 return NULL;
261# else
262 struct passwd *pwd = getpwnam(user);
263 return pwd ? pwd->pw_dir : NULL;
264# endif
265#else
266#endif
267}
268
269/**
270 * Lazy initialization of a signal state, globally.
271 *
272 * @param psh The shell doing the lazy work.
273 * @param signo The signal (valid).
274 */
275static void sh_int_lazy_init_sigaction(shinstance *psh, int signo)
276{
277 if (psh->sigactions[signo].sh_handler == SH_SIG_UNK)
278 {
279 shmtxtmp tmp;
280 shmtx_enter(&g_sh_mtx, &tmp);
281
282 if (psh->sigactions[signo].sh_handler == SH_SIG_UNK)
283 {
284 shsigaction_t shold;
285 shinstance *cur;
286#ifndef _MSC_VER
287 struct sigaction old;
288 if (!sigaction(signo, NULL, &old))
289 {
290 /* convert */
291 shold.sh_flags = old.sa_flags;
292 shold.sh_mask = old.sa_mask;
293 if (old.sa_handler == SIG_DFL)
294 shold.sh_handler = SH_SIG_DFL;
295 else
296 {
297 assert(old.sa_handler == SIG_IGN);
298 shold.sh_handler = SH_SIG_IGN;
299 }
300 }
301 else
302#endif
303 {
304 /* fake */
305#ifndef _MSC_VER
306 assert(0);
307 old.sa_handler = SIG_DFL;
308 old.sa_flags = 0;
309 sigemptyset(&shold.sh_mask);
310 sigaddset(&shold.sh_mask, signo);
311#endif
312 shold.sh_flags = 0;
313 sh_sigemptyset(&shold.sh_mask);
314 sh_sigaddset(&shold.sh_mask, signo);
315 shold.sh_handler = SH_SIG_DFL;
316 }
317
318 /* update globals */
319#ifndef _MSC_VER
320 g_sig_state[signo].sa = old;
321#else
322 g_sig_state[signo].sa.sa_handle = SIG_DFL;
323 g_sig_state[signo].sa.sa_flags = 0;
324 g_sig_state[signo].sa.sa_mask = shold.sh_mask;
325#endif
326
327 /* update all shells */
328 for (cur = g_sh_head; cur; cur = cur->next)
329 {
330 assert(cur->sigactions[signo].sh_handler == SH_SIG_UNK);
331 cur->sigactions[signo] = shold;
332 }
333 }
334
335 shmtx_leave(&g_sh_mtx, &tmp);
336 }
337}
338
339
340/**
341 * Handler for external signals.
342 *
343 * @param signo The signal.
344 */
345static void sh_sig_common_handler(int signo)
346{
347
348}
349
350
351int sh_sigaction(shinstance *psh, int signo, const struct shsigaction *newp, struct shsigaction *oldp)
352{
353 printf("sh_sigaction: signo=%d newp=%p oldp=%p\n", signo, newp, oldp);
354
355 /*
356 * Input validation.
357 */
358 if (signo >= NSIG || signo <= 0)
359 {
360 errno = EINVAL;
361 return -1;
362 }
363
364#ifdef SH_PURE_STUB_MODE
365 return -1;
366#else
367
368 /*
369 * Make sure our data is correct.
370 */
371 sh_int_lazy_init_sigaction(psh, signo);
372
373 /*
374 * Get the old one if requested.
375 */
376 if (oldp)
377 *oldp = psh->sigactions[signo];
378
379 /*
380 * Set the new one if it has changed.
381 *
382 * This will be attempted coordinated with the other signal handlers so
383 * that we can arrive at a common denominator.
384 */
385 if ( newp
386 && memcmp(&psh->sigactions[signo], newp, sizeof(*newp)))
387 {
388 shmtxtmp tmp;
389 shmtx_enter(&g_sh_mtx, &tmp);
390
391 /* Undo the accounting for the current entry. */
392 if (psh->sigactions[signo].sh_handler == SH_SIG_IGN)
393 g_sig_state[signo].num_ignore--;
394 else if (psh->sigactions[signo].sh_handler != SH_SIG_DFL)
395 g_sig_state[signo].num_specific--;
396 if (psh->sigactions[signo].sh_flags & SA_RESTART)
397 g_sig_state[signo].num_restart--;
398
399 /* Set the new entry. */
400 psh->sigactions[signo] = *newp;
401
402 /* Add the bits for the new action entry. */
403 if (psh->sigactions[signo].sh_handler == SH_SIG_IGN)
404 g_sig_state[signo].num_ignore++;
405 else if (psh->sigactions[signo].sh_handler != SH_SIG_DFL)
406 g_sig_state[signo].num_specific++;
407 if (psh->sigactions[signo].sh_flags & SA_RESTART)
408 g_sig_state[signo].num_restart++;
409
410 /*
411 * Calc new common action.
412 *
413 * This is quit a bit ASSUMPTIVE about the limited use. We will not
414 * bother synching the mask, and we pretend to care about SA_RESTART.
415 * The only thing we really actually care about is the sh_handler.
416 *
417 * On second though, it's possible we should just tie this to the root
418 * shell since it only really applies to external signal ...
419 */
420 if ( g_sig_state[signo].num_specific
421 || g_sig_state[signo].num_ignore != g_num_shells)
422 g_sig_state[signo].sa.sa_handler = sh_sig_common_handler;
423 else if (g_sig_state[signo].num_ignore)
424 g_sig_state[signo].sa.sa_handler = SIG_DFL;
425 else
426 g_sig_state[signo].sa.sa_handler = SIG_DFL;
427 g_sig_state[signo].sa.sa_flags = psh->sigactions[signo].sh_flags & SA_RESTART;
428
429# ifdef _MSC_VER
430 if (signal(signo, g_sig_state[signo].sa.sa_handler) == SIG_ERR)
431# else
432 if (sigaction(signo, &g_sig_state[signo].sa, NULL))
433# endif
434 assert(0);
435
436 shmtx_leave(&g_sh_mtx, &tmp);
437 }
438
439 return 0;
440#endif
441}
442
443shsig_t sh_signal(shinstance *psh, int signo, shsig_t handler)
444{
445 shsigaction_t sa;
446 shsig_t ret;
447
448 /*
449 * Implementation using sh_sigaction.
450 */
451 if (sh_sigaction(psh, signo, NULL, &sa))
452 return SH_SIG_ERR;
453
454 ret = sa.sh_handler;
455 sa.sh_flags &= SA_RESTART;
456 sa.sh_handler = handler;
457 sh_sigemptyset(&sa.sh_mask);
458 sh_sigaddset(&sa.sh_mask, signo); /* ?? */
459 if (sh_sigaction(psh, signo, &sa, NULL))
460 return SH_SIG_ERR;
461
462 return ret;
463}
464
465int sh_siginterrupt(shinstance *psh, int signo, int interrupt)
466{
467 shsigaction_t sa;
468 int oldflags = 0;
469
470 /*
471 * Implementation using sh_sigaction.
472 */
473 if (sh_sigaction(psh, signo, NULL, &sa))
474 return -1;
475 oldflags = sa.sh_flags;
476 if (interrupt)
477 sa.sh_flags &= ~SA_RESTART;
478 else
479 sa.sh_flags |= ~SA_RESTART;
480 if (!((oldflags ^ sa.sh_flags) & SA_RESTART))
481 return 0; /* unchanged. */
482
483 return sh_sigaction(psh, signo, &sa, NULL);
484}
485
486void sh_sigemptyset(shsigset_t *setp)
487{
488 memset(setp, 0, sizeof(*setp));
489}
490
491void sh_sigaddset(shsigset_t *setp, int signo)
492{
493#ifdef _MSC_VER
494 *setp |= 1U << signo;
495#else
496 sigaddset(setp, signo);
497#endif
498}
499
500void sh_sigdelset(shsigset_t *setp, int signo)
501{
502#ifdef _MSC_VER
503 *setp &= ~(1U << signo);
504#else
505 sigdelset(setp, signo);
506#endif
507}
508
509int sh_sigismember(shsigset_t *setp, int signo)
510{
511#ifdef _MSC_VER
512 return !!(*setp & (1U << signo));
513#else
514 return !!sigismember(setp, signo);
515#endif
516}
517
518int sh_sigprocmask(shinstance *psh, int operation, shsigset_t const *newp, shsigset_t *oldp)
519{
520#ifdef SH_PURE_STUB_MODE
521 return -1;
522#elif defined(SH_STUB_MODE)
523 (void)psh;
524# ifdef _MSC_VER
525 return -1;
526# else
527 return sigprocmask(operation, newp, oldp);
528# endif
529#else
530#endif
531}
532
533void sh_abort(shinstance *psh)
534{
535#ifdef SH_PURE_STUB_MODE
536#elif defined(SH_STUB_MODE)
537 (void)psh;
538 abort();
539#else
540#endif
541}
542
543void sh_raise_sigint(shinstance *psh)
544{
545#ifdef SH_PURE_STUB_MODE
546#elif defined(SH_STUB_MODE)
547 (void)psh;
548 raise(SIGINT);
549#else
550#endif
551}
552
553int sh_kill(shinstance *psh, pid_t pid, int signo)
554{
555#ifdef SH_PURE_STUB_MODE
556 return -1;
557#elif defined(SH_STUB_MODE)
558 (void)psh;
559# ifdef _MSC_VER
560 return -1;
561# else
562 //fprintf(stderr, "kill(%d, %d)\n", pid, signo);
563 return kill(pid, signo);
564# endif
565#else
566#endif
567}
568
569int sh_killpg(shinstance *psh, pid_t pgid, int signo)
570{
571#ifdef SH_PURE_STUB_MODE
572 return -1;
573#elif defined(SH_STUB_MODE)
574 (void)psh;
575# ifdef _MSC_VER
576 return -1;
577# else
578 //fprintf(stderr, "killpg(%d, %d)\n", pgid, signo);
579 return killpg(pgid, signo);
580# endif
581#else
582#endif
583}
584
585clock_t sh_times(shinstance *psh, shtms *tmsp)
586{
587#ifdef SH_PURE_STUB_MODE
588 return 0;
589#elif defined(SH_STUB_MODE)
590 (void)psh;
591# ifdef _MSC_VER
592 return 0;
593# else
594 return times(tmsp);
595# endif
596#else
597#endif
598}
599
600int sh_sysconf_clk_tck(void)
601{
602#ifdef SH_PURE_STUB_MODE
603 return 1;
604#else
605# ifdef _MSC_VER
606 return CLK_TCK;
607# else
608 return sysconf(_SC_CLK_TCK);
609# endif
610#endif
611}
612
613pid_t sh_fork(shinstance *psh)
614{
615#ifdef SH_PURE_STUB_MODE
616 return -1;
617#elif defined(SH_STUB_MODE)
618 (void)psh;
619# ifdef _MSC_VER
620 return -1;
621# else
622 return fork();
623# endif
624#else
625#endif
626}
627
628pid_t sh_waitpid(shinstance *psh, pid_t pid, int *statusp, int flags)
629{
630 *statusp = 0;
631#ifdef SH_PURE_STUB_MODE
632 return -1;
633#elif defined(SH_STUB_MODE)
634 (void)psh;
635# ifdef _MSC_VER
636 return -1;
637# else
638 pid = waitpid(pid, statusp, flags);
639 //fprintf(stderr, "waitpid -> %d *statusp=%d (rc=%d) flags=%#x\n", pid, *statusp, WEXITSTATUS(*statusp), flags);
640 return pid;
641# endif
642#else
643#endif
644}
645
646void sh__exit(shinstance *psh, int rc)
647{
648#ifdef SH_PURE_STUB_MODE
649 return -1;
650#elif defined(SH_STUB_MODE)
651 (void)psh;
652 _exit(rc);
653#else
654#endif
655}
656
657int sh_execve(shinstance *psh, const char *exe, const char * const *argv, const char * const *envp)
658{
659#ifdef SH_PURE_STUB_MODE
660 return -1;
661#elif defined(SH_STUB_MODE)
662 (void)psh;
663# ifdef _MSC_VER
664 return -1;
665# else
666 return execve(exe, (char **)argv, (char **)envp);
667# endif
668#else
669#endif
670}
671
672uid_t sh_getuid(shinstance *psh)
673{
674#ifdef SH_PURE_STUB_MODE
675 return 0;
676#elif defined(SH_STUB_MODE)
677 (void)psh;
678# ifdef _MSC_VER
679 return 0;
680# else
681 return getuid();
682# endif
683#else
684#endif
685}
686
687uid_t sh_geteuid(shinstance *psh)
688{
689#ifdef SH_PURE_STUB_MODE
690 return 0;
691#elif defined(SH_STUB_MODE)
692 (void)psh;
693# ifdef _MSC_VER
694 return 0;
695# else
696 return geteuid();
697# endif
698#else
699#endif
700}
701
702gid_t sh_getgid(shinstance *psh)
703{
704#ifdef SH_PURE_STUB_MODE
705 return 0;
706#elif defined(SH_STUB_MODE)
707 (void)psh;
708# ifdef _MSC_VER
709 return 0;
710# else
711 return getgid();
712# endif
713#else
714#endif
715}
716
717gid_t sh_getegid(shinstance *psh)
718{
719#ifdef SH_PURE_STUB_MODE
720 return 0;
721#elif defined(SH_STUB_MODE)
722 (void)psh;
723# ifdef _MSC_VER
724 return 0;
725# else
726 return getegid();
727# endif
728#else
729#endif
730}
731
732pid_t sh_getpid(shinstance *psh)
733{
734#ifdef SH_PURE_STUB_MODE
735 return 0;
736#elif defined(SH_STUB_MODE)
737 (void)psh;
738# ifdef _MSC_VER
739 return _getpid();
740# else
741 return getpid();
742# endif
743#else
744#endif
745}
746
747pid_t sh_getpgrp(shinstance *psh)
748{
749#ifdef SH_PURE_STUB_MODE
750 return 0;
751#elif defined(SH_STUB_MODE)
752 (void)psh;
753# ifdef _MSC_VER
754 return _getpid();
755# else
756 return getpgrp();
757# endif
758#else
759#endif
760}
761
762pid_t sh_getpgid(shinstance *psh, pid_t pid)
763{
764#ifdef SH_PURE_STUB_MODE
765 return pid;
766#elif defined(SH_STUB_MODE)
767 (void)psh;
768# ifdef _MSC_VER
769 return pid;
770# else
771 return getpgid(pid);
772# endif
773#else
774#endif
775}
776
777int sh_setpgid(shinstance *psh, pid_t pid, pid_t pgid)
778{
779#ifdef SH_PURE_STUB_MODE
780 return -1;
781#elif defined(SH_STUB_MODE)
782 (void)psh;
783# ifdef _MSC_VER
784 return -1;
785# else
786 int rc;
787 rc = setpgid(pid, pgid);
788 //fprintf(stderr, "setpgid(%d,%d) -> %d\n", pid, pgid, rc);
789 return rc;
790# endif
791#else
792#endif
793}
794
795pid_t sh_tcgetpgrp(shinstance *psh, int fd)
796{
797#ifdef SH_PURE_STUB_MODE
798 return -1;
799#elif defined(SH_STUB_MODE)
800 (void)psh;
801# ifdef _MSC_VER
802 return -1;
803# else
804 return tcgetpgrp(fd);
805# endif
806#else
807#endif
808}
809
810int sh_tcsetpgrp(shinstance *psh, int fd, pid_t pgrp)
811{
812#ifdef SH_PURE_STUB_MODE
813 return -1;
814#elif defined(SH_STUB_MODE)
815 (void)psh;
816# ifdef _MSC_VER
817 return -1;
818# else
819 return tcsetpgrp(fd, pgrp);
820# endif
821#else
822#endif
823}
824
825int sh_getrlimit(shinstance *psh, int resid, shrlimit *limp)
826{
827#ifdef SH_PURE_STUB_MODE
828 return -1;
829#elif defined(SH_STUB_MODE)
830 (void)psh;
831# ifdef _MSC_VER
832 return -1;
833# else
834 return getrlimit(resid, limp);
835# endif
836#else
837#endif
838}
839
840int sh_setrlimit(shinstance *psh, int resid, const shrlimit *limp)
841{
842#ifdef SH_PURE_STUB_MODE
843 return -1;
844#elif defined(SH_STUB_MODE)
845 (void)psh;
846# ifdef _MSC_VER
847 return -1;
848# else
849 return setrlimit(resid, limp);
850# endif
851#else
852#endif
853}
854
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette