chiark / gitweb /
changes from Cambridge University (Ben Harris) unedited; will edit shortly
authorian <ian>
Sun, 15 Jun 2003 17:46:49 +0000 (17:46 +0000)
committerian <ian>
Sun, 15 Jun 2003 17:46:49 +0000 (17:46 +0000)
groupmanage/groupmanage

index 19416062e27e5d96011fd228978d8ab0ff060f79..9d9401955c549c2ba33a3d019ee6e2c4d938fad3 100755 (executable)
@@ -1,6 +1,11 @@
 #!/usr/bin/perl
 #
 # Copyright (C)1995-9 Ian Jackson <ijackson@chiark.greenend.org.uk>
+# Copyright (C) 1999, 2003
+#     Chancellor Masters and Scholars of the University of Cambridge
+#
+# Hacked by Ben Harris <bjh21@cam.ac.uk> in 1999 and 2003 for Unix
+# Support's own nefarious purposes.
 #
 # This is free software; you can redistribute it and/or modify it
 # under the terms of the GNU General Public License as published by
@@ -55,30 +60,33 @@ $groupname =~ m/^\w[-0-9A-Za-z]*$/ ||
 
 @ARGV || push(@ARGV,'--info');
 
-if ($ARGV[0] eq '--info') {
-    @ARGV == 1 || &usage('no arguments allowed after --info');
-    &p_out;
-    &load;
-    &checkexists;
-    &display;
-    &p_out;
-    exit(0);
-}
-
 $callinguser= exists $ENV{'USERV_UID'} ? $ENV{'USERV_UID'} : $<;
+$callingname = exists $ENV{'USERV_USER'} ? $ENV{'USERV_USER'} : getpwuid($<);
 
 %opt= ('user-create','0',
        'user-create-minunameu','5',
        'user-create-min','10000',
        'user-create-max','19999',
        'user-create-nameintitle','0',
-       'user-create-maxperu','5');
+       'user-create-maxperu','5',
+       'group-file','group',
+       'gtmp-file','gtmp',
+       'grouplist-file','grouplist',
+       'name-regexp','',
+       'admin-group','',
+       'finish-command','');
 %ovalid=  ('user-create','boolean',
            'user-create-minunameu','number',
            'user-create-min','number',
            'user-create-max','number',
            'user-create-nameintitle','boolean',
-           'user-create-maxperu','number');
+           'user-create-maxperu','number',
+           'group-file','string',
+           'gtmp-file','string',
+           'grouplist-file','string',
+           'name-regexp','string',
+           'admin-group','string',
+           'finish-command','string');
 
 sub ov_boolean {
     $cov= $_ eq 'yes' ? 1 :
@@ -90,6 +98,10 @@ sub ov_number {
     m/^[0-9]{1,10}$/ || &quit("groupmanage.conf:$.: bad numerical value");
 }
 
+sub ov_string {
+
+}
+
 open(GMC,"groupmanage.conf") || &quit("read groupmanage.conf: $!");
 while (<GMC>) {
     next if m/^\#/ || !m/\S/;
@@ -104,32 +116,56 @@ while (<GMC>) {
 }
 close(GMC);
 
+if ($ARGV[0] eq '--info') {
+    @ARGV == 1 || &usage('no arguments allowed after --info');
+    &p_out;
+    &load;
+    &checkexists;
+    &display;
+    &p_out;
+    exit(0);
+}
+
 sub naming {
     $callinguser || return;
     &p_out;
-    print(STDERR <<END) || &quit("write err re name: $!");
+    if ($opt{'user-create-minunameu'}) {
+       print(STDERR <<END) || &quit("write err re name: $!");
 groupmanage: groups you create must be named after you ...
     <usernamepart>-<identifier>
  You must quote at least $opt{'user-create-minunameu'} chars of your username $createby
  (or all of it if it is shorter).
 END
+    }
+    if ($opt{'name-regexp'}) {
+       print(STDERR <<END) || &quit("write err re name: $!");
+groupmanage: groups you create must match a pattern...
+  The pattern is the Perl regular expression /$opt{'name-regexp'}/.
+END
+    }
     exit(1);
 }
 
 if ($ARGV[0] eq '--create') {
     $opt{'user-create'} || !$callinguser ||
+        ($opt{'admin-group'} &&
+        (getgrnam($opt{'admin-group'}))[3] =~ /(^| )$callingname( |$)/) ||
         &quit("group creation by users disabled by administrator");
     length($groupname) <= 8 || &quit("group names must be 8 chars or fewer");
-    $groupname =~ m/^([-0-9A-Za-z]+)-([0-9a-z]+)$/ || &naming;
-    $upart= $1;
-    $idpart= $2;
     $!=0; (@pw= getpwuid($callinguser))
        || &quit("cannot get your passwd entry: $!");
     $createby= $pw[0];
-    $upart eq $createby ||
-        (length($upart) >= $opt{'user-create-minunameu'} &&
-         substr($createby,0,length($upart)) eq $upart)
-            || &naming;
+    if ($opt{'user-create-minunameu'}) {
+       $groupname =~ m/^([-0-9A-Za-z]+)-([0-9a-z]+)$/ || &naming;
+       $upart= $1;
+       $idpart= $2;
+       $upart eq $createby ||
+           (length($upart) >= $opt{'user-create-minunameu'} &&
+            substr($createby,0,length($upart)) eq $upart)
+               || &naming;
+    } else {
+       $groupname =~ m/${opt{'name-regexp'}}/ || &naming;
+    }
     $create= 1;
     shift(@ARGV);
 }
@@ -158,6 +194,8 @@ if ($create) {
 }
 
 &weare($owner) || grep(&weare($_),@managers) || !$callinguser ||
+    ($opt{'admin-group'} &&
+     (getgrnam($opt{'admin-group'}))[3] =~ /(^| )$callingname( |$)/) ||
     &quit("you may not manage $groupname");
 
 $action= 'none';
@@ -227,14 +265,17 @@ $groupfile[$groupfileix]=
     "$groupname:$password:$gid:".join(',',@members)."\n";
 $grouplist[$grouplistix]=
     "$groupname:$description:$owner:".join(',',@managers).":$homedir\n";
-&save('group',@groupfile);
-&save('grouplist',@grouplist);
-unlink('gtmp') || &quit("unlock group (remove gtmp): $!");
+&save($opt{'group-file'},@groupfile);
+&save($opt{'grouplist-file'},@grouplist);
+if ($opt{'finish-command'}) {
+    !system($opt{'finish-command'}) || &quit("finish-command: $!");
+}
+unlink($opt{'gtmp-file'}) || &quit("unlock group (remove gtmp): $!");
 &p_out;
 exit(0);
 
 sub load {
-    open(GF,"< group") || &quit("read group: $!");
+    open(GF,"< $opt{'group-file'}") || &quit("read group: $!");
     @groupfile=<GF>; close(GF);
     $groupfileix=-1;
     for ($i=0; $i<=$#groupfile; $i++) {
@@ -250,7 +291,7 @@ sub load {
         $gid= $3;
         @members= split(/,/,$4);
     }
-    open(GL,"< grouplist") || &quit("read grouplist: $!");
+    open(GL,"< $opt{'grouplist-file'}") || &quit("read grouplist: $!");
     @grouplist=<GL>; close(GL);
     $grouplistix=-1;
     for ($i=0; $i<=$#grouplist; $i++) {
@@ -299,14 +340,27 @@ sub quit {
 }
 
 sub lock {
-    link('group','gtmp') || &quit("create gtmp: $!");
+    # NFS-safe Locking per Linux open(2)
+    my($hostname) = `hostname`;
+    chomp($hostname);
+    my($hitching_post) = "$opt{'gtmp-file'}.$hostname.$$";
+    open(LOCK, ">$hitching_post") || die "$hitching_post: $!";
+    close(LOCK);
+    link($hitching_post, $opt{'gtmp-file'});
+    if ((stat($hitching_post))[3] != 2) {
+       close(OUT);
+       unlink($hitching_post);
+       &quit("group file locked -- giving up...");
+    }
+    unlink($hitching_post);
+#    link($opt{'group-file'},$opt{'gtmp-file'}) || &quit("create gtmp: $!");
     $locked++;
 }
 
 sub unlock {
     return unless $locked;
     $locked--;
-    unlink('gtmp') || warn("unlock group file (remove gtmp): $!\n");
+    unlink($opt{'gtmp-file'}) || warn("unlock group file (remove gtmp): $!\n");
 }
 
 sub display {