4 * The shell instance methods.
6 * Copyright (c) 2007-2009 knut st. osmundsen <bird-kBuild-spamix@anduin.net>
9 * This file is part of kBuild.
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.
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.
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
27 /*******************************************************************************
29 *******************************************************************************/
36 extern char **environ
;
38 #include "shinstance.h"
41 /*******************************************************************************
43 *******************************************************************************/
44 /** The mutex protecting the the globals and some shell instance members (sigs). */
45 static shmtx g_sh_mtx
;
46 /** The root shell instance. */
47 static shinstance
*g_sh_root
;
48 /** The first shell instance. */
49 static shinstance
*g_sh_head
;
50 /** The last shell instance. */
51 static shinstance
*g_sh_tail
;
52 /** The number of shells. */
53 static int g_num_shells
;
54 /** Per signal state for determining a common denominator.
55 * @remarks defaults and unmasked actions aren't counted. */
58 /** The current signal action. */
64 void (*sa_handler
)(int);
69 /** The number of restarts (siginterrupt / SA_RESTART). */
71 /** The number of ignore handlers. */
73 /** The number of specific handlers. */
75 /** The number of threads masking it. */
81 typedef struct shmtxtmp
{ int i
; } shmtxtmp
;
83 int shmtx_init(shmtx
*pmtx
)
89 void shmtx_delete(shmtx
*pmtx
)
94 void shmtx_enter(shmtx
*pmtx
, shmtxtmp
*ptmp
)
100 void shmtx_leave(shmtx
*pmtx
, shmtxtmp
*ptmp
)
108 * Links the shell instance.
110 * @param psh The shell.
112 static void sh_int_link(shinstance
*psh
)
115 shmtx_enter(&g_sh_mtx
, &tmp
);
121 psh
->prev
= g_sh_tail
;
123 g_sh_tail
->next
= psh
;
125 g_sh_tail
= g_sh_head
= psh
;
130 shmtx_leave(&g_sh_mtx
, &tmp
);
135 * Unlink the shell instance.
137 * @param psh The shell.
139 static void sh_int_unlink(shinstance
*psh
)
142 shmtx_enter(&g_sh_mtx
, &tmp
);
146 if (g_sh_tail
== psh
)
147 g_sh_tail
= psh
->prev
;
149 psh
->next
->prev
= psh
->prev
;
151 if (g_sh_head
== psh
)
152 g_sh_head
= psh
->next
;
154 psh
->prev
->next
= psh
->next
;
156 if (g_sh_root
== psh
)
159 shmtx_leave(&g_sh_mtx
, &tmp
);
164 * Creates a root shell instance.
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.
170 * @returns pointer to root shell on success, NULL on failure.
172 shinstance
*sh_create_root_shell(shinstance
*inherit
, int argc
, char **argv
)
177 psh
= calloc(sizeof(*psh
), 1);
180 /* the special stuff. */
182 psh
->pid
= _getpid();
186 /*sh_sigemptyset(&psh->sigrestartset);*/
187 for (i
= 0; i
< NSIG
; i
++)
188 psh
->sigactions
[i
].sh_handler
= SH_SIG_UNK
;
191 psh
->stacknleft
= MINSIZE
;
193 psh
->stackp
= &psh
->stackbase
;
194 psh
->stacknxt
= psh
->stackbase
.space
;
198 psh
->init_editline
= 0;
199 psh
->parsefile
= &psh
->basepf
;
202 psh
->output
.bufsize
= OUTBUFSIZ
;
204 psh
->output
.psh
= psh
;
205 psh
->errout
.bufsize
= 100;
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
;
214 psh
->backgndpid
= -1;
230 char *sh_getenv(shinstance
*psh
, const char *var
)
232 #ifdef SH_PURE_STUB_MODE
234 #elif defined(SH_STUB_MODE)
241 char **sh_environ(shinstance
*psh
)
243 #ifdef SH_PURE_STUB_MODE
244 static char *s_null
[2] = {0,0};
246 #elif defined(SH_STUB_MODE)
253 const char *sh_gethomedir(shinstance
*psh
, const char *user
)
255 #ifdef SH_PURE_STUB_MODE
257 #elif defined(SH_STUB_MODE)
262 struct passwd
*pwd
= getpwnam(user
);
263 return pwd
? pwd
->pw_dir
: NULL
;
270 * Lazy initialization of a signal state, globally.
272 * @param psh The shell doing the lazy work.
273 * @param signo The signal (valid).
275 static void sh_int_lazy_init_sigaction(shinstance
*psh
, int signo
)
277 if (psh
->sigactions
[signo
].sh_handler
== SH_SIG_UNK
)
280 shmtx_enter(&g_sh_mtx
, &tmp
);
282 if (psh
->sigactions
[signo
].sh_handler
== SH_SIG_UNK
)
287 struct sigaction old
;
288 if (!sigaction(signo
, NULL
, &old
))
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
;
297 assert(old
.sa_handler
== SIG_IGN
);
298 shold
.sh_handler
= SH_SIG_IGN
;
307 old
.sa_handler
= SIG_DFL
;
309 sigemptyset(&shold
.sh_mask
);
310 sigaddset(&shold
.sh_mask
, signo
);
313 sh_sigemptyset(&shold
.sh_mask
);
314 sh_sigaddset(&shold
.sh_mask
, signo
);
315 shold
.sh_handler
= SH_SIG_DFL
;
320 g_sig_state
[signo
].sa
= old
;
322 g_sig_state
[signo
].sa
.sa_handler
= SIG_DFL
;
323 g_sig_state
[signo
].sa
.sa_flags
= 0;
324 g_sig_state
[signo
].sa
.sa_mask
= shold
.sh_mask
;
326 TRACE2((psh
, "sh_int_lazy_init_sigaction: signo=%d:%s sa_handler=%p sa_flags=%#x\n",
327 signo
, sys_signame
[signo
], g_sig_state
[signo
].sa
.sa_handler
, g_sig_state
[signo
].sa
.sa_flags
));
329 /* update all shells */
330 for (cur
= g_sh_head
; cur
; cur
= cur
->next
)
332 assert(cur
->sigactions
[signo
].sh_handler
== SH_SIG_UNK
);
333 cur
->sigactions
[signo
] = shold
;
337 shmtx_leave(&g_sh_mtx
, &tmp
);
343 * Handler for external signals.
345 * @param signo The signal.
347 static void sh_sig_common_handler(int signo
)
349 fprintf(stderr
, "sh_sig_common_handler: signo=%d:%s\n", signo
, sys_signame
[signo
]);
353 int sh_sigaction(shinstance
*psh
, int signo
, const struct shsigaction
*newp
, struct shsigaction
*oldp
)
356 TRACE2((psh
, "sh_sigaction: signo=%d:%s newp=%p:{.sh_handler=%p, .sh_flags=%#x} oldp=%p\n",
357 signo
, sys_signame
[signo
], newp
, newp
->sh_handler
, newp
->sh_flags
, oldp
));
359 TRACE2((psh
, "sh_sigaction: signo=%d:%s newp=NULL oldp=%p\n", signo
, sys_signame
[signo
], oldp
));
364 if (signo
>= NSIG
|| signo
<= 0)
370 #ifdef SH_PURE_STUB_MODE
375 * Make sure our data is correct.
377 sh_int_lazy_init_sigaction(psh
, signo
);
380 * Get the old one if requested.
383 *oldp
= psh
->sigactions
[signo
];
386 * Set the new one if it has changed.
388 * This will be attempted coordinated with the other signal handlers so
389 * that we can arrive at a common denominator.
392 && memcmp(&psh
->sigactions
[signo
], newp
, sizeof(*newp
)))
395 shmtx_enter(&g_sh_mtx
, &tmp
);
397 /* Undo the accounting for the current entry. */
398 if (psh
->sigactions
[signo
].sh_handler
== SH_SIG_IGN
)
399 g_sig_state
[signo
].num_ignore
--;
400 else if (psh
->sigactions
[signo
].sh_handler
!= SH_SIG_DFL
)
401 g_sig_state
[signo
].num_specific
--;
402 if (psh
->sigactions
[signo
].sh_flags
& SA_RESTART
)
403 g_sig_state
[signo
].num_restart
--;
405 /* Set the new entry. */
406 psh
->sigactions
[signo
] = *newp
;
408 /* Add the bits for the new action entry. */
409 if (psh
->sigactions
[signo
].sh_handler
== SH_SIG_IGN
)
410 g_sig_state
[signo
].num_ignore
++;
411 else if (psh
->sigactions
[signo
].sh_handler
!= SH_SIG_DFL
)
412 g_sig_state
[signo
].num_specific
++;
413 if (psh
->sigactions
[signo
].sh_flags
& SA_RESTART
)
414 g_sig_state
[signo
].num_restart
++;
417 * Calc new common action.
419 * This is quit a bit ASSUMPTIVE about the limited use. We will not
420 * bother synching the mask, and we pretend to care about SA_RESTART.
421 * The only thing we really actually care about is the sh_handler.
423 * On second though, it's possible we should just tie this to the root
424 * shell since it only really applies to external signal ...
426 if ( g_sig_state
[signo
].num_specific
427 || g_sig_state
[signo
].num_ignore
!= g_num_shells
)
428 g_sig_state
[signo
].sa
.sa_handler
= sh_sig_common_handler
;
429 else if (g_sig_state
[signo
].num_ignore
)
430 g_sig_state
[signo
].sa
.sa_handler
= SIG_IGN
;
432 g_sig_state
[signo
].sa
.sa_handler
= SIG_DFL
;
433 g_sig_state
[signo
].sa
.sa_flags
= psh
->sigactions
[signo
].sh_flags
& SA_RESTART
;
435 TRACE2((psh
, "sh_sigaction: setting signo=%d:%s to {.sa_handler=%p, .sa_flags=%#x}\n",
436 signo
, sys_signame
[signo
], g_sig_state
[signo
].sa
.sa_handler
, g_sig_state
[signo
].sa
.sa_flags
));
438 if (signal(signo
, g_sig_state
[signo
].sa
.sa_handler
) == SIG_ERR
)
440 if (sigaction(signo
, &g_sig_state
[signo
].sa
, NULL
))
444 shmtx_leave(&g_sh_mtx
, &tmp
);
451 shsig_t
sh_signal(shinstance
*psh
, int signo
, shsig_t handler
)
457 * Implementation using sh_sigaction.
459 if (sh_sigaction(psh
, signo
, NULL
, &sa
))
463 sa
.sh_flags
&= SA_RESTART
;
464 sa
.sh_handler
= handler
;
465 sh_sigemptyset(&sa
.sh_mask
);
466 sh_sigaddset(&sa
.sh_mask
, signo
); /* ?? */
467 if (sh_sigaction(psh
, signo
, &sa
, NULL
))
473 int sh_siginterrupt(shinstance
*psh
, int signo
, int interrupt
)
479 * Implementation using sh_sigaction.
481 if (sh_sigaction(psh
, signo
, NULL
, &sa
))
483 oldflags
= sa
.sh_flags
;
485 sa
.sh_flags
&= ~SA_RESTART
;
487 sa
.sh_flags
|= ~SA_RESTART
;
488 if (!((oldflags
^ sa
.sh_flags
) & SA_RESTART
))
489 return 0; /* unchanged. */
491 return sh_sigaction(psh
, signo
, &sa
, NULL
);
494 void sh_sigemptyset(shsigset_t
*setp
)
496 memset(setp
, 0, sizeof(*setp
));
499 void sh_sigaddset(shsigset_t
*setp
, int signo
)
502 *setp
|= 1U << signo
;
504 sigaddset(setp
, signo
);
508 void sh_sigdelset(shsigset_t
*setp
, int signo
)
511 *setp
&= ~(1U << signo
);
513 sigdelset(setp
, signo
);
517 int sh_sigismember(shsigset_t
*setp
, int signo
)
520 return !!(*setp
& (1U << signo
));
522 return !!sigismember(setp
, signo
);
526 int sh_sigprocmask(shinstance
*psh
, int operation
, shsigset_t
const *newp
, shsigset_t
*oldp
)
528 #ifdef SH_PURE_STUB_MODE
530 #elif defined(SH_STUB_MODE)
535 return sigprocmask(operation
, newp
, oldp
);
541 void sh_abort(shinstance
*psh
)
543 TRACE2((psh
, "sh_abort\n"));
545 #ifdef SH_PURE_STUB_MODE
546 #elif defined(SH_STUB_MODE)
551 TRACE2((psh
, "sh_abort returns!\n"));
555 void sh_raise_sigint(shinstance
*psh
)
557 TRACE2((psh
, "sh_raise(SIGINT)\n"));
559 #ifdef SH_PURE_STUB_MODE
560 #elif defined(SH_STUB_MODE)
566 TRACE2((psh
, "sh_raise(SIGINT) returns\n"));
570 int sh_kill(shinstance
*psh
, pid_t pid
, int signo
)
574 #ifdef SH_PURE_STUB_MODE
576 #elif defined(SH_STUB_MODE)
580 //fprintf(stderr, "kill(%d, %d)\n", pid, signo);
581 rc
= kill(pid
, signo
);
586 TRACE2((psh
, "sh_kill(%d, %d) -> %d [%d]\n", pid
, signo
, rc
, errno
));
591 int sh_killpg(shinstance
*psh
, pid_t pgid
, int signo
)
595 #ifdef SH_PURE_STUB_MODE
597 #elif defined(SH_STUB_MODE)
601 //fprintf(stderr, "killpg(%d, %d)\n", pgid, signo);
602 rc
= killpg(pgid
, signo
);
607 TRACE2((psh
, "sh_killpg(%d, %d) -> %d [%d]\n", pgid
, signo
, rc
, errno
));
612 clock_t sh_times(shinstance
*psh
, shtms
*tmsp
)
614 #ifdef SH_PURE_STUB_MODE
616 #elif defined(SH_STUB_MODE)
627 int sh_sysconf_clk_tck(void)
629 #ifdef SH_PURE_STUB_MODE
635 return sysconf(_SC_CLK_TCK
);
640 pid_t
sh_fork(shinstance
*psh
)
643 TRACE2((psh
, "sh_fork\n"));
645 #ifdef SH_PURE_STUB_MODE
647 #elif defined(SH_STUB_MODE)
656 TRACE2((psh
, "sh_fork -> %d [%d]\n", pid
, errno
));
661 pid_t
sh_waitpid(shinstance
*psh
, pid_t pid
, int *statusp
, int flags
)
666 #ifdef SH_PURE_STUB_MODE
668 #elif defined(SH_STUB_MODE)
672 pidret
= waitpid(pid
, statusp
, flags
);
677 TRACE2((psh
, "waitpid(%d, %p, %#x) -> %d [%d] *statusp=%#x (rc=%d)\n", pid
, statusp
, flags
,
678 pidret
, errno
, *statusp
, WEXITSTATUS(*statusp
)));
683 void sh__exit(shinstance
*psh
, int rc
)
685 TRACE2((psh
, "sh__exit(%d)\n", rc
));
688 #ifdef SH_PURE_STUB_MODE
690 #elif defined(SH_STUB_MODE)
696 int sh_execve(shinstance
*psh
, const char *exe
, const char * const *argv
, const char * const *envp
)
702 TRACE2((psh
, "sh_execve(%p:{%s}, %p, %p}\n", exe
, exe
, argv
, envp
));
703 for (rc
= 0; argv
[rc
]; rc
++)
704 TRACE2((psh
, " argv[%d]=%p:{%s}\n", rc
, argv
[rc
], argv
[rc
]));
707 #ifdef SH_PURE_STUB_MODE
709 #elif defined(SH_STUB_MODE)
713 rc
= execve(exe
, (char **)argv
, (char **)envp
);
718 TRACE2((psh
, "sh_execve -> %d [%d]\n", rc
, errno
));
723 uid_t
sh_getuid(shinstance
*psh
)
725 #ifdef SH_PURE_STUB_MODE
727 #elif defined(SH_STUB_MODE)
731 uid_t uid
= getuid();
736 TRACE2((psh
, "sh_getuid() -> %d [%d]\n", uid
, errno
));
741 uid_t
sh_geteuid(shinstance
*psh
)
743 #ifdef SH_PURE_STUB_MODE
745 #elif defined(SH_STUB_MODE)
749 uid_t euid
= geteuid();
754 TRACE2((psh
, "sh_geteuid() -> %d [%d]\n", euid
, errno
));
759 gid_t
sh_getgid(shinstance
*psh
)
761 #ifdef SH_PURE_STUB_MODE
763 #elif defined(SH_STUB_MODE)
767 gid_t gid
= getgid();
772 TRACE2((psh
, "sh_getgid() -> %d [%d]\n", gid
, errno
));
777 gid_t
sh_getegid(shinstance
*psh
)
779 #ifdef SH_PURE_STUB_MODE
781 #elif defined(SH_STUB_MODE)
785 gid_t egid
= getegid();
790 TRACE2((psh
, "sh_getegid() -> %d [%d]\n", egid
, errno
));
795 pid_t
sh_getpid(shinstance
*psh
)
799 #ifdef SH_PURE_STUB_MODE
801 #elif defined(SH_STUB_MODE)
814 pid_t
sh_getpgrp(shinstance
*psh
)
816 #ifdef SH_PURE_STUB_MODE
818 #elif defined(SH_STUB_MODE)
820 pid_t pgrp
_getpid();
822 pid_t pgrp
= getpgrp();
827 TRACE2((psh
, "sh_getpgrp() -> %d [%d]\n", pgrp
, errno
));
832 pid_t
sh_getpgid(shinstance
*psh
, pid_t pid
)
834 #ifdef SH_PURE_STUB_MODE
836 #elif defined(SH_STUB_MODE)
840 pid_t pgid
= getpgid(pid
);
845 TRACE2((psh
, "sh_getpgid(%d) -> %d [%d]\n", pid
, pgid
, errno
));
850 int sh_setpgid(shinstance
*psh
, pid_t pid
, pid_t pgid
)
852 #ifdef SH_PURE_STUB_MODE
854 #elif defined(SH_STUB_MODE)
858 int rc
= setpgid(pid
, pgid
);
863 TRACE2((psh
, "sh_setpgid(%d, %d) -> %d [%d]\n", pid
, pgid
, rc
, errno
));
868 pid_t
sh_tcgetpgrp(shinstance
*psh
, int fd
)
872 #ifdef SH_PURE_STUB_MODE
874 #elif defined(SH_STUB_MODE)
878 pgrp
= tcgetpgrp(fd
);
883 TRACE2((psh
, "sh_tcgetpgrp(%d) -> %d [%d]\n", fd
, pgrp
, errno
));
888 int sh_tcsetpgrp(shinstance
*psh
, int fd
, pid_t pgrp
)
891 TRACE2((psh
, "sh_tcsetpgrp(%d, %d)\n", fd
, pgrp
));
893 #ifdef SH_PURE_STUB_MODE
895 #elif defined(SH_STUB_MODE)
899 rc
= tcsetpgrp(fd
, pgrp
);
904 TRACE2((psh
, "sh_tcsetpgrp(%d, %d) -> %d [%d]\n", fd
, pgrp
, rc
, errno
));
909 int sh_getrlimit(shinstance
*psh
, int resid
, shrlimit
*limp
)
911 #ifdef SH_PURE_STUB_MODE
913 #elif defined(SH_STUB_MODE)
917 int rc
= getrlimit(resid
, limp
);
922 TRACE2((psh
, "sh_getrlimit(%d, %p) -> %d [%d] {%ld,%ld}\n",
923 resid
, limp
, rc
, errno
, (long)limp
->rlim_cur
, (long)limp
->rlim_max
));
928 int sh_setrlimit(shinstance
*psh
, int resid
, const shrlimit
*limp
)
930 #ifdef SH_PURE_STUB_MODE
932 #elif defined(SH_STUB_MODE)
936 int rc
= setrlimit(resid
, limp
);
941 TRACE2((psh
, "sh_setrlimit(%d, %p:{%ld,%ld}) -> %d [%d]\n",
942 resid
, limp
, (long)limp
->rlim_cur
, (long)limp
->rlim_max
, rc
, errno
));