2 # Common majordomo functions
4 BEGIN { push(@INC, ".."); };
8 %MAJOR_ENV = ( 'HOME', $config{'program_dir'} );
11 # Parse and return the majordomo config file
15 open(CONF, $config{'majordomo_cf'});
18 if (/^\s*\$(\S+)\s*=\s*"(.*)";\s*$/ ||
19 /^\s*\$(\S+)\s*=\s*'(.*)';\s*$/) {
20 # static config option
21 push(@rv, { 'name' => $1,
22 'value' => &perl_unescape($2),
26 elsif (/^\s*\$(\S+)\s*=\s*<<\s*'(\S+)';\s*$/) {
27 # multiline config option
28 local $o = { 'name' => $1,
33 last if ($_ =~ /^$end[\r\n]+$/);
36 $o->{'eline'} = $line;
39 # elsif (/^\s*\$(\S+)\s*=\s*\$ENV\{['"]([^'"]+)['"]\};\s*$/) {
40 # # from majordomo environment variable
41 # push(@rv, { 'name' => $1,
42 # 'value' => $MAJOR_ENV{$2},
44 # 'eline' => $line });
46 elsif (/^\s*\$(\S+)\s*=\s*(.*);\s*$/) {
47 # computed config option
48 push(@rv, { 'name' => $1,
60 # save_directive(&config, name, value)
61 # Update some directive in the global config file
64 local $old = &find($_[1], $_[0]);
66 local $lref = &read_file_lines($config{'majordomo_cf'});
67 local $olen = $old->{'eline'} - $old->{'line'} + 1;
71 splice(@$lref, $old->{'line'}, $olen,
72 ( "\$$_[1] = <<'END';", split(/\n/, $v, -1), "END" ));
76 splice(@$lref, $old->{'line'}, $olen, "\$$_[1] = \"$v\";");
84 foreach $c (@{$_[1]}) {
85 if ($c->{'name'} eq $_[0]) {
89 return @rv ? wantarray ? @rv : $rv[0]
90 : wantarray ? () : undef;
93 # find_value(name, &array)
97 @v = &find($_[0], $_[1]);
98 @v = grep { !$_->{'computed'} } @v;
99 if (!@v) { return undef; }
100 elsif (wantarray) { return map { $_->{'value'} } @v; }
101 else { return $v[0]->{'value'}; }
104 # list_lists(&config)
105 # Returns a list of mailing list names
109 local $ldir = &perl_var_replace(&find_value("listdir", $_[0]), $_[0]);
111 while($l = readdir(DIR)) {
112 if ($l =~ /^(\S+)\.config$/ && $1 !~ /\.old$/) {
120 # get_list(name, &config)
121 # Returns the details of some list
124 local $ldir = &perl_var_replace(&find_value("listdir", $_[1]), $_[1]);
126 return undef if (!-r "$ldir/$_[0].config");
127 $list{'name'} = $_[0];
128 $list{'members'} = "$ldir/$_[0]";
129 $list{'config'} = "$ldir/$_[0].config";
130 $list{'info'} = "$ldir/$_[0].info";
131 $list{'intro'} = "$ldir/$_[0].intro";
135 # get_list_config(file)
144 if (/^\s*(\S+)\s*=\s*(.*)$/) {
146 push(@rv, { 'name' => $1,
148 'index' => scalar(@rv),
152 elsif (/^\s*(\S+)\s*<<\s*(\S+)/) {
154 local $c = { 'name' => $1,
155 'index' => scalar(@rv),
160 last if (/^$end[\r\n]+$/);
165 $c->{'eline'} = $lnum;
173 # save_list_directive(&config, file, name, value, multiline)
174 sub save_list_directive
176 local $old = &find($_[2], $_[0]);
177 local $lref = &read_file_lines($_[1]);
178 local ($pos, $olen, $nlen);
180 $olen = $old->{'eline'} - $old->{'line'} + 1;
181 $pos = $old->{'line'};
188 local $ov = $old->{'value'};
192 local @lines = split(/\n/, $v, -1);
193 @lines = map { s/^-/--/; s/^$/-/; $_ } @lines;
194 splice(@$lref, $pos, $olen, ("$_[2] << END", @lines, "END"))
195 if (!$old || $v ne $ov);
196 $nlen = (!$old || $v ne $ov) ? @lines + 2 : $olen;
199 splice(@$lref, $pos, $olen, "$_[2] = $_[3]")
200 if (!$old || $_[3] ne $old->{'value'});
203 if ($old && $nlen != $olen) {
204 foreach $c (@{$_[0]}) {
205 if ($c->{'line'} > $old->{'eline'}) {
206 $c->{'line'} += ($nlen - $olen);
207 $c->{'eline'} += ($nlen - $olen);
214 # Returns the paths to the sendmail-style aliases files
217 if ($config{'aliases_file'} eq 'postfix') {
218 # Get from Postfix config
219 &foreign_require("postfix", "postfix-lib.pl");
220 local @afiles = &postfix::get_aliases_files(
221 &postfix::get_current_value("alias_maps"));
222 $aliases_module = "postfix";
226 &foreign_require("sendmail", "sendmail-lib.pl");
227 &foreign_require("sendmail", "aliases-lib.pl");
228 $aliases_module = "sendmail";
229 if ($config{'aliases_file'} eq '') {
231 local $sm_conf = &sendmail::get_sendmailcf();
232 return &sendmail::aliases_file($sm_conf);
236 return [ $config{'aliases_file'} ];
241 # perl_unescape(string)
242 # Converts a string like "hello\@there\\foo" to "hello@there\foo"
250 # perl_var_replace(string, &config)
251 # Replaces variables like $foo in a string with their value from
257 while($str =~ /\$([A-z0-9\_]+)/ && !$donevar{$1}) {
259 local $val = &find_value($1, $_[1]);
260 $str =~ s/\$([A-z0-9\_]+)/$val/;
265 # set_permissions(file)
266 # Sets the ownership and permissions on some file or directory,
267 # based on the ownership of the lists directory
270 local $conf = &get_config();
271 local $ldir = &perl_var_replace(&find_value("listdir", $conf), $conf);
272 local @ldir = stat($ldir);
273 chown($ldir[4], $ldir[5], $_[0]);
274 if ($config{'perms'}) {
275 chmod(-d $_[0] ? 0755 : 0644, $_[0]);
278 chmod(-d $_[0] ? 0775 : 0664, $_[0]);
282 # choice_input(name, text, &config, [opt, display]+)
285 local $v = &find_value($_[0], $_[2]);
286 local $rv = "<td><b>$_[1]</b></td> <td nowrap>";
287 for($i=3; $i<@_; $i+=2) {
288 local $ch = $v eq $_[$i] ? "checked" : "";
289 $rv .= "<input name=$_[0] type=radio value='$_[$i]' $ch> ".$_[$i+1];
295 # save_choice(&config, file, name)
298 &save_list_directive($_[0], $_[1], $_[2], $in{$_[2]});
301 # opt_input(name, text, &config, default, size, [units])
304 local $v = &find_value($_[0], $_[2]);
305 local $rv = "<td><b>$_[1]</b></td> <td nowrap ".
306 ($_[4] > 30 ? "colspan=3" : "").">";
307 $rv .= sprintf "<input type=radio name=$_[0]_def value=1 %s> $_[3]\n",
308 $v eq "" ? "checked" : "";
309 $rv .= sprintf "<input type=radio name=$_[0]_def value=0 %s>\n",
310 $v eq "" ? "" : "checked";
311 local $passwd = $_[0] =~ /passwd/ ? "type=password" : "";
312 $rv .= "<input $passwd name=$_[0] size=$_[4] value=\"$v\"> $_[5]</td>\n";
316 # save_opt(&config, file, name, [&func])
319 if ($in{"$_[2]_def"}) { &save_list_directive($_[0], $_[1], $_[2], ""); }
320 elsif ($_[3] && ($err = &{$_[3]}($in{$_[2]}))) { &error($err); }
321 else { &save_list_directive($_[0], $_[1], $_[2], $in{$_[2]}); }
324 # select_input(name, text, &config, [opt, display]+)
327 local $v = &find_value($_[0], $_[2]);
328 local $rv = "<td><b>$_[1]</b></td> <td nowrap><select name=$_[0]>";
329 for($i=3; $i<@_; $i+=2) {
330 local $ch = $v eq $_[$i] ? "selected" : "";
331 $rv .= "<option value='$_[$i]' $ch> ".$_[$i+1];
333 $rv .= "</select></td>\n";
337 # save_select(&config, file, name)
340 &save_list_directive($_[0], $_[1], $_[2], $in{$_[2]});
343 # multi_input(name, text, &config)
346 local $v = &find_value($_[0], $_[2]);
347 local $rv = "<td valign=top><b>$_[1]</b></td> <td colspan=3>".
348 "<textarea rows=4 cols=80 name=$_[0]>\n$v</textarea></td>\n";
352 # save_multi(&config, file, name)
355 $in{$_[2]} =~ s/\r//g;
356 &save_list_directive($_[0], $_[1], $_[2], $in{$_[2]}, 1);
359 # can_edit_list(&access, name)
362 foreach (split(/\s+/, $_[0]->{'lists'})) {
363 return 1 if ($_ eq "*" || $_ eq $_[1]);
368 # homedir_valid(&config)
371 local $homedir = &find_value("homedir", $_[0]);
374 foreach $c (@$conf) {
375 $homeused++ if ($c->{'value'} =~ /\$homedir/);