chall, recursive chown, chgrp - (nf)
utzoo!decvax!harpo!eagle!mhuxt!mhuxj!mhuxa!houxm!ihnp4!ixn5c!inuxc!pur-ee!uiucdcs!adams
utzoo!decvax!harpo!eagle!mhuxt!mhuxj!mhuxa!houxm!ihnp4!ixn5c!inuxc!pur-ee!uiucdcs!adams
Fri Apr 22 22:39:05 AEST 1983
#N:uiucdcs:12600008:000:8218
uiucdcs!adams Apr 22 17:58:00 1983
What follows is the source and man page (in a Bourne RunMe script)
for chall, a recursive chown/chgrp. Syntax is as follows:
% chall owner group dir1 dir2 ...
E.g.,
% chall uucp bin /usr/lib/uucp /usr/spool/uucp
The example appropriately changes the ownership (and group ownship)
of /usr/lib/uucp, /usr/spool/uucp and all of their descendants.
For more info, read the man page.
Instructions:
Save this in a file, and get rid of this
garbage at top
type /bin/sh RunMe
type make chall
Known lacks:
Reading the directory could be more efficient.
(E.g. I could use 4.1aBSD's directory readers, which
has the side effect of making this work for 4.1c)
N.b. I don't know if this will work on 4.1c.
Error recovery is less than gracious. If ANYTHING goes
wrong, chall just dies (by design). I prolly ought
to have it continue its task.
It has only been tested on 4.1,4.1aBSD, and one hybrid
UNIX running on a Cadlinc Sun 68000. If it does
not port easily to your machine, please let me know.
I have one open file for every directory level. This means
that you may only go (NOFILE -3) levels deep. On my machine
this means I can get to *almost* everything if I execute
%chall adams bin / (No, I didn't try it...)
RCS:
I use purdue's RCS (Revision Control System), and it
has left its mark in my code. To get RCS, contact
purdue!wft or Tichy at purdue.
Distribution:
I don't care where it goes, but don't sell it, and if
you find any bugs (in my code?), let me know.
Rob Adams
(217) 333 3536
uiucdcs!adams
By the way:
There is a reason I don't just use find(1). This
runs (seriously) 100 times as fast. Really.
============================ RunMe Follows... ========================
# This is the RunMe script for chall, from the University of Illinois
# This Software may be distributed provided
# 1) It may NOT be sold.
# 2) The recipient agrees to (1).
#
# Rob Adams
# decvax!pur-ee!uiucdcs!adams
# parsec!uiucdcs!adams
# UofIllinois
echo Extracting Makefile
cat << !EOF!EOF! > Makefile
chall: main.o walk.o assert.o
cc -o chall main.o walk.o assert.o
clean:
rm -f *.o chall core
!EOF!EOF!
echo Extracting main.c
cat << !EOF!EOF! > main.c
static char *RCSid = "$Header: /mnt/staff/adams/Cprogs/Chall/RCS/main.c,v 1.5 83/04/21 07:13:03 adams Exp $";
/* Modification history --
*
* $Log: /mnt/staff/adams/Cprogs/Chall/RCS/main.c,v $
* Revision 1.5 83/04/21 07:13:03 adams
* Added multiple directories.
*
* Revision 1.4 83/04/21 06:59:56 adams
* indented right.
* R
*
* Revision 1.3 83/04/11 04:52:30 adams
* Added su-checking.
*
* Revision 1.2 83/04/11 04:47:38 adams
* changed all the asserts to my new format.
*
* Revision 1.1 83/04/11 03:30:24 adams
* Initial revision
*
*
*/
/* chall -- change the ownership and group ownership of a directory
* and all its descendants. (I wonder if that is spelled right.. hmmm)
*/
/*
*
* The line marked $Header: and the comment marked $Log: are courtesy
* RCS, the Revision Control System written and distributed by
* Walter F. Tichy at University of Purdue. I have found it invaluable
* in generating code, and recommend it whole-heartedly. For more
* information, contact the author. (purdue!wft or Tichy at purdue)
*
*/
/*
* original work by Rob Adams, (uiucdcs!adams) on 11 April.
*
*/
#include <stdio.h>
#include <pwd.h>
#include <grp.h>
main (argc, argv)
int argc;
char *argv[];
{
/* some defs here later. */
int uid,
gid;
int i;
int walked;
struct passwd *pswd,
*getpwnam ();
struct group *grp,
*getgrnam ();
/* Were we called correctly? */
assert ((argc >= 4), 's', "Usage: chall owner group file");
/* Am I su? non-roots fail */
assert (((getuid () == 0) || (geteuid () == 0)), 's', "You must be SU to run chall");
/* parse the args, first the name (argv[1]) */
setpwent ();
pswd = getpwnam (argv[1]);
endpwent ();
assert ((pswd != (struct passwd *) 0), 's', "Cant get user info");
uid = pswd -> pw_uid;
/* now comes the group. */
setgrent ();
grp = getgrnam (argv[2]);
endgrent ();
assert ((grp != (struct group *) 0), 's', "Cant get group info");
gid = grp -> gr_gid;
/* now, lets just pass everything off to the tree walker. */
for (i = 3; i < argc; i++)
{
walked = walk (uid, gid, argv[i]);
assert (walked == 0, 's', "Something is wrong, but I don't know what");
}
exit (walked); /* I know, walked is guaranteed to be 0 here */
}
!EOF!EOF!
echo Extracting walk.c
cat << !EOF!EOF! > walk.c
static char *RCSid = "$Header: RCS/walk.v Revision 1.2 83/04/11 04:48:28 adams Exp$";
/*
* walk()
* This guy does all the recursion. It should propagate
* errors backwards, but I don't know if I will do that tonight.
*
*/
#include <sys/types.h>
#include <sys/dir.h>
#include <sys/stat.h>
#include <stdio.h>
walk (uid, gid, filename)
int uid,
gid;
char *filename;
{
char file_nullend[2 * DIRSIZ]; /* better safe, et al... */
struct stat status;
struct direct dirbuf;
long lseek(); /* for lint */
int stated;
int isdir;
int walked;
long lseeked;
int chowned = 0;
int dot;
int readed;
/* see if filename is a non-directory or directory */
stated = stat (filename, &status);
assert ((stated == 0),'p',"chall: stat()");
isdir = ((status.st_mode & S_IFMT) == S_IFDIR);
if (!isdir) /* I know, I really don't need
isdir, but I like it */
{
chowned = chown(filename, uid, gid);
assert ((chowned == 0),'p',"chall: chown()");
return (0);
}
/* else */
chdir (filename);
chowned = chown(".", uid, gid);
assert ((chowned == 0),'p',"chall: chown()");
dot = open (".", 0); /* 0 means read-only */
assert ((dot != (-1)),'p', "chall: read()");
lseeked = lseek (dot, (long) 2*sizeof (dirbuf),0);
assert ((lseeked != (-1)),'p',"chall: lseek()"); /* blow off . and .. */
while (1 == 1)
{ /* I suppose I should make a
condition in there, but I am
lazy.. */
readed = read (dot, (char *) & dirbuf, sizeof (dirbuf));
if (readed == 0) /* EOF */
break;
assert ((readed == sizeof (dirbuf)),'p', "chall: read()");
if (dirbuf.d_ino == 0)
continue;
/* I need to terminate filename with a null char. */
(void) strncpy (file_nullend, dirbuf.d_name, DIRSIZ + 1);
walked = walk (uid, gid, file_nullend);
assert ((walked == 0),'s',"Something mysterious just happend");
}
close (dot);
chdir ("..");
return (0); /* just emptied a directory */
}
!EOF!EOF!
echo Extracting assert.c
cat << !EOF!EOF! > assert.c
static char *RCSid = "$Header: RCS/assert.v Revision 1.2 83/04/11 04:47:02 adams Exp$";
/*
* assert(bool,char,char *)
*
* program verification...
*
* If bool is true then return, else print a message and exit(-1)
*
* If char = p then perror(3) is used.
*
*/
#include <stdio.h>
assert (bool, c, s)
int bool;
char c;
char *s;
{
if (bool)
return;
if (c == 'p')
perror (s);
else
fprintf (stderr, "%s\n", s);
exit (-1);
}
!EOF!EOF!
echo Extracting man'(8)' page
cat << !EOF!EOF! > chown.8
.TH CHOWN 8
.UC 4
.SH NAME
chown, chgrp, chall \- change owner or group
.SH SYNOPSIS
.B /etc/chown
owner file ...
.PP
.B /etc/chgrp
group file ...
.PP
.B chall owner group directory ...
.SH DESCRIPTION
.I Chown
changes the owner of the
.I files
to
.IR owner .
The owner may be either a decimal UID or
a login name found in the password file.
.PP
.I Chgrp
changes the group-ID of the
.I files
to
.IR group .
The group may be either a decimal GID or
a group name found in the group-ID file.
.PP
.I Chall
changes the owner and group, of any file in a directory and
its subdirectories. The owner and group must be logical names,
not decimal UID or GID's.
.PP
Only the super-user can change owner or group,
in order to simplify as yet unimplemented accounting procedures.
.SH FILES
/etc/passwd
.br
/etc/group
.SH "SEE ALSO"
chown(2),
passwd(5), group(5)
!EOF!EOF!
More information about the Comp.sources.unix
mailing list