Handle hostnames with upper-case letters
[webmin.git] / nis / aix-lib.pl
1 # aix-lib.pl
2 # NIS functions for aix, based on the solaris library
3
4 $binding_dir = "/var/yp/binding";
5 $yp_makefile = "/var/yp/Makefile";
6
7 # get_nis_support()
8 # Returns 0 for no support, 1 for client only, 2 for server and 3 for both
9 sub get_nis_support
10 {
11 local $rv;
12 local $result;
13
14 $result=`lssrc -s ypbind |grep -q active && echo ok`;
15
16 $rv += 1 if ($result == "ok");
17
18 $result=`lssrc -s ypserv |grep -q active && echo ok`;
19 $rv += 2 if ($result == "ok");
20 return $rv;
21 }
22
23 # get_client_config()
24 # Returns a hash ref containg details of the client's NIS settings
25 sub get_client_config
26 {
27 local $nis;
28 open(DOM, "/usr/bin/domainname |") ||die("could not run /usr/bin/domainname : $!");
29 chomp($nis->{'domain'} = <DOM>);
30 close(DOM);
31 if ($nis->{'domain'}) {
32         if (open(SRV, "$binding_dir/$nis->{'domain'}/ypservers")) {
33                 while(<SRV>) {
34                         s/\r|\n//g;
35                         push(@{$nis->{'servers'}}, $_);
36                         }
37                 close(SRV);
38                 }
39         else {
40                 $nis->{'broadcast'} = 1;
41                 }
42         }
43 return $nis;
44 }
45
46 # save_client_config(&config)
47 # Saves and applies the NIS client configuration in the give hash.
48 # Returns an error message if any, or undef on success.
49 sub save_client_config
50 {
51 if ($_[0]->{'domain'}) {
52         # Check if the servers are in /etc/hosts
53         local @s = @{$_[0]->{'servers'}};
54         &foreign_require("net", "net-lib.pl");
55         foreach $s (@s) {
56                 local $found = 0;
57                 foreach $h (&foreign_call("net", "list_hosts")) {
58                         $found++ if (&indexof($s, @{$h->{'hosts'}}) >= 0);
59                         }
60                 return &text("client_ehosts", $s) if (!$found);
61                 }
62
63         # Write the files
64         &logged_system("/usr/bin/domainname \"$_[0]->{'domain'}\"");
65         mkdir("$binding_dir/$_[0]->{'domain'}", 0755);
66         if (@s) {
67                 &open_tempfile(SRV, ">$binding_dir/$_[0]->{'domain'}/ypservers");
68                 foreach $s (@s) {
69                         &print_tempfile(SRV, "$s\n");
70                         }
71                 &close_tempfile(SRV);
72                 }
73         else {
74                 unlink("$binding_dir/$_[0]->{'domain'}/ypservers");
75                 }
76         }
77 else {
78         &logged_system("/usr/bin/domainname ''");
79         }
80
81 # Apply by running ypstop and ypstart
82 &system_logged("(stopsrc -s ypserv ; /usr/bin/domainname \"$_[0]->{'domain'}\" ; startsrc -s ypserv ) > /dev/null 2>&1 ");
83 sleep(2);
84 if ($_[0]->{'domain'}) {
85         local $out = `ypwhich 2>&1`;
86         if ($? || $out =~ /not\s+bound/i || $out =~ /can't\s+communicate/i) {
87                 system("(stopsrc -s ypserv) >/dev/null 2>&1");
88                 return $text{'client_eypwhich'};
89                 }
90         }
91 }
92
93 @nis_tables = ( "passwd", "group", "hosts", "ethers", "networks", "rpc",
94                 "services", "protocols", "netgroup", "bootparams", "aliases",
95                 "publickey", "netid", "netmasks", "c2secure", "timezone",
96                 "auto.master", "auto.home" );
97
98 # show_server_config()
99 # Display a form for editing NIS server options
100 sub show_server_config
101 {
102 local ($var, $rule) = &parse_yp_makefile();
103 local $dom = `domainname`; chop($dom);
104
105 print "<tr> <td><b>$text{'server_boot'}</b></td> <td>\n";
106 if ($dom && -d "/var/yp/$dom") {
107         print "<i>$text{'server_already'}</i>\n";
108         }
109 else {
110         print "<input type=radio name=boot value=1 > $text{'yes'}\n";
111         print "<input type=radio name=boot value=0 checked > $text{'no'}\n";
112         }
113 print "</td>\n";
114
115 print "<td><b>$text{'server_domain'}</b></td>\n";
116 printf "<td><input type=radio name=domain_def value=1 %s> %s\n",
117         $dom ? '' : 'checked', $text{'server_none'};
118 printf "<input type=radio name=domain_def value=0 %s>\n",
119         $dom ? 'checked' : '';
120 printf "<input name=domain size=35 value='%s'></td> </tr>\n", $dom;
121
122 print "<tr> <td><b>$text{'server_type'}</b></td>\n";
123 printf "<td colspan=3><input type=radio name=type value=1 %s> %s\n",
124         $config{'slave'} ? '' : 'checked', $text{'server_master'};
125 printf "<input type=radio name=type value=0 %s> %s\n",
126         $config{'slave'} ? 'checked' : '', $text{'server_slave'};
127 printf "<input name=slave size=30 value='%s'></td> </tr>\n", $config{'slave'};
128
129 print "<tr> <td colspan=4><i>$text{'server_aix'}</i></td> </tr>\n";
130
131 print "</table></td></tr></table><p>\n";
132 print "<table border width=100%>\n";
133 print "<tr $tb> <td><b>$text{'server_mheader'}</b></td> </tr>\n";
134 print "<tr $cb> <td><table width=100%>\n";
135
136 local %inall;
137 local @all = split(/\s+/, $rule->{'all'}->{'value'});
138 map { $inall{$_}++ } @all;
139 print "<tr> <td rowspan=4 valign=top><b>$text{'server_tables'}</b></td>\n";
140 print "<td rowspan=4><select multiple size=6 name=tables>\n";
141 foreach $t (&unique(@nis_tables, @all)) {
142         printf "<option value=%s %s>%s\n",
143                 $t, $inall{$t} ? 'selected' : '', $t;
144         }
145 print "</select></td>\n";
146
147 print "<td><b>$text{'server_dns'}</b></td>\n";
148 printf "<td><input type=radio name=b value='-b' %s> %s\n",
149         $var->{'B'}->{'value'} eq '-b' ? 'checked' : '', $text{'yes'};
150 printf "<input type=radio name=b value='' %s> %s</td> </tr>\n",
151         $var->{'B'}->{'value'} eq '-b' ? '' : 'checked', $text{'no'};
152
153 print "<tr> <td><b>$text{'server_push'}</b></td>\n";
154 printf "<td><input type=radio name=nopush value='\"\"' %s> %s\n",
155         $var->{'NOPUSH'}->{'value'} eq 'true' ? '' : 'checked', $text{'yes'};
156 printf "<input type=radio name=nopush value=true %s> %s</td> </tr>\n",
157         $var->{'NOPUSH'}->{'value'} eq 'true' ? 'checked' : '', $text{'no'};
158
159 print "<tr> <td><b>$text{'server_dir'}</b></td>\n";
160 printf "<td><input name=dir size=30 value='%s'> %s</td> </tr>\n",
161         $var->{'DIR'}->{'value'}, &file_chooser_button("dir", 0);
162
163 print "<tr> <td><b>$text{'server_pwdir'}</b></td>\n";
164 printf "<td><input name=pwdir size=30 value='%s'> %s</td> </tr>\n",
165         $var->{'PWDIR'}->{'value'}, &file_chooser_button("pwdir", 0);
166 }
167
168 # parse_server_config()
169 # Parse and save the NIS server options
170 sub parse_server_config
171 {
172 local ($var, $rule) = &parse_yp_makefile();
173 $in{'domain_def'} || $in{'domain'} =~ /^[A-Za-z0-9\.\-\_]+$/ ||
174         &error(&text('server_edomain', $in{'domain'}));
175 if ($in{'boot'} && $in{'domain_def'}) {
176         &error($text{'server_ebootdom'});
177         }
178 $in{'type'} || &to_ipaddress($in{'slave'}) ||
179         &to_ip6address($in{'slave'}) || &error($text{'server_eslave'});
180 -d $in{'dir'} || &error($text{'server_edir'});
181 -d $in{'pwdir'} || &error($text{'server_epwdir'});
182 &update_makefile($var->{'NOPUSH'}, $in{'nopush'});
183 &update_makefile($var->{'B'}, $in{'b'});
184 &update_makefile($rule->{'all'}, join(" ", split(/\0/, $in{'tables'})), "");
185 &update_makefile($var->{'DIR'}, $in{'dir'});
186 &update_makefile($var->{'PWDIR'}, $in{'pwdir'});
187 &flush_file_lines();
188
189 if ($in{'domain_def'}) {
190         &system_logged("domainname \"\" >/dev/null 2>&1");
191         }
192 else {
193         local $old = `domainname`; chop($old);
194         &system_logged("chypdom -B \"$in{'domain'}\"");
195         &system_logged("domainname \"$in{'domain'}\" >/dev/null 2>&1");
196         if ($in{'boot'}) {
197                 # Create the domain directory
198                 mkdir("/var/yp/$in{'domain'}", 0755);
199                 &system_logged("rm -f /var/yp/*.time"); # force a remake
200                 }
201         }
202
203 if ($in{'type'}) {
204         # Master server
205         delete($config{'slave'});
206         &apply_table_changes()
207                 if (!$in{'domain_def'} && -d "/var/yp/$in{'domain'}");
208         }
209 else {
210         local $temp = &transname();
211         open(TEMP, ">$temp");
212         print TEMP "n\ny\n";
213         close(TEMP);
214         $out = &backquote_logged("/usr/sbin/ypinit -s $in{'slave'} <$temp 2>&1");
215         unlink($temp);
216         if ($?) { &error("<tt>$out</tt>"); }
217         $config{'slave'} = $in{'slave'};
218         }
219 &write_file("$module_config_directory/config", \%config);
220 &system_logged("stopsrc -g yp >/dev/null 2>&1");
221 &system_logged("startsrc -g yp >/dev/null 2>&1");
222 }
223
224 # get_server_mode()
225 # Returns 0 if the NIS server is inactive, 1 if active as a master, or 2 if
226 # active as a slave.
227 sub get_server_mode
228 {
229 local $dom = `domainname`; chop($dom);
230 return !$dom ? 0 : $config{'slave'} ? 2 : 1;
231 }
232
233 # parse_yp_makefile()
234 # Returns hashes of makefile variables and rules
235 sub parse_yp_makefile
236 {
237 # First parse joined lines
238 local $lnum = 0;
239 local (@lines, $llast);
240 open(MAKE, $yp_makefile);
241 while(<MAKE>) {
242         s/\r|\n//g;
243         local $slash = (s/\\$//);
244         s/#.*$//;
245         if ($llast) {
246                 $llast->{'value'} .= " $_";
247                 $llast->{'eline'} = $lnum;
248                 }
249         else {
250                 push(@lines, { 'value' => $_,
251                                'line' => $lnum,
252                                'eline' => $lnum });
253                 }
254         $llast = $slash ? $lines[$#lines] : undef;
255         $lnum++;
256         }
257 close(MAKE);
258
259 # Then look for variables and rules
260 local ($i, %var, %rule);
261 for($i=0; $i<@lines; $i++) {
262         if ($lines[$i]->{'value'} =~ /^\s*(\S+)\s*=\s*(.*)/) {
263                 # Found a variable
264                 $var{$1} = { 'name' => $1,
265                              'value' => $2,
266                              'type' => 0,
267                              'line' => $lines[$i]->{'line'},
268                              'eline' => $lines[$i]->{'eline'} };
269                 }
270         elsif ($lines[$i]->{'value'} =~ /^\s*(\S+):\s*(.*)/) {
271                 # Found a makefile rule
272                 $rule{$1} = { 'name' => $1,
273                               'value' => $2,
274                               'type' => 1,
275                               'code' => $lines[$i+1]->{'value'},
276                               'line' => $lines[$i]->{'line'},
277                               'eline' => $lines[$i+1]->{'eline'} };
278                 $i++;
279                 }
280         }
281 return ( \%var, \%rule );
282 }
283
284 # expand_vars(string, &vars)
285 sub expand_vars
286 {
287 local $rv = $_[0];
288 while($rv =~ /^(.*)\$\(([A-Za-z0-9_]+)\)(.*)$/) {
289         $rv = $1.$_[1]->{$2}->{'value'}.$3;
290         }
291 return $rv;
292 }
293
294 # update_makefile(&old, value, [value]);
295 sub update_makefile
296 {
297 local $lref = &read_file_lines($yp_makefile);
298 local @n;
299 if ($_[0]->{'type'} == 0) {
300         @n = ( "$_[0]->{'name'} = $_[1]" );
301         }
302 else {
303         @n = ( "$_[0]->{'name'}: $_[1]", $_[2] );
304         }
305 splice(@$lref, $_[0]->{'line'}, $_[0]->{'eline'} - $_[0]->{'line'} + 1, @n);
306 }
307
308 # apply_table_changes()
309 # Do whatever is necessary for the table text files to be loaded into
310 # the NIS server
311 sub apply_table_changes
312 {
313 &system_logged("(cd /var/yp ; /usr/bin/make) >/dev/null 2>&1 </dev/null");
314 }
315
316 # list_nis_tables()
317 # Returns a list of structures of all NIS tables
318 sub list_nis_tables
319 {
320 local @rv;
321 local ($var, $rule) = &parse_yp_makefile();
322 local $dom = `domainname`; chop($dom);
323 local @all = split(/\s+/, $rule->{'all'}->{'value'});
324 foreach $t (@all) {
325         local $table = { 'table' => $t,
326                          'index' => scalar(@rv),
327                          'domain' => $dom };
328         local $rt = $rule->{"$t.time"};
329         local @files = split(/\s+/, $rt->{'value'});
330         @files = map { &expand_vars($_, $var) } @files;
331         $table->{'files'} = \@files;
332         $table->{'type'} = $t eq 'passwd' && @files > 1 ? 'passwd_shadow' :
333                            $t;
334         push(@rv, $table);
335         }
336 return @rv;
337 }
338
339 sub show_server_security
340 {
341 }
342
343 sub parse_server_security
344 {
345 &system_logged("stopsrc -g yp  >/dev/null 2>&1");
346 &system_logged("startsrc -g yp >/dev/null 2>&1");
347 }
348
349 1;
350