source: trunk/src/kash/shinstance.c@ 2289

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

kash: implementing shfile on top of the win32 api instead of msvcrt.

  • Property svn:eol-style set to LF
  • Property svn:keywords set to Id
File size: 27.0 KB
Line 
1/* $Id: shinstance.c 2289 2009-02-26 04:58:49Z bird $ */
2/** @file
3 *
4 * The shell instance methods.
5 *
6 * Copyright (c) 2007-2009 knut st. osmundsen <bird-kBuild-spamix@anduin.net>
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#ifdef _MSC_VER
34# include <process.h>
35#else
36# include <unistd.h>
37# include <pwd.h>
38#endif
39#include "shinstance.h"
40
41
42/*******************************************************************************
43* Global Variables *
44*******************************************************************************/
45/** The mutex protecting the the globals and some shell instance members (sigs). */
46static shmtx g_sh_mtx;
47/** The root shell instance. */
48static shinstance *g_sh_root;
49/** The first shell instance. */
50static shinstance *g_sh_head;
51/** The last shell instance. */
52static shinstance *g_sh_tail;
53/** The number of shells. */
54static int volatile g_num_shells;
55/** Per signal state for determining a common denominator.
56 * @remarks defaults and unmasked actions aren't counted. */
57struct shsigstate
58{
59 /** The current signal action. */
60#ifndef _MSC_VER
61 struct sigaction sa;
62#else
63 struct
64 {
65 void (*sa_handler)(int);
66 int sa_flags;
67 shsigset_t sa_mask;
68 } sa;
69#endif
70 /** The number of restarts (siginterrupt / SA_RESTART). */
71 int num_restart;
72 /** The number of ignore handlers. */
73 int num_ignore;
74 /** The number of specific handlers. */
75 int num_specific;
76 /** The number of threads masking it. */
77 int num_masked;
78} g_sig_state[NSIG];
79
80
81
82int shmtx_init(shmtx *pmtx)
83{
84 pmtx->b[0] = 0;
85 return 0;
86}
87
88void shmtx_delete(shmtx *pmtx)
89{
90 pmtx->b[0] = 0;
91}
92
93void shmtx_enter(shmtx *pmtx, shmtxtmp *ptmp)
94{
95 pmtx->b[0] = 0;
96 ptmp->i = 0;
97}
98
99void shmtx_leave(shmtx *pmtx, shmtxtmp *ptmp)
100{
101 pmtx->b[0] = 0;
102 ptmp->i = 432;
103}
104
105/**
106 * Links the shell instance.
107 *
108 * @param psh The shell.
109 */
110static void sh_int_link(shinstance *psh)
111{
112 shmtxtmp tmp;
113 shmtx_enter(&g_sh_mtx, &tmp);
114
115 if (psh->rootshell)
116 g_sh_root = psh;
117
118 psh->next = NULL;
119 psh->prev = g_sh_tail;
120 if (g_sh_tail)
121 g_sh_tail->next = psh;
122 else
123 g_sh_tail = g_sh_head = psh;
124 g_sh_tail = psh;
125
126 g_num_shells++;
127
128 shmtx_leave(&g_sh_mtx, &tmp);
129}
130
131#if 0
132/**
133 * Unlink the shell instance.
134 *
135 * @param psh The shell.
136 */
137static void sh_int_unlink(shinstance *psh)
138{
139 shmtxtmp tmp;
140 shmtx_enter(&g_sh_mtx, &tmp);
141
142 g_num_shells--;
143
144 if (g_sh_tail == psh)
145 g_sh_tail = psh->prev;
146 else
147 psh->next->prev = psh->prev;
148
149 if (g_sh_head == psh)
150 g_sh_head = psh->next;
151 else
152 psh->prev->next = psh->next;
153
154 if (g_sh_root == psh)
155 g_sh_root = 0;
156
157 shmtx_leave(&g_sh_mtx, &tmp);
158}
159#endif
160
161/**
162 * Destroys the shell instance.
163 *
164 * This will work on partially initialized instances (because I'm lazy).
165 *
166 * @param psh The shell instance to be destroyed.
167 */
168static void sh_destroy(shinstance *psh)
169{
170 memset(psh, 0, sizeof(*psh));
171 free(psh);
172}
173
174/**
175 * Clones an environment vector.
176 *
177 * @returns 0 on success, -1 and errno on failure.
178 * @param dstp Where to store the clone.
179 * @param src The vector to be cloned.
180 */
181static int sh_env_clone(char ***dstp, char **src)
182{
183 char **dst;
184 size_t items;
185
186 /* count first */
187 items = 0;
188 while (src[items])
189 items++;
190
191 /* alloc clone array. */
192 *dstp = dst = malloc(sizeof(*dst) * items + 1);
193 if (!dst)
194 return -1;
195
196 /* copy the items */
197 dst[items] = NULL;
198 while (items-- > 0)
199 {
200 dst[items] = strdup(src[items]);
201 if (!dst[items])
202 {
203 /* allocation error, clean up. */
204 while (dst[++items])
205 free(dst[items]);
206 free(dst);
207 errno = ENOMEM;
208 return -1;
209 }
210 }
211
212 return 0;
213}
214
215/**
216 * Creates a root shell instance.
217 *
218 * @param inherit The shell to inherit from. If NULL inherit from environment and such.
219 * @param argc The argument count.
220 * @param argv The argument vector.
221 * @param envp The environment vector.
222 *
223 * @returns pointer to root shell on success, NULL on failure.
224 */
225shinstance *sh_create_root_shell(shinstance *inherit, int argc, char **argv, char **envp)
226{
227 shinstance *psh;
228 int i;
229
230 /*
231 * The allocations.
232 */
233 psh = calloc(sizeof(*psh), 1);
234 if (psh)
235 {
236 /* Init it enought for sh_destroy() to not get upset */
237 /* ... */
238
239 /* Call the basic initializers. */
240 if ( !sh_env_clone(&psh->shenviron, envp)
241 && !shfile_init(&psh->fdtab, inherit ? &inherit->fdtab : NULL))
242 {
243 /* the special stuff. */
244#ifdef _MSC_VER
245 psh->pid = _getpid();
246#else
247 psh->pid = getpid();
248#endif
249 /*sh_sigemptyset(&psh->sigrestartset);*/
250 for (i = 0; i < NSIG; i++)
251 psh->sigactions[i].sh_handler = SH_SIG_UNK;
252 if (inherit)
253 psh->sigmask = psh->sigmask;
254 else
255 {
256#if defined(SH_PURE_STUB_MODE) || defined(_MSC_VER)
257 sh_sigemptyset(&psh->sigmask);
258#else
259 sigprocmask(SIG_SETMASK, NULL, &psh->sigmask);
260#endif
261 }
262
263 /* memalloc.c */
264 psh->stacknleft = MINSIZE;
265 psh->herefd = -1;
266 psh->stackp = &psh->stackbase;
267 psh->stacknxt = psh->stackbase.space;
268
269 /* input.c */
270 psh->plinno = 1;
271 psh->init_editline = 0;
272 psh->parsefile = &psh->basepf;
273
274 /* output.c */
275 psh->output.bufsize = OUTBUFSIZ;
276 psh->output.fd = 1;
277 psh->output.psh = psh;
278 psh->errout.bufsize = 100;
279 psh->errout.fd = 2;
280 psh->errout.psh = psh;
281 psh->memout.fd = MEM_OUT;
282 psh->memout.psh = psh;
283 psh->out1 = &psh->output;
284 psh->out2 = &psh->errout;
285
286 /* jobs.c */
287 psh->backgndpid = -1;
288#if JOBS
289 psh->curjob = -1;
290#else
291# error asdf
292#endif
293 psh->ttyfd = -1;
294
295 /* link it. */
296 sh_int_link(psh);
297 return psh;
298 }
299
300 sh_destroy(psh);
301 }
302 return NULL;
303}
304
305char *sh_getenv(shinstance *psh, const char *var)
306{
307 size_t len;
308 int i = 0;
309
310 if (!var)
311 return NULL;
312
313 len = strlen(var);
314 i = 0;
315 while (psh->shenviron[i])
316 {
317 const char *item = psh->shenviron[i];
318 if ( !strncmp(item, var, len)
319 && item[len] == '=')
320 return (char *)item + len + 1;
321 }
322
323 return NULL;
324}
325
326char **sh_environ(shinstance *psh)
327{
328 return psh->shenviron;
329}
330
331const char *sh_gethomedir(shinstance *psh, const char *user)
332{
333 const char *ret = NULL;
334
335#ifdef _MSC_VER
336 ret = sh_getenv(psh, "HOME");
337 if (!ret)
338 ret = sh_getenv(psh, "USERPROFILE");
339#else
340 struct passwd *pwd = getpwnam(user); /** @todo use getpwdnam_r */
341 (void)psh;
342 ret = pwd ? pwd->pw_dir : NULL;
343#endif
344
345 return ret;
346}
347
348/**
349 * Lazy initialization of a signal state, globally.
350 *
351 * @param psh The shell doing the lazy work.
352 * @param signo The signal (valid).
353 */
354static void sh_int_lazy_init_sigaction(shinstance *psh, int signo)
355{
356 if (psh->sigactions[signo].sh_handler == SH_SIG_UNK)
357 {
358 shmtxtmp tmp;
359 shmtx_enter(&g_sh_mtx, &tmp);
360
361 if (psh->sigactions[signo].sh_handler == SH_SIG_UNK)
362 {
363 shsigaction_t shold;
364 shinstance *cur;
365#ifndef _MSC_VER
366 struct sigaction old;
367 if (!sigaction(signo, NULL, &old))
368 {
369 /* convert */
370 shold.sh_flags = old.sa_flags;
371 shold.sh_mask = old.sa_mask;
372 if (old.sa_handler == SIG_DFL)
373 shold.sh_handler = SH_SIG_DFL;
374 else
375 {
376 assert(old.sa_handler == SIG_IGN);
377 shold.sh_handler = SH_SIG_IGN;
378 }
379 }
380 else
381#endif
382 {
383 /* fake */
384#ifndef _MSC_VER
385 assert(0);
386 old.sa_handler = SIG_DFL;
387 old.sa_flags = 0;
388 sigemptyset(&shold.sh_mask);
389 sigaddset(&shold.sh_mask, signo);
390#endif
391 shold.sh_flags = 0;
392 sh_sigemptyset(&shold.sh_mask);
393 sh_sigaddset(&shold.sh_mask, signo);
394 shold.sh_handler = SH_SIG_DFL;
395 }
396
397 /* update globals */
398#ifndef _MSC_VER
399 g_sig_state[signo].sa = old;
400#else
401 g_sig_state[signo].sa.sa_handler = SIG_DFL;
402 g_sig_state[signo].sa.sa_flags = 0;
403 g_sig_state[signo].sa.sa_mask = shold.sh_mask;
404#endif
405 TRACE2((psh, "sh_int_lazy_init_sigaction: signo=%d:%s sa_handler=%p sa_flags=%#x\n",
406 signo, sys_signame[signo], g_sig_state[signo].sa.sa_handler, g_sig_state[signo].sa.sa_flags));
407
408 /* update all shells */
409 for (cur = g_sh_head; cur; cur = cur->next)
410 {
411 assert(cur->sigactions[signo].sh_handler == SH_SIG_UNK);
412 cur->sigactions[signo] = shold;
413 }
414 }
415
416 shmtx_leave(&g_sh_mtx, &tmp);
417 }
418}
419
420/**
421 * Perform the default signal action on the shell.
422 *
423 * @param psh The shell instance.
424 * @param signo The signal.
425 */
426static void sh_sig_do_default(shinstance *psh, int signo)
427{
428 /** @todo */
429}
430
431/**
432 * Deliver a signal to a shell.
433 *
434 * @param psh The shell instance.
435 * @param pshDst The shell instance to signal.
436 * @param signo The signal.
437 * @param locked Whether we're owning the lock or not.
438 */
439static void sh_sig_do_signal(shinstance *psh, shinstance *pshDst, int signo, int locked)
440{
441 shsig_t pfn = pshDst->sigactions[signo].sh_handler;
442 if (pfn == SH_SIG_UNK)
443 {
444 sh_int_lazy_init_sigaction(pshDst, signo);
445 pfn = pshDst->sigactions[signo].sh_handler;
446 }
447
448 if (pfn == SH_SIG_DFL)
449 sh_sig_do_default(pshDst, signo);
450 else if (pfn == SH_SIG_IGN)
451 /* ignore it */;
452 else
453 {
454 assert(pfn != SH_SIG_ERR);
455 pfn(pshDst, signo);
456 }
457 (void)locked;
458}
459
460/**
461 * Handler for external signals.
462 *
463 * @param signo The signal.
464 */
465static void sh_sig_common_handler(int signo)
466{
467 shinstance *psh;
468
469 fprintf(stderr, "sh_sig_common_handler: signo=%d:%s\n", signo, sys_signame[signo]);
470
471 /*
472 * No need to take locks if there is only one shell.
473 * Since this will be the initial case, just avoid the deadlock
474 * hell for a litte while...
475 */
476 if (g_num_shells <= 1)
477 {
478 psh = g_sh_head;
479 if (psh)
480 sh_sig_do_signal(NULL, psh, signo, 0 /* no lock */);
481 }
482 else
483 {
484 shmtxtmp tmp;
485 shmtx_enter(&g_sh_mtx, &tmp);
486
487 /** @todo signal focus chain or something? Atm there will only be one shell,
488 * so it's not really important until we go threaded for real... */
489 psh = g_sh_tail;
490 while (psh != NULL)
491 {
492 sh_sig_do_signal(NULL, psh, signo, 1 /* locked */);
493 psh = psh->prev;
494 }
495
496 shmtx_leave(&g_sh_mtx, &tmp);
497 }
498}
499
500int sh_sigaction(shinstance *psh, int signo, const struct shsigaction *newp, struct shsigaction *oldp)
501{
502 if (newp)
503 TRACE2((psh, "sh_sigaction: signo=%d:%s newp=%p:{.sh_handler=%p, .sh_flags=%#x} oldp=%p\n",
504 signo, sys_signame[signo], newp, newp->sh_handler, newp->sh_flags, oldp));
505 else
506 TRACE2((psh, "sh_sigaction: signo=%d:%s newp=NULL oldp=%p\n", signo, sys_signame[signo], oldp));
507
508 /*
509 * Input validation.
510 */
511 if (signo >= NSIG || signo <= 0)
512 {
513 errno = EINVAL;
514 return -1;
515 }
516
517#ifdef SH_PURE_STUB_MODE
518 return -1;
519#else
520
521 /*
522 * Make sure our data is correct.
523 */
524 sh_int_lazy_init_sigaction(psh, signo);
525
526 /*
527 * Get the old one if requested.
528 */
529 if (oldp)
530 *oldp = psh->sigactions[signo];
531
532 /*
533 * Set the new one if it has changed.
534 *
535 * This will be attempted coordinated with the other signal handlers so
536 * that we can arrive at a common denominator.
537 */
538 if ( newp
539 && memcmp(&psh->sigactions[signo], newp, sizeof(*newp)))
540 {
541 shmtxtmp tmp;
542 shmtx_enter(&g_sh_mtx, &tmp);
543
544 /* Undo the accounting for the current entry. */
545 if (psh->sigactions[signo].sh_handler == SH_SIG_IGN)
546 g_sig_state[signo].num_ignore--;
547 else if (psh->sigactions[signo].sh_handler != SH_SIG_DFL)
548 g_sig_state[signo].num_specific--;
549 if (psh->sigactions[signo].sh_flags & SA_RESTART)
550 g_sig_state[signo].num_restart--;
551
552 /* Set the new entry. */
553 psh->sigactions[signo] = *newp;
554
555 /* Add the bits for the new action entry. */
556 if (psh->sigactions[signo].sh_handler == SH_SIG_IGN)
557 g_sig_state[signo].num_ignore++;
558 else if (psh->sigactions[signo].sh_handler != SH_SIG_DFL)
559 g_sig_state[signo].num_specific++;
560 if (psh->sigactions[signo].sh_flags & SA_RESTART)
561 g_sig_state[signo].num_restart++;
562
563 /*
564 * Calc new common action.
565 *
566 * This is quit a bit ASSUMPTIVE about the limited use. We will not
567 * bother synching the mask, and we pretend to care about SA_RESTART.
568 * The only thing we really actually care about is the sh_handler.
569 *
570 * On second though, it's possible we should just tie this to the root
571 * shell since it only really applies to external signal ...
572 */
573 if ( g_sig_state[signo].num_specific
574 || g_sig_state[signo].num_ignore != g_num_shells)
575 g_sig_state[signo].sa.sa_handler = sh_sig_common_handler;
576 else if (g_sig_state[signo].num_ignore)
577 g_sig_state[signo].sa.sa_handler = SIG_IGN;
578 else
579 g_sig_state[signo].sa.sa_handler = SIG_DFL;
580 g_sig_state[signo].sa.sa_flags = psh->sigactions[signo].sh_flags & SA_RESTART;
581
582 TRACE2((psh, "sh_sigaction: setting signo=%d:%s to {.sa_handler=%p, .sa_flags=%#x}\n",
583 signo, sys_signame[signo], g_sig_state[signo].sa.sa_handler, g_sig_state[signo].sa.sa_flags));
584# ifdef _MSC_VER
585 if (signal(signo, g_sig_state[signo].sa.sa_handler) == SIG_ERR)
586# else
587 if (sigaction(signo, &g_sig_state[signo].sa, NULL))
588# endif
589 assert(0);
590
591 shmtx_leave(&g_sh_mtx, &tmp);
592 }
593
594 return 0;
595#endif
596}
597
598shsig_t sh_signal(shinstance *psh, int signo, shsig_t handler)
599{
600 shsigaction_t sa;
601 shsig_t ret;
602
603 /*
604 * Implementation using sh_sigaction.
605 */
606 if (sh_sigaction(psh, signo, NULL, &sa))
607 return SH_SIG_ERR;
608
609 ret = sa.sh_handler;
610 sa.sh_flags &= SA_RESTART;
611 sa.sh_handler = handler;
612 sh_sigemptyset(&sa.sh_mask);
613 sh_sigaddset(&sa.sh_mask, signo); /* ?? */
614 if (sh_sigaction(psh, signo, &sa, NULL))
615 return SH_SIG_ERR;
616
617 return ret;
618}
619
620int sh_siginterrupt(shinstance *psh, int signo, int interrupt)
621{
622 shsigaction_t sa;
623 int oldflags = 0;
624
625 /*
626 * Implementation using sh_sigaction.
627 */
628 if (sh_sigaction(psh, signo, NULL, &sa))
629 return -1;
630 oldflags = sa.sh_flags;
631 if (interrupt)
632 sa.sh_flags &= ~SA_RESTART;
633 else
634 sa.sh_flags |= ~SA_RESTART;
635 if (!((oldflags ^ sa.sh_flags) & SA_RESTART))
636 return 0; /* unchanged. */
637
638 return sh_sigaction(psh, signo, &sa, NULL);
639}
640
641void sh_sigemptyset(shsigset_t *setp)
642{
643 memset(setp, 0, sizeof(*setp));
644}
645
646void sh_sigfillset(shsigset_t *setp)
647{
648 memset(setp, 0xff, sizeof(*setp));
649}
650
651void sh_sigaddset(shsigset_t *setp, int signo)
652{
653#ifdef _MSC_VER
654 *setp |= 1U << signo;
655#else
656 sigaddset(setp, signo);
657#endif
658}
659
660void sh_sigdelset(shsigset_t *setp, int signo)
661{
662#ifdef _MSC_VER
663 *setp &= ~(1U << signo);
664#else
665 sigdelset(setp, signo);
666#endif
667}
668
669int sh_sigismember(shsigset_t const *setp, int signo)
670{
671#ifdef _MSC_VER
672 return !!(*setp & (1U << signo));
673#else
674 return !!sigismember(setp, signo);
675#endif
676}
677
678int sh_sigprocmask(shinstance *psh, int operation, shsigset_t const *newp, shsigset_t *oldp)
679{
680 int rc;
681
682 if ( operation != SIG_BLOCK
683 && operation != SIG_UNBLOCK
684 && operation != SIG_SETMASK)
685 {
686 errno = EINVAL;
687 return -1;
688 }
689
690#if (defined(SH_STUB_MODE) || defined(SH_FORKED_MODE)) && !defined(_MSC_VER)
691 rc = sigprocmask(operation, newp, oldp);
692 if (!rc && newp)
693 psh->sigmask = *newp;
694
695#else
696 if (oldp)
697 *oldp = psh->sigmask;
698 if (newp)
699 {
700 /* calc the new mask */
701 shsigset_t mask = psh->sigmask;
702 switch (operation)
703 {
704 case SIG_BLOCK:
705 for (rc = 0; rc < NSIG; rc++)
706 if (sh_sigismember(newp, rc))
707 sh_sigaddset(&mask, rc);
708 break;
709 case SIG_UNBLOCK:
710 for (rc = 0; rc < NSIG; rc++)
711 if (sh_sigismember(newp, rc))
712 sh_sigdelset(&mask, rc);
713 break;
714 case SIG_SETMASK:
715 mask = *newp;
716 break;
717 }
718
719# if defined(SH_STUB_MODE) || defined(_MSC_VER)
720 rc = 0;
721# else
722 rc = sigprocmask(operation, &mask, NULL);
723 if (!rc)
724# endif
725 psh->sigmask = mask;
726 }
727
728#endif
729 return rc;
730}
731
732void sh_abort(shinstance *psh)
733{
734 shsigset_t set;
735 TRACE2((psh, "sh_abort\n"));
736
737 /* block other async signals */
738 sh_sigfillset(&set);
739 sh_sigdelset(&set, SIGABRT);
740 sh_sigprocmask(psh, SIG_SETMASK, &set, NULL);
741
742 sh_sig_do_signal(psh, psh, SIGABRT, 0 /* no lock */);
743
744 /** @todo die in a nicer manner. */
745 *(char *)1 = 3;
746
747 TRACE2((psh, "sh_abort returns!\n"));
748 (void)psh;
749 abort();
750}
751
752void sh_raise_sigint(shinstance *psh)
753{
754 TRACE2((psh, "sh_raise(SIGINT)\n"));
755
756 sh_sig_do_signal(psh, psh, SIGINT, 0 /* no lock */);
757
758 TRACE2((psh, "sh_raise(SIGINT) returns\n"));
759}
760
761int sh_kill(shinstance *psh, pid_t pid, int signo)
762{
763 shinstance *pshDst;
764 shmtxtmp tmp;
765 int rc;
766
767 /*
768 * Self or any of the subshells?
769 */
770 shmtx_enter(&g_sh_mtx, &tmp);
771
772 pshDst = g_sh_tail;
773 while (pshDst != NULL)
774 {
775 if (pshDst->pid == pid)
776 {
777 TRACE2((psh, "sh_kill(%d, %d): pshDst=%p\n", pid, signo, pshDst));
778 sh_sig_do_signal(psh, pshDst, signo, 1 /* locked */);
779
780 shmtx_leave(&g_sh_mtx, &tmp);
781 return 0;
782 }
783 pshDst = pshDst->prev;
784 }
785
786 shmtx_leave(&g_sh_mtx, &tmp);
787
788 /*
789 * Some other process, call kill where possible
790 */
791#ifdef SH_PURE_STUB_MODE
792 rc = -1;
793
794#elif defined(SH_STUB_MODE) || defined(SH_FORKED_MODE)
795# ifdef _MSC_VER
796 errno = ENOSYS;
797 rc = -1;
798# else
799 fprintf(stderr, "kill(%d, %d)\n", pid, signo);
800 rc = kill(pid, signo);
801# endif
802
803#else
804#endif
805
806 TRACE2((psh, "sh_kill(%d, %d) -> %d [%d]\n", pid, signo, rc, errno));
807 return rc;
808}
809
810int sh_killpg(shinstance *psh, pid_t pgid, int signo)
811{
812 int rc;
813
814#ifdef SH_PURE_STUB_MODE
815 rc = -1;
816
817#elif defined(SH_STUB_MODE)
818# ifdef _MSC_VER
819 errno = ENOSYS;
820 rc = -1;
821# else
822 //fprintf(stderr, "killpg(%d, %d)\n", pgid, signo);
823 rc = killpg(pgid, signo);
824# endif
825
826#else
827#endif
828
829 TRACE2((psh, "sh_killpg(%d, %d) -> %d [%d]\n", pgid, signo, rc, errno));
830 (void)psh;
831 return rc;
832}
833
834clock_t sh_times(shinstance *psh, shtms *tmsp)
835{
836#ifdef SH_PURE_STUB_MODE
837 return 0;
838
839#elif defined(SH_STUB_MODE) || defined(SH_FORKED_MODE)
840 (void)psh;
841# ifdef _MSC_VER
842 errno = ENOSYS;
843 return (clock_t)-1;
844# else
845 return times(tmsp);
846# endif
847
848#else
849#endif
850}
851
852int sh_sysconf_clk_tck(void)
853{
854#ifdef SH_PURE_STUB_MODE
855 return 1;
856#else
857# ifdef _MSC_VER
858 return CLK_TCK;
859# else
860 return sysconf(_SC_CLK_TCK);
861# endif
862#endif
863}
864
865pid_t sh_fork(shinstance *psh)
866{
867 pid_t pid;
868 TRACE2((psh, "sh_fork\n"));
869
870#ifdef SH_PURE_STUB_MODE
871 pid = -1;
872
873#elif defined(SH_STUB_MODE) || defined(SH_FORKED_MODE)
874# ifdef _MSC_VER
875# ifdef SH_FORKED_MODE
876 /** @todo */
877 *(char *)1 = 0x1;
878# else
879 pid = -1;
880 errno = ENOSYS;
881# endif
882# else
883 pid = fork();
884# endif
885
886#else
887
888#endif
889
890 TRACE2((psh, "sh_fork -> %d [%d]\n", pid, errno));
891 (void)psh;
892 return pid;
893}
894
895pid_t sh_waitpid(shinstance *psh, pid_t pid, int *statusp, int flags)
896{
897 pid_t pidret;
898
899 *statusp = 0;
900#ifdef SH_PURE_STUB_MODE
901 pidret = -1;
902
903#elif defined(SH_STUB_MODE) || defined(SH_FORKED_MODE)
904# ifdef _MSC_VER
905 pidret = -1;
906 errno = ENOSYS;
907# else
908 pidret = waitpid(pid, statusp, flags);
909# endif
910
911#else
912#endif
913
914 TRACE2((psh, "waitpid(%d, %p, %#x) -> %d [%d] *statusp=%#x (rc=%d)\n", pid, statusp, flags,
915 pidret, errno, *statusp, WEXITSTATUS(*statusp)));
916 (void)psh;
917 return pidret;
918}
919
920void sh__exit(shinstance *psh, int rc)
921{
922 TRACE2((psh, "sh__exit(%d)\n", rc));
923 (void)psh;
924
925#ifdef SH_PURE_STUB_MODE
926 return -1;
927
928#elif defined(SH_STUB_MODE) || defined(SH_FORKED_MODE)
929 _exit(rc);
930
931#else
932#endif
933}
934
935int sh_execve(shinstance *psh, const char *exe, const char * const *argv, const char * const *envp)
936{
937#ifdef _MSC_VER
938 intptr_t rc;
939#else
940 int rc;
941#endif
942
943#ifdef DEBUG
944 /* log it all */
945 TRACE2((psh, "sh_execve(%p:{%s}, %p, %p}\n", exe, exe, argv, envp));
946 for (rc = 0; argv[rc]; rc++)
947 TRACE2((psh, " argv[%d]=%p:{%s}\n", rc, argv[rc], argv[rc]));
948#endif
949
950 if (!envp)
951 envp = sh_environ(psh);
952
953#ifdef SH_PURE_STUB_MODE
954 rc = -1;
955
956#elif defined(SH_STUB_MODE) || defined(SH_FORKED_MODE)
957# ifdef _MSC_VER
958 rc = _spawnve(_P_WAIT, exe, (char **)argv, (char **)envp);
959# else
960 rc = execve(exe, (char **)argv, (char **)envp);
961# endif
962
963#else
964#endif
965
966 TRACE2((psh, "sh_execve -> %d [%d]\n", rc, errno));
967 (void)psh;
968 return (int)rc;
969}
970
971uid_t sh_getuid(shinstance *psh)
972{
973#ifdef SH_PURE_STUB_MODE
974 uid_t uid = 0;
975
976#elif defined(SH_STUB_MODE) || defined(SH_FORKED_MODE)
977# ifdef _MSC_VER
978 uid_t uid = 0;
979# else
980 uid_t uid = getuid();
981# endif
982
983#else
984#endif
985
986 TRACE2((psh, "sh_getuid() -> %d [%d]\n", uid, errno));
987 (void)psh;
988 return uid;
989}
990
991uid_t sh_geteuid(shinstance *psh)
992{
993#ifdef SH_PURE_STUB_MODE
994 uid_t euid = 0;
995
996#elif defined(SH_STUB_MODE) || defined(SH_FORKED_MODE)
997# ifdef _MSC_VER
998 uid_t euid = 0;
999# else
1000 uid_t euid = geteuid();
1001# endif
1002
1003#else
1004#endif
1005
1006 TRACE2((psh, "sh_geteuid() -> %d [%d]\n", euid, errno));
1007 (void)psh;
1008 return euid;
1009}
1010
1011gid_t sh_getgid(shinstance *psh)
1012{
1013#ifdef SH_PURE_STUB_MODE
1014 gid_t gid = 0;
1015
1016#elif defined(SH_STUB_MODE) || defined(SH_FORKED_MODE)
1017# ifdef _MSC_VER
1018 gid_t gid = 0;
1019# else
1020 gid_t gid = getgid();
1021# endif
1022
1023#else
1024#endif
1025
1026 TRACE2((psh, "sh_getgid() -> %d [%d]\n", gid, errno));
1027 (void)psh;
1028 return gid;
1029}
1030
1031gid_t sh_getegid(shinstance *psh)
1032{
1033#ifdef SH_PURE_STUB_MODE
1034 gid_t egid = 0;
1035
1036#elif defined(SH_STUB_MODE) || defined(SH_FORKED_MODE)
1037# ifdef _MSC_VER
1038 gid_t egid = 0;
1039# else
1040 gid_t egid = getegid();
1041# endif
1042
1043#else
1044#endif
1045
1046 TRACE2((psh, "sh_getegid() -> %d [%d]\n", egid, errno));
1047 (void)psh;
1048 return egid;
1049}
1050
1051pid_t sh_getpid(shinstance *psh)
1052{
1053 pid_t pid;
1054
1055#ifdef SH_PURE_STUB_MODE
1056 pid = 0;
1057
1058#elif defined(SH_STUB_MODE) || defined(SH_FORKED_MODE)
1059# ifdef _MSC_VER
1060 pid = _getpid();
1061# else
1062 pid = getpid();
1063# endif
1064#else
1065#endif
1066
1067 (void)psh;
1068 return pid;
1069}
1070
1071pid_t sh_getpgrp(shinstance *psh)
1072{
1073#ifdef SH_PURE_STUB_MODE
1074 pid_t pgrp = 0;
1075
1076#elif defined(SH_STUB_MODE) || defined(SH_FORKED_MODE)
1077# ifdef _MSC_VER
1078 pid_t pgrp = _getpid();
1079# else
1080 pid_t pgrp = getpgrp();
1081# endif
1082
1083#else
1084#endif
1085
1086 TRACE2((psh, "sh_getpgrp() -> %d [%d]\n", pgrp, errno));
1087 (void)psh;
1088 return pgrp;
1089}
1090
1091pid_t sh_getpgid(shinstance *psh, pid_t pid)
1092{
1093#ifdef SH_PURE_STUB_MODE
1094 pid_t pgid = pid;
1095
1096#elif defined(SH_STUB_MODE) || defined(SH_FORKED_MODE)
1097# ifdef _MSC_VER
1098 pid_t pgid = pid;
1099# else
1100 pid_t pgid = getpgid(pid);
1101# endif
1102
1103#else
1104#endif
1105
1106 TRACE2((psh, "sh_getpgid(%d) -> %d [%d]\n", pid, pgid, errno));
1107 (void)psh;
1108 return pgid;
1109}
1110
1111int sh_setpgid(shinstance *psh, pid_t pid, pid_t pgid)
1112{
1113#ifdef SH_PURE_STUB_MODE
1114 int rc = -1;
1115
1116#elif defined(SH_STUB_MODE) || defined(SH_FORKED_MODE)
1117# ifdef _MSC_VER
1118 int rc = -1;
1119 errno = ENOSYS;
1120# else
1121 int rc = setpgid(pid, pgid);
1122# endif
1123
1124#else
1125#endif
1126
1127 TRACE2((psh, "sh_setpgid(%d, %d) -> %d [%d]\n", pid, pgid, rc, errno));
1128 (void)psh;
1129 return rc;
1130}
1131
1132pid_t sh_tcgetpgrp(shinstance *psh, int fd)
1133{
1134 pid_t pgrp;
1135
1136#ifdef SH_PURE_STUB_MODE
1137 pgrp = -1;
1138
1139#elif defined(SH_STUB_MODE) || defined(SH_FORKED_MODE)
1140# ifdef _MSC_VER
1141 pgrp = -1;
1142 errno = ENOSYS;
1143# else
1144 pgrp = tcgetpgrp(fd);
1145# endif
1146
1147#else
1148#endif
1149
1150 TRACE2((psh, "sh_tcgetpgrp(%d) -> %d [%d]\n", fd, pgrp, errno));
1151 (void)psh;
1152 return pgrp;
1153}
1154
1155int sh_tcsetpgrp(shinstance *psh, int fd, pid_t pgrp)
1156{
1157 int rc;
1158 TRACE2((psh, "sh_tcsetpgrp(%d, %d)\n", fd, pgrp));
1159
1160#ifdef SH_PURE_STUB_MODE
1161 rc = -1;
1162
1163#elif defined(SH_STUB_MODE) || defined(SH_FORKED_MODE)
1164# ifdef _MSC_VER
1165 rc = -1;
1166 errno = ENOSYS;
1167# else
1168 rc = tcsetpgrp(fd, pgrp);
1169# endif
1170
1171#else
1172#endif
1173
1174 TRACE2((psh, "sh_tcsetpgrp(%d, %d) -> %d [%d]\n", fd, pgrp, rc, errno));
1175 (void)psh;
1176 return rc;
1177}
1178
1179int sh_getrlimit(shinstance *psh, int resid, shrlimit *limp)
1180{
1181#ifdef SH_PURE_STUB_MODE
1182 int rc = -1;
1183
1184#elif defined(SH_STUB_MODE) || defined(SH_FORKED_MODE)
1185# ifdef _MSC_VER
1186 int rc = -1;
1187 errno = ENOSYS;
1188# else
1189 int rc = getrlimit(resid, limp);
1190# endif
1191
1192#else
1193 /* returned the stored limit */
1194#endif
1195
1196 TRACE2((psh, "sh_getrlimit(%d, %p) -> %d [%d] {%ld,%ld}\n",
1197 resid, limp, rc, errno, (long)limp->rlim_cur, (long)limp->rlim_max));
1198 (void)psh;
1199 return rc;
1200}
1201
1202int sh_setrlimit(shinstance *psh, int resid, const shrlimit *limp)
1203{
1204#ifdef SH_PURE_STUB_MODE
1205 int rc = -1;
1206
1207#elif defined(SH_STUB_MODE) || defined(SH_FORKED_MODE)
1208# ifdef _MSC_VER
1209 int rc = -1;
1210 errno = ENOSYS;
1211# else
1212 int rc = setrlimit(resid, limp);
1213# endif
1214
1215#else
1216 /* if max(shell) < limp; then setrlimit; fi
1217 if success; then store limit for later retrival and maxing. */
1218
1219#endif
1220
1221 TRACE2((psh, "sh_setrlimit(%d, %p:{%ld,%ld}) -> %d [%d]\n",
1222 resid, limp, (long)limp->rlim_cur, (long)limp->rlim_max, rc, errno));
1223 (void)psh;
1224 return rc;
1225}
1226
Note: See TracBrowser for help on using the repository browser.