Imported Upstream version 2.6.0p2
[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 any
59 configuration.
60
61 C<$name> is the name of the application, used in log messages, etc.  C<$type>
62 is usualy one of "server" or "client".  It specifies the subdirectory in which
63 debug logfiles will be created.  C<$context> indicates the usual manner in
64 which this application is invoked; one of C<"cmdline"> for a user-invoked
65 command-line utility (e.g., C<amadmin>) which should send human-readable error
66 messages to stderr; C<"daemon"> for a program started by C<amandad>, e.g.,
67 C<sendbackup>; or C<"scriptutil"> for a small program used from shell scripts,
68 e.g., C<amgetconf>
69
70 Based on C<$type> and C<$context>, this function does the following:
71
72 =over
73
74 =item *
75
76 sets up debug logging;
77
78 =item *
79
80 configures internationalization
81
82 =item *
83
84 sets the umask;
85
86 =item *
87
88 sets the current working directory to the debug or temporary directory;
89
90 =item *
91
92 closes any unnecessary file descriptors as a security meaasure;
93
94 =item *
95
96 ignores C<SIGPIPE>; and
97
98 =item *
99
100 sets the appropriate target for error messages.
101
102 =back
103
104 =cut
105
106 # private package variables
107 my $_pname;
108 my $_ptype;
109 my $_pcontext;
110
111 sub setup_application {
112     my ($name, $type, $context) = @_;
113
114     # sanity check
115     croak("no name given") unless ($name);
116     croak("no type given") unless ($type);
117     croak("no context given") unless ($context);
118
119     # store these as perl values
120     $_pname = $name;
121     $_ptype = $type;
122     $_pcontext = $context;
123
124     # and let the C side know about the pname
125     set_pname($name);
126
127     safe_cd(); # (also sets umask)
128     check_std_fds();
129
130     # set up debugging for this application type
131     dbopen($type);
132
133     # ignore SIGPIPE
134     $SIG{'PIPE'} = 'IGNORE';
135
136     set_erroutput_type($type, $context);
137 }
138
139 =item C<finish_setup($running_as_flags)>
140
141 Perform final initialization tasks that require a loaded configuration.
142 Specifically, move the debug log into a configuration-specific
143 subdirectory, and check that the current userid is appropriate for
144 this applciation.
145
146 The user is specified by one of the following flags, which are
147 available in export tag C<:check_running_as_flags>:
148
149   $RUNNING_AS_ROOT                # root
150   $RUNNING_AS_DUMPUSER            # dumpuser, from configuration
151   $RUNNING_AS_DUMPUSER_PREFERRED  # dumpuser, but client_login is OK too
152   $RUNNING_AS_CLIENT_LOGIN        # client_login (--with-user at build time)
153
154 If the flag C<$RUNNING_AS_UID_ONLY> is bit-or'd into C<$running_as_flags>, then
155 the euid is ignored; this is used for programs that expect to be setuid-root.
156
157 =cut
158
159 sub finish_setup {
160     my ($running_as) = @_;
161
162     my $config_name = Amanda::Config::get_config_name();
163
164     if ($config_name) {
165         dbrename($config_name, $_ptype);
166     }
167
168     check_running_as($running_as);
169 }
170
171 =item C<safe_env()>
172
173 Return a "safe" environment hash.  For non-setuid programs, this means filtering out any
174 localization variables.
175
176 =cut
177
178 sub safe_env {
179     my %rv = %ENV;
180
181     delete @rv{qw(IFS CDPATH ENV BASH_ENV LANG)};
182
183     # delete all LC_* variables
184     for my $var (grep /^LC_/, keys %rv) {
185         delete $rv{$var};
186     }
187
188     return %rv;
189 }
190
191 %}
192
193 amglue_add_flag_tag_fns(running_as_flags);
194 amglue_add_constant(RUNNING_AS_ROOT, running_as_flags);
195 amglue_add_constant(RUNNING_AS_DUMPUSER, running_as_flags);
196 amglue_add_constant(RUNNING_AS_DUMPUSER_PREFERRED, running_as_flags);
197 amglue_add_constant(RUNNING_AS_CLIENT_LOGIN, running_as_flags);
198 amglue_add_constant(RUNNING_AS_UID_ONLY, running_as_flags);
199
200 /* -------------------------------------------------------------------------
201  * Functions below this line are only meant to be called within this module;
202  * do not call them externally. */
203
204 void set_pname(char *name);
205 void safe_cd(void);
206
207 void check_running_as(running_as_flags who);
208
209 /* Set erroutput_type as appropriate for this process type and context.
210  *
211  * @param type: process type
212  * @param context: process context
213  */
214 %inline %{
215 void
216 set_erroutput_type(char *type, char *context)
217 {
218     if (strcmp(context, "cmdline") == 0) {
219         erroutput_type = ERR_INTERACTIVE;
220     } else if (strcmp(context, "daemon") == 0) {
221         if (strcmp(type, "server") == 0) {
222             erroutput_type = ERR_INTERACTIVE|ERR_AMANDALOG;
223         } else if (strcmp(type, "client") == 0) {
224             erroutput_type = ERR_INTERACTIVE|ERR_SYSLOG;
225         }
226     }
227 }
228 %}
229
230 /* Check that fd's 0, 1, and 2 are open, calling critical() if not.
231  */
232 %perlcode %{
233 sub check_std_fds {
234     fcntl(STDIN, F_GETFD, 0) or critical("Standard input is not open");
235     fcntl(STDOUT, F_GETFD, 0) or critical("Standard output is not open");
236     fcntl(STDERR, F_GETFD, 0) or critical("Standard error is not open");
237 }
238
239 =back
240
241 =cut
242 %}