Handle hostnames with upper-case letters
[webmin.git] / nis / united-linux-lib.pl
1 # united-linux-lib.pl
2 # NIS functions for United Linux NIS client and server
3
4 $yp_makefile = "/var/yp/Makefile";
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 (&has_command("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->{'broadcast'}++;
29                 }
30         elsif (/^\s*domain\s*(\S+)\s*server\s*(\S+)/i) {
31                 push(@{$nis->{'servers'}}, $2);
32                 }
33         elsif (/^\s*ypserver\s*(\S+)/) {
34                 push(@{$nis->{'servers'}}, $1);
35                 }
36         }
37 close(CONF);
38 open(DOMAIN, "/etc/defaultdomain");
39 chop($nis->{'domain'} = <DOMAIN>);
40 close(DOMAIN);
41 return $nis;
42 }
43
44 # save_client_config(&config)
45 # Saves and applies the NIS client configuration in the give hash.
46 # Returns an error message if any, or undef on success.
47 sub save_client_config
48 {
49 # Save the config file
50 &open_tempfile(CONF, ">$config{'client_conf'}");
51 if ($_[0]->{'domain'}) {
52         if ($_[0]->{'broadcast'}) {
53                 &print_tempfile(CONF, "domain $_[0]->{'domain'} broadcast\n");
54                 }
55         else {
56                 local @s = @{$_[0]->{'servers'}};
57                 &print_tempfile(CONF, "domain $_[0]->{'domain'} server ",shift(@s),"\n");
58                 foreach $s (@s) {
59                         &print_tempfile(CONF, "ypserver $s\n");
60                         }
61                 }
62         }
63 &close_tempfile(CONF);
64
65 # Stop the init script
66 local $init = &init_script("ypbind");
67 &system_logged("$init stop >/dev/null 2>&1");
68
69 # Save domain name
70 if ($_[0]->{'domain'}) {
71         &open_tempfile(DOMAIN, ">/etc/defaultdomain");
72         &print_tempfile(DOMAIN, $_[0]->{'domain'},"\n");
73         &close_tempfile(DOMAIN);
74         }
75 else {
76         unlink("/etc/defaultdomain");
77         }
78
79 # Start the init script
80 if ($_[0]->{'domain'}) {
81         local $out = &backquote_logged("$init start 2>&1");
82         if ($?) { return "<pre>$out</pre>"; }
83         }
84 return undef;
85 }
86
87 @nis_files = ( "passwd", "shadow", "group", "gshadow", "adjunct",
88                "aliases", "ethers", "bootparams", "hosts", "networks",
89                "printcap", "protocols", "publickeys", "rpc", "services",
90                "netgroup", "netid", "auto_master", "auto_home",
91                "auto_local", "timezone", "locale", "netmasks" );
92
93 @nis_tables = ( "passwd", "group", "hosts", "rpc", "services", "netid",
94                 "protocols", "netgrp", "mail", "shadow", "publickey",
95                 "networks", "ethers", "bootparams", "printcap", "amd.home",
96                 "auto.master", "auto.home", "auto.local", "passwd.adjunct",
97                 "timezone", "locale", "netmasks" );
98
99 # show_server_config()
100 # Display a form for editing NIS server options
101 sub show_server_config
102 {
103 local ($var, $rule) = &parse_yp_makefile();
104 if ($var->{'YPPWDDIR'}->{'value'} =~ /^\$\(shell/) {
105         # Value comes from the ypserv config file
106         local %ypserv;
107         &read_env_file("/etc/sysconfig/ypserv", \%ypserv);
108         $var->{'YPPWDDIR'}->{'value'} = $ypserv{'YPPWD_SRCDIR'};
109         }
110
111 local $boot = &init::action_status("ypserv");
112 print "<tr> <td><b>$text{'server_boot'}</b></td>\n";
113 printf "<td><input type=radio name=boot value=1 %s> %s\n",
114         $boot == 2 ? 'checked' : '', $text{'yes'};
115 printf "<input type=radio name=boot value=0 %s> %s</td>\n",
116         $boot == 2 ? '' : 'checked', $text{'no'};
117
118 local $dom = $var->{'LOCALDOMAIN'}->{'value'};
119 print "<td><b>$text{'server_domain'}</b></td>\n";
120 printf "<td><input type=radio name=domain_auto value=1 %s> %s\n",
121         $dom =~ /`.*domainname`/ ? 'checked' : '', $text{'server_domain_auto'};
122 printf "<input type=radio name=domain_auto value=0 %s>\n",
123         $dom =~ /`.*domainname`/ ? '' : 'checked';
124 printf "<input name=domain size=20 value='%s'></td> </tr>\n",
125         $dom =~ /`.*domainname`/ ? '' : $dom;
126
127 print "<tr> <td><b>$text{'server_type'}</b></td>\n";
128 printf "<td colspan=3><input type=radio name=type value=1 %s> %s\n",
129         $config{'slave'} ? '' : 'checked', $text{'server_master'};
130 printf "<input type=radio name=type value=0 %s> %s\n",
131         $config{'slave'} ? 'checked' : '', $text{'server_slave'};
132 printf "<input name=slave size=30 value='%s'></td> </tr>\n", $config{'slave'};
133
134 print "</table></td></tr></table><p>\n";
135 print "<table border width=100%>\n";
136 print "<tr $tb> <td><b>$text{'server_mheader'}</b></td> </tr>\n";
137 print "<tr $cb> <td><table width=100%>\n";
138
139 print "<tr> <td><b>$text{'server_dns'}</b></td>\n";
140 printf "<td><input type=radio name=b value='-b' %s> %s\n",
141         $var->{'B'}->{'value'} eq '-b' ? 'checked' : '', $text{'yes'};
142 printf "<input type=radio name=b value='' %s> %s</td>\n",
143         $var->{'B'}->{'value'} eq '-b' ? '' : 'checked', $text{'no'};
144
145 print "<td><b>$text{'server_push'}</b></td>\n";
146 printf "<td><input type=radio name=nopush value=false %s> %s\n",
147         $var->{'NOPUSH'}->{'value'} eq 'true' ? '' : 'checked', $text{'yes'};
148 printf "<input type=radio name=nopush value=true %s> %s</td> </tr>\n",
149         $var->{'NOPUSH'}->{'value'} eq 'true' ? 'checked' : '', $text{'no'};
150
151 local %inall;
152 map { $inall{$_}++ } split(/\s+/, $rule->{'all'}->{'value'});
153 print "<tr> <td rowspan=2 valign=top><b>$text{'server_tables'}</b></td>\n";
154 print "<td rowspan=2><select multiple size=5 name=tables>\n";
155 foreach $t (grep { $rule->{$_} } @nis_tables) {
156         printf "<option value=%s %s>%s\n",
157                 $t, $inall{$t} ? 'selected' : '', $t;
158         }
159 print "</select></td>\n";
160
161 print "<td><b>$text{'server_minuid'}</b></td>\n";
162 printf "<td><input name=minuid size=10 value='%s'></td> </tr>\n",
163         $var->{'MINUID'}->{'value'};
164
165 print "<td><b>$text{'server_mingid'}</b></td>\n";
166 printf "<td><input name=mingid size=10 value='%s'></td> </tr>\n",
167         $var->{'MINGID'}->{'value'};
168
169 print "<tr> <td><b>$text{'server_slaves'}</b></td>\n";
170 open(SLAVES, "/var/yp/ypservers");
171 while(<SLAVES>) {
172         s/\s//g;
173         push(@slaves, $_) if ($_);
174         }
175 close(SLAVES);
176 printf "<td colspan=3><input name=slaves size=60 value='%s'></td> </tr>\n",
177         join(" ", @slaves);
178
179 print "</table></td></tr></table><p>\n";
180 print "<table border width=100%>\n";
181 print "<tr $tb> <td><b>$text{'server_fheader'}</b></td> </tr>\n";
182 print "<tr $cb> <td><table width=100%>\n";
183
184 local $i = 0;
185 foreach $t (@nis_files) {
186         local $f = &expand_vars($var->{uc($t)}->{'value'}, $var);
187         next if (!$f);
188         print "<tr>\n" if ($i%2 == 0);
189         print "<td><b>",&text('server_file', $text{"desc_$t"} ? $text{"desc_$t"}
190                                                               : $t),"</b></td>\n";
191         print "<td><input name=$t size=30 value='$f'></td>\n";
192         print "</tr>\n" if ($i++%2 == 1);
193         }
194 }
195
196 # parse_server_config()
197 # Parse and save the NIS server options
198 sub parse_server_config
199 {
200 local ($var, $rule) = &parse_yp_makefile();
201 if ($var->{'YPPWDDIR'}->{'value'} =~ /^\$\(shell/) {
202         # Value comes from the ypserv config file
203         local %ypserv;
204         &read_env_file("/etc/sysconfig/ypserv", \%ypserv);
205         $var->{'YPPWDDIR'}->{'value'} = $ypserv{'YPPWD_SRCDIR'};
206         }
207
208 $in{'minuid'} =~ /^\d+$/ || &error($text{'server_eminuid'});
209 $in{'mingid'} =~ /^\d+$/ || &error($text{'server_emingid'});
210 $in{'domain_auto'} || $in{'domain'} =~ /^[A-Za-z0-9\.\-]+$/ ||
211         &error($text{'server_edomain'});
212 $in{'type'} || &to_ipaddress($in{'slave'}) ||
213         &to_ip6address($in{'slave'}) || &error($text{'server_eslave'});
214 &update_makefile($var->{'MINUID'}, $in{'minuid'});
215 &update_makefile($var->{'MINGID'}, $in{'mingid'});
216 &update_makefile($var->{'NOPUSH'}, $in{'nopush'});
217 &update_makefile($var->{'B'}, $in{'b'});
218 &update_makefile($var->{'LOCALDOMAIN'}, $in{'domain_auto'} ? "`domainname`"
219                                                            : $in{'domain'});
220 &update_makefile($rule->{'all'}, join(" ", split(/\0/, $in{'tables'})), "");
221
222 foreach $t (@nis_files) {
223         local $old = &expand_vars($var->{uc($t)}->{'value'}, $var);
224         next if (!$old);
225         if ($old ne $in{$t}) {
226                 $in{$t} =~ /\S/ || &error(&text('server_efile', $text{"desc_$t"}));
227                 &update_makefile($var->{uc($t)}, $in{$t});
228                 }
229         }
230 &flush_file_lines();
231
232 &open_tempfile(SLAVES, ">/var/yp/ypservers");
233 foreach $s (split(/\s+/, $in{'slaves'})) {
234         &print_tempfile(SLAVES, "$s\n");
235         }
236 &close_tempfile(SLAVES);
237
238 local $init1 = &init_script("ypserv");
239 local $init2 = &init_script("yppasswdd");
240 local $init3 = &init_script("ypxfrd");
241 &system_logged("$init1 stop >/dev/null 2>&1");
242 &system_logged("$init2 stop >/dev/null 2>&1");
243 &system_logged("$init3 stop >/dev/null 2>&1");
244 if ($in{'boot'}) {
245         &init::enable_at_boot("ypserv");
246         &init::enable_at_boot("yppasswdd");
247         &init::enable_at_boot("ypxfrd");
248         }
249 else {
250         &init::disable_at_boot("ypserv");
251         &init::disable_at_boot("yppasswdd");
252         &init::disable_at_boot("ypxfrd");
253         }
254 if ($in{'boot'}) {
255         &system_logged("$init1 start >/dev/null 2>&1");
256         &system_logged("$init2 start >/dev/null 2>&1");
257         &system_logged("$init3 start >/dev/null 2>&1");
258         }
259 if ($in{'type'}) {
260         # Master server
261         delete($config{'slave'});
262         &apply_table_changes() if ($in{'boot'});
263         }
264 else {
265         $out = &backquote_logged("/usr/lib/yp/ypinit -s $in{'slave'} 2>&1");
266         if ($?) { &error("<tt>$out</tt>"); }
267         $config{'slave'} = $in{'slave'};
268         }
269 &write_file("$module_config_directory/config", \%config);
270 }
271
272 # get_server_mode()
273 # Returns 0 if the NIS server is inactive, 1 if active as a master, or 2 if
274 # active as a slave.
275 sub get_server_mode
276 {
277 if (&init::action_status("ypserv") != 2) {
278         return 0;
279         }
280 elsif ($config{'slave'}) {
281         return 2;
282         }
283 else {
284         return 1;
285         }
286 }
287
288 # list_nis_tables()
289 # Returns a list of structures of all NIS tables
290 sub list_nis_tables
291 {
292 local ($var, $rule) = &parse_yp_makefile();
293 if ($var->{'YPPWDDIR'}->{'value'} =~ /^\$\(shell/) {
294         # Value comes from the ypserv config file
295         local %ypserv;
296         &read_env_file("/etc/sysconfig/ypserv", \%ypserv);
297         $var->{'YPPWDDIR'}->{'value'} = $ypserv{'YPPWD_SRCDIR'};
298         }
299 local @rv;
300 local $dom = $var->{'LOCALDOMAIN'}->{'value'};
301 chop($dom = `domainname`) if ($dom =~ /`.*domainname`/);
302 local %file;
303 map { $file{uc($_)} = &expand_vars($var->{uc($_)}->{'value'}, $var) } @nis_files;
304 local @all = split(/\s+/, $rule->{'all'}->{'value'});
305 foreach $t (@all) {
306         local $table = { 'table' => $t,
307                          'index' => scalar(@rv),
308                          'domain' => $dom };
309         if ($t eq "passwd") {
310                 if ($var->{'MERGE_PASSWD'}->{'value'} eq 'true') {
311                         $table->{'type'} = 'passwd_shadow';
312                         $table->{'files'} = [ $file{'PASSWD'}, $file{'SHADOW'} ];
313                         }
314                 elsif (&indexof('shadow', @all) >= 0) {
315                         # Show separate shadow and passwd tables as one table
316                         $table->{'type'} = 'passwd_shadow_full';
317                         $table->{'files'} = [ $file{'PASSWD'}, $file{'SHADOW'} ];
318                         @all = grep { $_ ne 'shadow' } @all;
319                         }
320                 else {
321                         $table->{'type'} = 'passwd';
322                         $table->{'files'} = [ $file{'PASSWD'} ];
323                         }
324                 }
325         elsif ($t eq "group") {
326                 if ($var->{'MERGE_GROUP'}->{'value'} eq 'true') {
327                         $table->{'type'} = 'group_shadow';
328                         $table->{'files'} = [ $file{'GROUP'}, $file{'GSHADOW'} ];
329                         }
330                 else {
331                         $table->{'type'} = 'group';
332                         $table->{'files'} = [ $file{'GROUP'} ];
333                         }
334                 }
335         elsif ($t eq "netgrp") {
336                 $table->{'type'} = "netgroup";
337                 $table->{'files'} = [ $file{'NETGROUP'} ];
338                 }
339         elsif ($t eq "mail") {
340                 $table->{'type'} = "aliases";
341                 $table->{'files'} = [ $file{'ALIASES'} ];
342                 }
343         else {
344                 $table->{'type'} = $t;
345                 $table->{'files'} = [ $file{uc($t)} ];
346                 }
347         push(@rv, $table);
348         }
349 return @rv;
350 }
351
352 # apply_table_changes()
353 # Do whatever is necessary for the table text files to be loaded into
354 # the NIS server
355 sub apply_table_changes
356 {
357 &system_logged("(cd /var/yp ; make) >/dev/null 2>&1 </dev/null");
358 }
359
360 sub extra_config_files
361 {
362 return ( "/etc/defaultdomain", "/var/yp/ypservers" );
363 }
364
365 1;
366