e67a471d7e3f1526c3fbf1705493707975662380
[debian/amanda] / perl / Amanda / Util.swg
1 /*
2  * Copyright (c) Zmanda, Inc.  All Rights Reserved.
3  *
4  * This library is free software; you can redistribute it and/or modify it
5  * under the terms of the GNU Lesser General Public License version 2.1
6  * as published by the Free Software Foundation.
7  *
8  * This library is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
10  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
11  * License for more details.
12  *
13  * You should have received a copy of the GNU Lesser General Public License
14  * along with this library; if not, write to the Free Software Foundation,
15  * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA.
16  *
17  * Contact information: Zmanda Inc., 505 N Mathlida Ave, Suite 120
18  * Sunnyvale, CA 94085, USA, or: http://www.zmanda.com
19  */
20
21 %module "Amanda::Util"
22 %include "amglue/amglue.swg"
23 %include "exception.i"
24
25 %{
26 #include "debug.h"
27 /* use a relative path here to avoid conflicting with Perl's util.h. */
28 #include "../common-src/util.h"
29 #include "file.h"
30 %}
31
32 %perlcode %{
33 use Amanda::Debug qw(:init);
34 use Carp;
35 use POSIX qw(:fcntl_h);
36
37 =head1 NAME
38
39 Amanda::Util - Runtime support for Amanda applications
40
41 =head1 Application Initialization
42
43 Application initialization generally looks like this:
44
45   use Amanda::Config qw( :init );
46   use Amanda::Util qw( :check_running_as_flags );
47   use Amanda::Debug;
48
49   Amanda::Util::setup_application("myapp", "server", "cmdline");
50   # .. command-line processing ..
51   Amanda::Config::config_init(...);
52   Amanda::Util::finish_setup($RUNNING_AS_DUMPUSER);
53
54 =over
55
56 =item C<setup_application($name, $type, $context)>
57
58 Set up the operating environment for an application, without requiring
59 any configuration.
60
61 =over
62
63 =item C<$name> is the name of the application, used in log messages, etc.
64
65 =item C<$type> is one of "server" or "client".
66
67 =item C<$context> is one of "cmdline" for a user-invoked command-line
68 utility (e.g., C<amadmin>) or "daemon" for a program started by
69 C<amandad>.  (TODO: daemon is not supported yet)
70
71 =back
72
73 Based on C<$type> and C<$context>, this function does the following:
74
75 =over
76
77 =item sets up debug logging;
78
79 =item configures internationalization
80
81 =item sets the umask;
82
83 =item sets the current working directory to the debug or temporary directory;
84
85 =item closes any unnecessary file descriptors as a security meaasure;
86
87 =item ignores C<SIGPIPE>; and
88
89 =item sets the appropriate target for error messages.
90
91 =back
92
93 =cut
94
95 # private package variables
96 my $_pname;
97 my $_ptype;
98 my $_pcontext;
99
100 sub setup_application {
101     my ($name, $type, $context) = @_;
102
103     # sanity check
104     croak("no name given") unless ($name);
105     croak("no type given") unless ($type);
106     croak("no context given") unless ($context);
107
108     # store these as perl values
109     $_pname = $name;
110     $_ptype = $type;
111     $_pcontext = $context;
112
113     # and let the C side know about the pname
114     set_pname($name);
115
116     safe_cd(); # (also sets umask)
117     check_std_fds();
118
119     # set up debugging for this application type
120     dbopen($type);
121
122     # ignore SIGPIPE
123     $SIG{'PIPE'} = 'IGNORE';
124
125     set_erroutput_type($type, $context);
126 }
127
128 =item C<finish_setup($running_as_flags)>
129
130 Perform final initialization tasks that require a loaded configuration.
131 Specifically, move the debug log into a configuration-specific
132 subdirectory, and check that the current userid is appropriate for
133 this applciation.
134
135 The user is specified by one of the following flags, which are
136 available in export tag C<:check_running_as_flags>:
137
138   $RUNNING_AS_ROOT                # root
139   $RUNNING_AS_DUMPUSER            # dumpuser, from configuration
140   $RUNNING_AS_DUMPUSER_PREFERRED  # dumpuser, but client_login is OK too
141   $RUNNING_AS_CLIENT_LOGIN        # client_login (--with-user at build time)
142
143 If the flag C<$RUNNING_AS_UID_ONLY> is bit-or'd into C<$running_as_flags>, then
144 the euid is ignored; this is used for programs that expect to be setuid-root.
145
146 =cut
147
148 sub finish_setup {
149     my ($running_as) = @_;
150
151     my $config_name = Amanda::Config::get_config_name();
152
153     if ($config_name) {
154         dbrename($config_name, $_ptype);
155     }
156
157     check_running_as($running_as);
158 }
159
160 =item safe_env
161
162 Return a "safe" environment hash.  For non-setuid programs, this means filtering out any
163 localization variables.
164
165 =cut
166
167 sub safe_env {
168     my %rv = %ENV;
169
170     delete @rv{qw(IFS CDPATH ENV BASH_ENV LANG)};
171
172     # delete all LC_* variables
173     for my $var (grep /^LC_/, keys %rv) {
174         delete $rv{$var};
175     }
176
177     return %rv;
178 }
179
180 %}
181
182 amglue_add_flag_tag_fns(running_as_flags);
183 amglue_add_constant(RUNNING_AS_ROOT, running_as_flags);
184 amglue_add_constant(RUNNING_AS_DUMPUSER, running_as_flags);
185 amglue_add_constant(RUNNING_AS_DUMPUSER_PREFERRED, running_as_flags);
186 amglue_add_constant(RUNNING_AS_CLIENT_LOGIN, running_as_flags);
187 amglue_add_constant(RUNNING_AS_UID_ONLY, running_as_flags);
188
189 /* -------------------------------------------------------------------------
190  * Functions below this line are only meant to be called within this module;
191  * do not call them externally. */
192
193 void set_pname(char *name);
194 void safe_cd(void);
195
196 void check_running_as(running_as_flags who);
197
198 /* Set erroutput_type as appropriate for this process type and context.
199  *
200  * @param type: process type
201  * @param context: process context
202  */
203 %inline %{
204 void
205 set_erroutput_type(char *type, char *context)
206 {
207     if (strcmp(context, "cmdline") == 0) {
208         erroutput_type = ERR_INTERACTIVE;
209     } else if (strcmp(context, "daemon") == 0) {
210         if (strcmp(type, "server") == 0) {
211             erroutput_type = ERR_INTERACTIVE|ERR_AMANDALOG;
212         } else if (strcmp(type, "client") == 0) {
213             erroutput_type = ERR_INTERACTIVE|ERR_SYSLOG;
214         }
215     }
216 }
217 %}
218
219 /* Check that fd's 0, 1, and 2 are open, calling critical() if not.
220  */
221 %perlcode %{
222 sub check_std_fds {
223     fcntl(STDIN, F_GETFD, 0) or critical("Standard input is not open");
224     fcntl(STDOUT, F_GETFD, 0) or critical("Standard output is not open");
225     fcntl(STDERR, F_GETFD, 0) or critical("Standard error is not open");
226 }
227 %}