1 #!/usr/perl5/bin/perl -w
5 # The contents of this file are subject to the terms of the
6 # Common Development and Distribution License, Version 1.0 only
7 # (the "License"). You may not use this file except in compliance
10 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
11 # or http://www.opensolaris.org/os/licensing.
12 # See the License for the specific language governing permissions
13 # and limitations under the License.
15 # When distributing Covered Code, include this CDDL HEADER in each
16 # file and include the License file at usr/src/OPENSOLARIS.LICENSE.
17 # If applicable, add the following below this CDDL HEADER, with the
18 # fields enclosed by brackets "[]" replaced with your own identifying
19 # information: Portions Copyright [yyyy] [name of copyright owner]
24 # Copyright 2004 Sun Microsystems, Inc. All rights reserved.
25 # Use is subject to license terms.
27 #ident "%Z%%M% %I% %E% SMI"
37 use Getopt
::Long
qw(:config no_ignore_case bundling);
38 use POSIX
qw(locale_h getuid getgid);
39 use Sun
::Solaris
::Utils
qw(textdomain gettext);
40 use Sun
::Solaris
::Project
qw(:ALL :PRIVATE);
43 # Print a usage message and exit.
48 my $prog = basename
($0);
49 my $space = ' ' x
length($prog);
50 print(STDERR
"$prog: @msg\n") if (@msg);
51 printf(STDERR gettext
(
52 " %s [-n] [-f filename] [-p projid [-o]] [-c comment]\n".
53 " %s [-U user[,user...]] [-G group[,group...]]\n".
54 " %s [-K name[=value[,value...]]] project\n"),
55 $prog, $space, $space);
60 # Print a list of error messages and exit.
65 my $prog = basename
($0) . ': ';
66 foreach my $err (@_) {
67 my ($e, $fmt, @args) = @
$err;
68 printf(STDERR
$prog . $fmt . "\n", @args);
74 # Main routine of script.
76 # Set the message locale.
78 setlocale
(LC_ALL
, '');
79 textdomain
(TEXT_DOMAIN
);
82 # Process command options and do some initial command-line validity checking.
85 my $projfile = &PROJF_PATH
;
94 GetOptions
("f=s" => \
$projfile,
101 "K=s" => \
@opt_K) || usage
();
103 usage
(gettext
('Invalid command-line arguments')) if (@ARGV != 1);
104 usage
(gettext
('No project name specified')) if (! defined($ARGV[0]));
105 usage
(gettext
('-o requires -p projid to be specified'))
106 if (defined($opt_o) && ! defined($opt_p));
113 # Fabricate an unique temporary filename.
114 $tmpprojf = $projfile . ".tmp.$$";
118 if (defined($opt_n)) {
119 $flags->{'validate'} = 'false';
121 $flags->{'validate'} = 'true';
124 $flags->{'res'} = 'true';
125 $flags->{'dup'} = 'true';
128 my ($mode, $uid, $gid);
133 # Read the project file. sysopen() is used so we can control the file mode.
134 if (! sysopen($pfh, $projfile, O_RDONLY
)) {
135 if ($! == Errno
::ENOENT
) {
141 error
([10, gettext
('Cannot open %s: %s'), $projfile, $!]);
144 ($mode, $uid, $gid) = (stat($pfh))[2,4,5];
146 ($ret, $pf) = projf_read
($pfh, $flags);
152 $maxpjid = $_->{'projid'} if ($_->{'projid'} > $maxpjid);
160 $proj->{'name'} = '';
161 $proj->{'projid'} = $maxpjid + 1;;
162 $proj->{'comment'} = '';
163 $proj->{'userlist'} = [];
164 $proj->{'grouplist'} = [];
165 $proj->{'attributelist'} = [];
166 $proj->{'modified'} = 'true';
169 # Update the record as appropriate.
172 ($ret, $value) = projent_parse_name
($pname);
174 push(@
$err, @
$value);
176 $proj->{'name'} = $value;
177 if (!defined($opt_n)) {
179 projent_validate_unique_name
($proj, $pf);
181 push(@
$err, @
$tmperr);
186 # Apply any changes due to options.
187 if (defined($opt_p)) {
189 my ($ret, $value) = projent_parse_projid
($opt_p);
191 push(@
$err, @
$value);
193 $proj->{'projid'} = $value;
194 if (!defined($opt_n)) {
196 projent_validate_projid
($value, {});
198 push(@
$err, @
$tmperr);
201 if ((!defined($opt_n)) && (!defined($opt_o))) {
203 projent_validate_unique_id
($proj, $pf);
205 push(@
$err, @
$tmperr);
210 if (defined($opt_c)) {
212 my ($ret, $value) = projent_parse_comment
($opt_c);
214 push(@
$err, @
$value);
216 $proj->{'comment'} = $value;
219 if (defined($opt_U)) {
222 my ($ret, $list) = projent_parse_users
($opt_U,
223 { 'allowspaces' => 1 });
227 @sortlist = sort(@
$list);
228 $proj->{'userlist'} = \
@sortlist;
231 if (defined($opt_G)) {
234 my ($ret, $list) = projent_parse_groups
($opt_G,
235 { 'allowspaces' => 1 });
239 @sortlist = sort(@
$list);
240 $proj->{'grouplist'} = \
@sortlist;
248 # Support multiple instances of -K.
249 foreach $attrib (@opt_K) {
251 my ($ret, $list) = projent_parse_attributes
($attrib,
252 {'allowunits' => 1});
256 push(@attriblist, @
$list);
261 @sortlist = sort { $a->{'name'} cmp $b->{'name'} } @attriblist;
262 $proj->{'attributelist'} = \
@sortlist;
265 # Validate project entry changes.
266 if (!defined($opt_n)) {
267 ($ret, $tmperr) = projent_validate
($proj, $flags);
269 push(@
$err, @
$tmperr);
276 # Write out the project file.
278 sysopen($pfh, $tmpprojf, O_WRONLY
| O_CREAT
| O_EXCL
, $mode) ||
279 error
([10, gettext
('Cannot create %s: %s'), $tmpprojf, $!]);
280 projf_write
($pfh, $pf);
282 if (!chown($uid, $gid, $tmpprojf)) {
284 error
([10, gettext
('Cannot set ownership of %s: %s'),
287 if (! rename($tmpprojf, $projfile)) {
289 error
([10, gettext
('cannot rename %s to %s: %s'),
290 $tmpprojf, $projfile, $!]);