1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
|
/* -*-c-*- */
/*
* Copyright (C) 2003 Dale Mellor
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
/*
This C code represents the thinnest possible wrapper around the Guile code
which constitutes all the functionality of the mcron program. There are two
plus one reasons why we need to do this, and one very unfortunate
consequence.
Firstly, SUID does not work on an executable script. In the end, it is
the execution of the translator, in our case guile, which determines the
effective user, and it is not wise to make the system guile installation
SUID root!
Secondly, executable scripts show up in ugly ways in listings of the
system process table. Guile in particular, with its multi-line
#! ...\ \n -s ...!#
idiosyncracies shows up in process listings in a way that is difficult
to determine what program is actually running.
A third reason for the C wrapper which might be mentioned is that a
security-conscious system administrator can choose to only install a
binary, thus removing the possibility of a user studying a guile script
and working out ways of hacking it to his own ends, or worse still
finding a way to modify it to his own ends.
Unfortunately, running the guile script from inside a C program means
that the sigaction function does not work. Instead, it is necessary to
perform the signal processing in C.
The guile code itself is substituted for the GU1LE_PROGRAM_GOES_HERE (sic)
token by the makefile, which processes the scheme to make it look like one
big string.
*/
#include <signal.h>
#include <libguile.h>
/* This is a function designed to be installed as a signal handler, for signals
which are supposed to initiate shutdown of this program. It calls the scheme
procedure (see mcron.scm for details) to do all the work, and then exits. */
void
react_to_terminal_signal (int sig)
{
scm_eval_string (scm_take0str ("(delete-run-file)") );
exit (1);
}
/* This is a function designed to be callable from scheme, and sets up all the
signal handlers required by the cron personality. */
SCM
set_cron_signals ()
{
static struct sigaction sa;
memset (&sa, 0, sizeof (sa));
sa.sa_handler = react_to_terminal_signal;
sigaction (SIGTERM, &sa, 0);
sigaction (SIGINT, &sa, 0);
sigaction (SIGQUIT, &sa, 0);
sigaction (SIGHUP, &sa, 0);
return SCM_BOOL_T;
}
/* The effective main function (i.e. the one that actually does some work). We
register the function above with the guile system, and then execute the mcron
guile program. */
void
inner_main ()
{
scm_c_define_gsubr ("c-set-cron-signals", 0, 0, 0, set_cron_signals);
scm_eval_string (scm_take0str (
GUILE_PROGRAM_GOES_HERE
) );
}
/* The real main function. Does nothing but start up the guile subsystem. */
int
main (int argc, char **argv)
{
setenv ("GUILE_LOAD_PATH", GUILE_LOAD_PATH, 1);
scm_boot_guile (argc, argv, inner_main, 0);
return 0;
}
|