Skip site navigation (1)Skip section navigation (2)
Date:      23 Nov 2000 21:58:26 -0000
From:      Peter Pentchev <roam@orbitel.bg>
To:        FreeBSD-gnats-submit@freebsd.org
Subject:   bin/23052: [PATCH] rmuser fails to remove at jobs
Message-ID:  <20001123215826.1379.qmail@ringworld.nanolink.com>

next in thread | raw e-mail | index | archive | help

>Number:         23052
>Category:       bin
>Synopsis:       [PATCH] rmuser fails to remove at jobs
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Thu Nov 23 14:00:01 PST 2000
>Closed-Date:
>Last-Modified:
>Originator:     Peter Pentchev
>Release:        FreeBSD 4.2-STABLE i386
>Organization:
Orbitel JSCo.
>Environment:

RELENG_3, RELENG_4, HEAD

>Description:

The /usr/sbin/rmuser Perl script includes a function for removing
the late user's at-scheduled jobs.  However, that code has been subtly
wrong from the start, and for quite some time now has simply not worked.

It scans the /var/at/jobs directory for files belonging to the user
being removed, and then passes each filename as an argument to atrm.
However, atrm no longer accepts such filenames as arguments - it wants
a job ID.  Failing to find the "ID" specified, atrm quietly does nothing,
leaving the scheduled job to be executed, and not alerting the adminstrator
or whoever it is invoking rmuser.

Submitted by:	Mike Sellenschuetter <mike.sellenschuetter@bankofamerica.com>
		in a mail to -security;
		Message-Id: <8625699E.0061FCDC.00@dalnsd40.bankofamerica.com>

>How-To-Repeat:

[root@ringworld:v4 ~]# pw adduser test
[root@ringworld:v4 ~]# echo 'at -f /dev/null now + 1 hour' | su test
Job 24 will be executed using /bin/sh
[root@ringworld:v4 ~]# atq
Date                    Owner   Queue   Job#
00:45:00 11/24/00       test    c       24
[root@ringworld:v4 ~]# rmuser test
Matching password entry:

test:*:1007:1007::0:0:User &:/home/test:/bin/sh

Is this the entry you wish to remove? y
/usr/sbin/rmuser: Informational: Home /home/test is not a directory, so it won't
 be removed
Removing user's at jobs: c0001800f7f5d5 done.
Updating password file, updating databases, done.
Updating group file: (removing group test -- personal group is empty) done.
Removing user's incoming mail file /var/mail/test: done.
Removing files belonging to test from /tmp: done.
Removing files belonging to test from /var/tmp: done.
Removing files belonging to test from /var/tmp/vi.recover: done.
[root@ringworld:v4 ~]# atq
Date                    Owner   Queue   Job#
00:45:00 11/24/00       ???     c       24
[root@ringworld:v4 ~]#

>Fix:

Although it is trivial to extract the job ID from the filename - in the
example given, the job ID was 24, and the filename contained a 00018
hex string - I do not really think this is the way to go.  There's no
telling when the at job filename format shall be changed again, and it is
very easy to miss updating rmuser if/when that should happen.

Attached instead are two patches - one against RELENG_4, another against
-current - which add two additional subroutines to invoke atq, parse its
output, find the jobs belonging to this user, then invoke atrm and kill
off the correct job ID's.

The patch against RELENG_4 also applies cleanly to RELENG_3.  I think
this one might well be worth MFC'ing into 3.x.

Here's the diff against -current..

Index: rmuser.perl
===================================================================
RCS file: /home/ncvs/src/usr.sbin/adduser/rmuser.perl,v
retrieving revision 1.11
diff -u -r1.11 rmuser.perl
--- rmuser.perl	2000/11/21 05:52:35	1.11
+++ rmuser.perl	2000/11/23 21:27:47
@@ -199,7 +199,7 @@
 # Remove the user's at jobs, if any
 # (probably also needs to be done before password databases are updated)
 
-&remove_at_jobs($login_name, $uid);
+&remove_at_jobs($login_name);
 
 #
 # Kill all the user's processes
@@ -464,32 +464,75 @@
     printf STDERR " done.\n";
 }
 
-sub remove_at_jobs {
-    local($login_name, $uid) = @_;
-    local($i, $owner, $found);
-
-    $found = 0;
-    opendir(ATDIR, $atjob_dir) || return;
-    while ($i = readdir(ATDIR)) {
-	next if $i eq '.';
-	next if $i eq '..';
-	next if $i eq '.lockfile';
 
-	$owner = (stat("$atjob_dir/$i"))[4]; # UID
-	if ($uid == $owner) {
-	    if (!$found) {
-		print STDERR "Removing user's at jobs:";
-		$found = 1;
-	    }
-	    # Use atrm to remove the job
-	    print STDERR " $i";
-	    system('/usr/bin/atrm', $i);
+sub invoke_atq {
+    local *ATQ;
+    my($user) = (shift || "");
+    my($path_atq) = "/usr/bin/atq";
+    my(@at) = ();
+    my($pid, $line);
+    
+    return @at if ($user eq "");
+    
+    if (!defined($pid = open(ATQ, "-|"))) {
+	die("creating pipe to atq: $!\n");
+    } elsif ($pid == 0) {
+	exec($path_atq, $user);
+	die("executing $path_atq: $!\n");
+    }
+    
+    while(defined($_ = <ATQ>)) {
+	chomp;
+	if (/^\d\d:\d\d:\d\d\s+\d\d\/\d\d\/\d\d\s+(\S+)\s+\S+\s+(\d+)$/) {
+	    push(@at, $2) if ($1 eq $user);
 	}
     }
-    closedir(ATDIR);
-    if ($found) {
-	print STDERR " done.\n";
+    close ATQ;
+    return @at;
+}
+
+sub invoke_atrm {
+    local *ATRM;
+    my($user) = (shift || "");
+    my($path_atrm) = "/usr/bin/atrm";
+    my(@jobs) = @_;
+    my($pid);
+    my($txt) = "";
+    
+    return "Invalid arguments" if (($user eq "") || ($#jobs == -1));
+    
+    if (!defined($pid = open(ATRM, "-|"))) {
+	die("creating pipe to atrm: $!\n");
+    } elsif ($pid == 0) {
+	exec($path_atrm, $user, @jobs);
+    }
+    
+    while(defined($_ = <ATRM>)) {
+	$txt .= $_;
     }
+    close ATRM;
+    return $txt;
+}
+
+sub remove_at_jobs {
+    my($user) = (shift || "");
+    my(@at, $atrm);
+    
+    return 1 if ($user eq "");
+    
+    print STDERR "Removing user's at jobs:";
+    @at = invoke_atq($user);
+    return 0 if ($#at == -1);
+    
+    print STDERR " @at:";
+    $atrm = invoke_atrm($user, @at);
+    if ($atrm ne "") {
+	print STDERR " -- $atrm\n";
+	return 1;
+    }
+    
+    print STDERR "done.\n";
+    return 0;
 }
 
 sub resolvelink {

==================================================================

And here's the diff against RELENG_4..

Index: rmuser.perl
===================================================================
RCS file: /home/ncvs/src/usr.sbin/adduser/rmuser.perl,v
retrieving revision 1.8.2.1
diff -u -r1.8.2.1 rmuser.perl
--- rmuser.perl	2000/03/20 13:00:36	1.8.2.1
+++ rmuser.perl	2000/11/23 21:25:50
@@ -202,7 +202,7 @@
 # Remove the user's at jobs, if any
 # (probably also needs to be done before password databases are updated)
 
-&remove_at_jobs($login_name, $uid);
+&remove_at_jobs($login_name);
 
 #
 # Kill all the user's processes
@@ -495,32 +495,75 @@
     printf STDERR " done.\n";
 }
 
-sub remove_at_jobs {
-    local($login_name, $uid) = @_;
-    local($i, $owner, $found);
-
-    $found = 0;
-    opendir(ATDIR, $atjob_dir) || return;
-    while ($i = readdir(ATDIR)) {
-	next if $i eq '.';
-	next if $i eq '..';
-	next if $i eq '.lockfile';
 
-	$owner = (stat("$atjob_dir/$i"))[4]; # UID
-	if ($uid == $owner) {
-	    if (!$found) {
-		print STDERR "Removing user's at jobs:";
-		$found = 1;
-	    }
-	    # Use atrm to remove the job
-	    print STDERR " $i";
-	    system('/usr/bin/atrm', $i);
+sub invoke_atq {
+    local *ATQ;
+    my($user) = (shift || "");
+    my($path_atq) = "/usr/bin/atq";
+    my(@at) = ();
+    my($pid, $line);
+    
+    return @at if ($user eq "");
+    
+    if (!defined($pid = open(ATQ, "-|"))) {
+	die("creating pipe to atq: $!\n");
+    } elsif ($pid == 0) {
+	exec($path_atq, $user);
+	die("executing $path_atq: $!\n");
+    }
+    
+    while(defined($_ = <ATQ>)) {
+	chomp;
+	if (/^\d\d:\d\d:\d\d\s+\d\d\/\d\d\/\d\d\s+(\S+)\s+\S+\s+(\d+)$/) {
+	    push(@at, $2) if ($1 eq $user);
 	}
     }
-    closedir(ATDIR);
-    if ($found) {
-	print STDERR " done.\n";
+    close ATQ;
+    return @at;
+}
+
+sub invoke_atrm {
+    local *ATRM;
+    my($user) = (shift || "");
+    my($path_atrm) = "/usr/bin/atrm";
+    my(@jobs) = @_;
+    my($pid);
+    my($txt) = "";
+    
+    return "Invalid arguments" if (($user eq "") || ($#jobs == -1));
+    
+    if (!defined($pid = open(ATRM, "-|"))) {
+	die("creating pipe to atrm: $!\n");
+    } elsif ($pid == 0) {
+	exec($path_atrm, $user, @jobs);
+    }
+    
+    while(defined($_ = <ATRM>)) {
+	$txt .= $_;
     }
+    close ATRM;
+    return $txt;
+}
+
+sub remove_at_jobs {
+    my($user) = (shift || "");
+    my(@at, $atrm);
+    
+    return 1 if ($user eq "");
+    
+    print STDERR "Removing user's at jobs:";
+    @at = invoke_atq($user);
+    return 0 if ($#at == -1);
+    
+    print STDERR " @at:";
+    $atrm = invoke_atrm($user, @at);
+    if ($atrm ne "") {
+	print STDERR " -- $atrm\n";
+	return 1;
+    }
+    
+    print STDERR "done.\n";
+    return 0;
 }
 
 sub resolvelink {

>Release-Note:
>Audit-Trail:
>Unformatted:


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20001123215826.1379.qmail>