Handle hostnames with upper-case letters
[webmin.git] / pserver / pserver-lib.pl
1 # pserver-lib.pl
2
3 BEGIN { push(@INC, ".."); };
4 use WebminCore;
5 &init_config();
6
7 $cvs_path = &has_command($config{'cvs'});
8 $cvs_port = 2401;
9 $cvs_inet_name = "cvspserver";
10 $has_xinetd = &foreign_check("xinetd");
11 $has_inetd = &foreign_check("inetd");
12 $passwd_file = "$config{'cvsroot'}/CVSROOT/passwd";
13 $readers_file = "$config{'cvsroot'}/CVSROOT/readers";
14 $writers_file = "$config{'cvsroot'}/CVSROOT/writers";
15 $cvs_config_file = "$config{'cvsroot'}/CVSROOT/config";
16
17 @features = ('passwd', 'access', 'config', 'cvsweb');
18 %access = &get_module_acl();
19 %featureprog = ( 'passwd' => 'list_passwd.cgi',
20                  'access' => 'edit_access.cgi',
21                  'config' => 'edit_config.cgi',
22                  'cvsweb' => 'cvsweb.cgi' );
23
24 # check_inetd()
25 # Find out if cvs is being run from inetd or xinetd
26 sub check_inetd
27 {
28 if ($has_xinetd) {
29         # Find an xinetd service on the CVS port, with the CVS command, or
30         # with the CVS name
31         &foreign_require("xinetd", "xinetd-lib.pl");
32         local @xic = &xinetd::get_xinetd_config();
33         local $x;
34         foreach $x (@xic) {
35                 next if ($x->{'name'} ne 'service');
36                 local $q = $x->{'quick'};
37                 if ($q->{'server'}->[0] eq $cvs_path ||
38                     $q->{'server'}->[0] eq $config{'cvs'} ||
39                     $port == $cvs_port ||
40                     $x->{'value'} eq $cvs_inet_name) {
41                         # Found the entry
42                         return { 'type' => 'xinetd',
43                                  'user' => $q->{'user'}->[0],
44                                  'command' => $q->{'server'}->[0],
45                                  'args' => $q->{'server'}->[0]." ".
46                                            $q->{'server_args'}->[0],
47                                  'active' => $q->{'disable'}->[0] ne 'yes',
48                                  'xinetd' => $x };
49                         }
50                 }
51         }
52 if ($has_inetd) {
53         # Find an inetd service on the CVS port, with the CVS command, or
54         # with the CVS name
55         local (%portmap, $s, $a, $i);
56         &foreign_require("inetd", "inetd-lib.pl");
57         foreach $s (&inetd::list_services()) {
58                 $portmap{$s->[1]} = $s;
59                 foreach $a (split(/\s+/, $s->[4])) {
60                         $portmap{$a} = $s;
61                         }
62                 }
63         foreach $i (&inetd::list_inets()) {
64                 if ($i->[8] eq $cvs_path || $i->[8] eq $config{'cvs'} ||
65                     $portmap{$i->[3]}->[2] == $cvs_port ||
66                     $i->[3] eq $cvs_inet_name) {
67                         # Found the entry
68                         return { 'type' => 'inetd',
69                                  'user' => $i->[7],
70                                  'command' => $i->[8],
71                                  'args' => $i->[9],
72                                  'active' => $i->[1],
73                                  'inetd' => $i };
74                         }
75                 }
76         }
77 return undef;
78 }
79
80 # list_passwords()
81 # List all CVS users
82 sub list_passwords
83 {
84 local @rv;
85 local $lnum = 0;
86 open(PASSWD, $passwd_file);
87 while(<PASSWD>) {
88         s/\r|\n//g;
89         s/#.*$//;
90         local @p = split(/:/, $_);
91         if (@p) {
92                 push(@rv, { 'user' => $p[0],
93                             'pass' => $p[1],
94                             'unix' => $p[2],
95                             'line' => $lnum,
96                             'index' => scalar(@rv) });
97                 }
98         $lnum++;
99         }
100 close(PASSWD);
101 return @rv;
102 }
103
104 sub create_password
105 {
106 local $lref = &read_file_lines($passwd_file);
107 push(@$lref, join(":", $_[0]->{'user'}, $_[0]->{'pass'}, $_[0]->{'unix'}));
108 &flush_file_lines();
109 }
110
111 sub modify_password
112 {
113 local $lref = &read_file_lines($passwd_file);
114 $lref->[$_[0]->{'line'}] =
115         join(":", $_[0]->{'user'}, $_[0]->{'pass'}, $_[0]->{'unix'});
116 &flush_file_lines();
117 }
118
119 sub delete_password
120 {
121 local $lref = &read_file_lines($passwd_file);
122 splice(@$lref, $_[0]->{'line'}, 1);
123 &flush_file_lines();
124 }
125
126 # get_cvs_config()
127 # Returns a list of values from the CVSROOT/config file
128 sub get_cvs_config
129 {
130 local @rv;
131 local $lnum = 0;
132 open(CONFIG, $cvs_config_file);
133 while(<CONFIG>) {
134         s/\s+$//;
135         s/^\s*#.*$//;
136         if (/^\s*([^\s=]+)\s*=\s*(.*)/) {
137                 push(@rv, { 'name' => $1,
138                             'value' => $2,
139                             'line' => $lnum,
140                             'index' => scalar(@rc) } );
141                 }
142         $lnum++;
143         }
144 close(CONFIG);
145 return @rv;
146 }
147
148 # find(name, &config)
149 sub find
150 {
151 local ($c, @rv);
152 foreach $c (@{$_[1]}) {
153         push(@rv, $c) if (lc($c->{'name'}) eq lc($_[0]));
154         }
155 return wantarray ? @rv : $rv[0];
156 }
157
158 # save_cvs_config(&config, name, value, [default])
159 sub save_cvs_config
160 {
161 local $lref = &read_file_lines($cvs_config_file);
162 local $old = &find($_[1], $_[0]);
163 if ($old && $_[2]) {
164         # Replacing an existing config line
165         $lref->[$old->{'line'}] = "$_[1]=$_[2]";
166         }
167 elsif ($old) {
168         # Deleting a config line (unless it already exists with the default)
169         if (!$_[3] || $old->{'value'} ne $_[3]) {
170                 splice(@$lref, $old->{'line'}, 1);
171                 local $c;
172                 foreach $c (@{$_[0]}) {
173                         $c->{'line'}-- if ($c->{'line'} > $old->{'line'});
174                         }
175                 }
176         }
177 elsif ($_[2]) {
178         # Adding a config line
179         push(@$lref, "$_[1]=$_[2]");
180         }
181 }
182
183 # get_cvs_version(&out)
184 # Returns the cvs command version number, or undef
185 sub get_cvs_version
186 {
187 local $out = `$config{'cvs'} -v`;
188 ${$_[0]} = $out;
189 if ($out =~ /CVS[^0-9\.]*([0-9\.]+)/) {
190         return $1;
191         }
192 else {
193         return undef;
194         }
195 }
196
197 @hist_chars = ( "F", "O", "E", "T", "C", "G", "U", "W", "A", "M", "R" );
198
199 1;
200