Handle hostnames with upper-case letters
[webmin.git] / nis / open-linux-lib.pl
1 # open-linux-lib.pl
2 # NIS functions for caldera linux NIS client and server
3
4 $nis_config_dir = "/etc/nis";
5 $ypserv_conf = "/etc/ypserv.conf";
6 $pid_file = "/var/run/ypserv.pid";
7
8 # get_nis_support()
9 # Returns 0 for no support, 1 for client only, 2 for server and 3 for both
10 sub get_nis_support
11 {
12 local $rv;
13 $rv += 1 if (&has_command("ypbind"));
14 $rv += 2 if (-x "/usr/libexec/nis/rpc.ypserv");
15 return $rv;
16 }
17
18 # get_client_config()
19 # Returns a hash ref containg details of the client's NIS settings
20 sub get_client_config
21 {
22 local $nis;
23 open(CONF, $config{'client_conf'});
24 while(<CONF>) {
25         s/\r|\n//g;
26         s/#.*$//g;
27         if (/^\s*domain\s*(\S+)\s*broadcast/i) {
28                 $nis->{'domain'} = $1;
29                 $nis->{'broadcast'}++;
30                 }
31         elsif (/^\s*domain\s*(\S+)\s*server\s*(\S+)/i) {
32                 $nis->{'domain'} = $1;
33                 push(@{$nis->{'servers'}}, $2);
34                 }
35         elsif (/^\s*ypserver\s*(\S+)/) {
36                 push(@{$nis->{'servers'}}, $1);
37                 }
38         }
39 close(CONF);
40 return $nis;
41 }
42
43 # save_client_config(&config)
44 # Saves and applies the NIS client configuration in the give hash.
45 # Returns an error message if any, or undef on success.
46 sub save_client_config
47 {
48 # Save the config file
49 &open_tempfile(CONF, ">$config{'client_conf'}");
50 if ($_[0]->{'domain'}) {
51         if ($_[0]->{'broadcast'}) {
52                 &print_tempfile(CONF, "domain $_[0]->{'domain'} broadcast\n");
53                 }
54         else {
55                 local @s = @{$_[0]->{'servers'}};
56                 &print_tempfile(CONF, "domain $_[0]->{'domain'} server ",shift(@s),"\n");
57                 foreach $s (@s) {
58                         &print_tempfile(CONF, "ypserver $s\n");
59                         }
60                 }
61         }
62 &close_tempfile(CONF);
63 if ($_[0]->{'domain'}) {
64         &init::enable_at_boot("nis-client");
65         }
66 else {
67         &init::disable_at_boot("nis-client");
68         }
69
70 # Apply by running the init script
71 local $init = &init_script("nis-client");
72 &system_logged("$init stop >/dev/null 2>&1");
73 if ($_[0]->{'domain'}) {
74         &system_logged("domainname \"$_[0]->{'domain'}\"");
75         local $out = &backquote_logged("$init start 2>&1");
76         if ($?) { return "<pre>$out</pre>"; }
77         $out = `ypwhich 2>&1`;
78         if ($?) { return $text{'client_eypwhich'}; }
79         }
80 else {
81         &system_logged("domainname '' >/dev/null 2>&1");
82         }
83 return undef;
84 }
85
86 # show_server_config()
87 # Display a form for editing NIS server options
88 sub show_server_config
89 {
90 local @domains;
91 opendir(DIR, $nis_config_dir);
92 foreach $f (readdir(DIR)) {
93         push(@domains, $f) if ($f !~ /^\./ &&
94                                -r "$nis_config_dir/$f/.nisupdate.conf");
95         }
96 closedir(DIR);
97 @domains = ( "" ) if (!@domains);
98
99 local $boot = &init::action_status("nis-server");
100 print "<tr> <td valign=top><b>$text{'server_boot'}</b></td>\n";
101 printf "<td valign=top><input type=radio name=boot value=1 %s> %s\n",
102         $boot == 2 ? 'checked' : '', $text{'yes'};
103 printf "<input type=radio name=boot value=0 %s> %s</td> </tr>\n",
104         $boot == 2 ? '' : 'checked', $text{'no'};
105
106 local $n = 0;
107 foreach $d (@domains) {
108         print "<tr> <td colspan=4><hr></td> </tr>\n";
109         print "<input type=hidden name=old_$n value='$d'>\n";
110         print "<tr> <td valign=top><b>$text{'server_domain'}</b></td>\n";
111         printf "<td valign=top>".
112                "<input type=radio name=domain_def_$n value=1 %s> %s\n",
113                 $d ? '' : 'checked', $text{'server_none'};
114         printf "<input type=radio name=domain_def_$n value=0 %s>\n",
115                 $d ? 'checked' : '';
116         print "<input name=domain_$n size=30 value='$d'></td>\n";
117
118         local @conf = &parse_nisupdate_conf(
119                 $d ? "$nis_config_dir/$d/.nisupdate.conf"
120                    : "nisupdate.conf");
121         print "<td valign=top><b>$text{'server_tables'}</b></td>\n";
122         print "<td><select name=tables_$n size=6 multiple>\n";
123         foreach $c (@conf) {
124                 printf "<option value=%s %s>%s\n",
125                         $c->{'table'}, $c->{'active'} ? 'selected' : '',
126                         $c->{'table'};
127                 }
128         print "</select></td> </tr>\n";
129
130         $n++;
131         }
132
133 }
134
135 # parse_server_config()
136 # Parse and save the NIS server options
137 sub parse_server_config
138 {
139 local ($n, $anydomains);
140 for($n=0; defined($in{"old_$n"}); $n++) {
141         # Update the domain name directory
142         $in{"domain_def_$n"} || $in{"domain_$n"} =~ /^[A-Za-z0-9\.\-]+$/ ||
143                 &error(&text('server_edomain', $in{"domain_$n"}));
144         local $domain = $in{"domain_def_$n"} ? undef : $in{"domain_$n"};
145         local $old = $in{"old_$n"};
146         if (!$old && !$domain) {
147                 # No domain before, and none chosen
148                 next;
149                 }
150         elsif (!$old && $domain) {
151                 # New domain added
152                 mkdir("$nis_config_dir/$domain", 0755);
153                 &system_logged("cp nisupdate.conf ".
154                                "$nis_config_dir/$domain/.nisupdate.conf");
155                 }
156         elsif ($old && !$domain) {
157                 # Domain taken away
158                 &system_logged("rm -rf $nis_config_dir/$old");
159                 next;
160                 }
161         elsif ($old ne $domain) {
162                 # Domain renamed
163                 &rename_logged("$nis_config_dir/$old",
164                                "$nis_config_dir/$domain");
165                 }
166         $anydomains++;
167
168         # Update the config file
169         local $file = "$nis_config_dir/$domain/.nisupdate.conf";
170         local @conf = &parse_nisupdate_conf($file);
171         local $lref = &read_file_lines($file);
172         local %table;
173         map { $table{$_}++ } split(/\0/, $in{"tables_$n"});
174         foreach $c (@conf) {
175                 if ($c->{'active'} && !$table{$c->{'table'}}) {
176                         # Need to deactivate a table
177                         splice(@$lref, $c->{'line'},
178                                $c->{'eline'} - $c->{'line'} + 1,
179                                map { "#$_" } @{$c->{'data'}});
180                         }
181                 elsif (!$c->{'active'} && $table{$c->{'table'}}) {
182                         # Need to activate a table
183                         splice(@$lref, $c->{'line'},
184                                $c->{'eline'} - $c->{'line'} + 1,
185                                @{$c->{'data'}});
186                         }
187                 }
188         &flush_file_lines();
189         }
190
191 # Start the NIS server and rebuild maps if needed
192 if ($in{'boot'}) {
193         &init::enable_at_boot("nis-server");
194         }
195 else {
196         &init::disable_at_boot("nis-server");
197         }
198 local $init = &init_script("nis-server");
199 &system_logged("$init stop >/dev/null 2>&1");
200 if ($anydomains && $in{'boot'}) {
201         &system_logged("$init start >/dev/null 2>&1");
202         }
203 &apply_table_changes();
204 }
205
206 # get_server_mode()
207 # Returns 0 if the NIS server is inactive, 1 if active as a master, or 2 if
208 # active as a slave.
209 sub get_server_mode
210 {
211 local $boot = &init::action_status("nis-server");
212 local $dc;
213 opendir(DIR, $nis_config_dir);
214 foreach $f (readdir(DIR)) {
215         $dc++ if ($f !~ /^\./ && -r "$nis_config_dir/$f/.nisupdate.conf");
216         }
217 closedir(DIR);
218 if ($boot != 2 || !$dc) {
219         return 0;
220         }
221 else {
222         return 1;
223         }
224 }
225
226 # parse_nisupdate_conf(file)
227 sub parse_nisupdate_conf
228 {
229 local @rv;
230 local $lnum = 0;
231 open(CONF, $_[0]);
232 while(<CONF>) {
233         s/\r|\n//g;
234         if (/^\s*(#*)(\s*\$rule{['"]([^"']+)['"]}.*)/) {
235                 local $text = $2;
236                 local $table = { 'table' => $3,
237                                  'active' => $1 eq '',
238                                  'data' => [ $2 ],
239                                  'line' => $lnum,
240                                  'eline' => $lnum };
241                 while(!/;\s*$/) {
242                         ($_ = <CONF>) || last;
243                         s/^\s*#+//; s/\r|\n//g;
244                         push(@{$table->{'data'}}, $_);
245                         $text .= " $_";
246                         $lnum++;
247                         $table->{'eline'} = $lnum;
248                         }
249                 $table->{'value'} = $2 if ($text =~ /\$rule{['"]([^"']+)['"]}\s*=\s*["']([^"']+)["']/);
250                 push(@rv, $table);
251                 }
252         $lnum++;
253         }
254 close(CONF);
255 return @rv;
256 }
257
258 # list_nis_tables()
259 # Returns a list of structures of all NIS tables
260 sub list_nis_tables
261 {
262 local @rv;
263 opendir(DIR, $nis_config_dir);
264 foreach $d (readdir(DIR)) {
265         push(@domains, $d) if ($d !~ /^\./ &&
266                                -r "$nis_config_dir/$d/.nisupdate.conf");
267         }
268 closedir(DIR);
269 foreach $d (@domains) {
270         local @conf = &parse_nisupdate_conf(
271                         "$nis_config_dir/$d/.nisupdate.conf");
272         foreach $t (@conf) {
273                 next if (!$t->{'active'});
274                 local $table = { 'table' => $t->{'table'},
275                                  'domain' => $d,
276                                  'index' => scalar(@rv) };
277                 if ($t->{'value'} =~ /^(\S+)\s+(\S+)/) {
278                         $table->{'files'} = [ map { "$nis_config_dir/$d/$_" }
279                                                   split(/,/, $2) ];
280                         }
281                 if ($t->{'table'} eq 'passwd') {
282                         $table->{'type'} = 'passwd_shadow';
283                         }
284                 elsif ($t->{'table'} eq 'services') {
285                         $table->{'type'} = 'services2';
286                         }
287                 else {
288                         $table->{'type'} = $t->{'table'};
289                         }
290                 push(@rv, $table);
291                 }
292         }
293 return @rv;
294 }
295
296 # apply_table_changes()
297 # Do whatever is necessary for the table text files to be loaded into
298 # the NIS server
299 sub apply_table_changes
300 {
301 &system_logged("(cd /var/yp ; make) >/dev/null 2>&1 </dev/null");
302 }
303
304 sub extra_config_files
305 {
306 local ($f, @rv);
307 opendir(DIR, $nis_config_dir);
308 foreach $f (readdir(DIR)) {
309         push(@rv, "$nis_config_dir/$f/.nisupdate.conf") if ($f !~ /^\./);
310         }
311 closedir(DIR);
312 push(@rv, "$nis_config_dir/nisupdate.conf");
313 return grep { -r $_ } @rv;
314 }
315
316 1;
317