home *** CD-ROM | disk | FTP | other *** search
- Newsgroups: comp.sources.misc
- organization: Math & Computer Science, Emory University, Atlanta, GA
- subject: v09i087: Public domain chown/chgrp clone
- From: arnold@mathcs.emory.edu (Arnold D. Robbins {EUCC})
- Sender: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
-
- Posting-number: Volume 9, Issue 87
- Submitted-by: arnold@mathcs.emory.edu (Arnold D. Robbins {EUCC})
- Archive-name: chgrp_ar
-
- This is a Chanukah gift for all you System V-ers out there who might
- like the BSD chown, which can (a) recursively chown a tree, and (b)
- take an option group argument, which saves tarversing a file tree twice.
-
- I wrote this because I had the BSD chown at work but not at home, and
- sorely missed the functionality.
-
- It requires the ftw(3) library routine, but PD versions are available
- in the archives.
-
- This program is PUBLIC DOMAIN. No warranties of any sort.
-
- Enjoy,
-
- Arnold Robbins
- --------------------------------------------------
- /*
- * chown.c
- *
- * Reimplementation of the 4.3 BSD chown, which can recursively chown
- * a directory, and take a user + group combination argument.
- * If called as chgrp, just do chgrp.
- *
- * Requires System V ftw(3) library routine, but a PD version is in the
- * source archives.
- *
- * Arnold Robbins
- * arnold@skeeve.atl.ga.us
- * skeeve!arnold
- *
- * Usage: chown [ -R ] user[.group] file ...
- * Usage: chgrp [ -R ] group file ...
- *
- * Posted December 1989.
- */
-
- #include <stdio.h>
- #include <ctype.h>
- #include <pwd.h>
- #include <grp.h>
- #include <ftw.h>
- #include <sys/types.h>
- #include <sys/stat.h>
-
- char chown_name[] = "chown";
- char chgrp_name[] = "chgrp";
-
- int user; /* new uid */
- int group; /* new gid */
-
- char *myname; /* for errors, and to decide behavior */
-
- #define MAXFDS 17 /* Any Unix will have at least this many */
-
- int problems = 0; /* exit non-zero if problems != 0 */
-
- main (argc, argv)
- int argc;
- char **argv;
- {
- extern int optind, getopt ();
- extern char *strchr (); /* use index if necessary */
- extern char *strrchr (); /* use rindex if necessary */
- int recursive = 0;
- int c, ret;
- char *username, *groupname;
- struct passwd *pwd, *getpwnam ();
- struct group *grp, *getgrnam ();
- extern int do_chown ();
-
- /* save program name */
- if ((myname = strrchr (argv[0], '/')) != NULL)
- myname++;
- else
- myname = argv[0];
-
- if (strcmp (myname, chown_name) != 0 && strcmp (myname, chgrp_name) != 0) {
- fprintf (stderr, "%s: not called as `chown' or `chgrp'\n", myname);
- exit (1);
- }
-
- /* are we recursive? */
- while ((c = getopt (argc, argv, "R")) != EOF) {
- switch (c) {
- case 'R':
- recursive = 1;
- break;
- default:
- usage ();
- break;
- }
- }
-
- if (optind >= argc)
- usage ();
-
- user = group = -1;
- if (strcmp (myname, chown_name) == 0) {
- /* called as chown, get user and group */
-
- /* first, get user and group names */
- username = argv[optind];
- groupname = strchr (argv[optind], '.');
- if (groupname != NULL)
- *groupname++ = '\0'; /* skip dot */
-
- /* get uid number */
- pwd = getpwnam (username);
- if (pwd == NULL) {
- if (isnumber (username)) {
- user = atoi (username);
- } else {
- fprintf (stderr, "%s: %s: no such user\n",
- myname, username);
- exit (1);
- }
- } else
- user = pwd -> pw_uid;
- endpwent ();
-
- if (groupname != NULL)
- goto getgroup;
- } else {
- /* just get group name */
- groupname = argv[optind];
-
- getgroup:
- grp = getgrnam (groupname);
- if (grp == NULL) {
- if (isnumber (groupname)) {
- group = atoi (groupname);
- } else {
- fprintf (stderr, "%s: %s: no such group\n",
- myname, groupname);
- exit (1);
- }
- } else
- group = grp -> gr_gid;
- endgrent ();
- }
-
- if (++optind >= argc)
- usage (); /* no files specified */
-
- /* actually do something to the files */
- for (; optind < argc; optind++) {
- if (recursive && isdir (argv[optind])) {
- ret = ftw (argv[optind], do_chown, MAXFDS);
- if (ret == -1)
- perror (myname); /* no file name */
- } else
- (void) chown1 (argv[optind]);
- }
- exit (problems != 0);
- }
-
- int
- do_chown (path, sbuf, flag)
- char *path;
- struct stat *sbuf;
- int flag;
- {
- int u, g;
- char buf[BUFSIZ];
-
- switch (flag) {
- case FTW_F: /* file */
- case FTW_D: /* directory */
- u = (user == -1) ? sbuf -> st_uid : user;
- g = (group == -1) ? sbuf -> st_gid : group;
- if (chown (path, u, g) < 0) {
- perror (path);
- problems = 1;
- }
- return 0; /* so ftw() will continue */
-
- case FTW_DNR: /* directory not readable */
- sprintf (buf, "%s: directory %s not readable\n", myname, path);
- break;
-
- case FTW_NS: /* file could not be stat'ed */
- sprintf (buf, "%s: could not stat %s\n", myname, path);
- break;
-
- default:
- sprintf (buf, "%s: impossible value (%d) from FTW\n", myname,
- flag);
- break;
- }
- fputs (buf, stderr);
- problems = 1;
- return 0;
- }
-
- int
- chown1 (path)
- char *path;
- {
- struct stat buf;
- int u, g;
-
- if (user == -1 || group == -1) { /* get old info */
- if (stat (path, & buf) < 0) {
- problems = 1;
- fprintf (stderr, "%s: ", path);
- perror ("stat");
- return -1;
- }
- }
-
- u = (user == -1) ? buf.st_uid : user;
- g = (group == -1) ? buf.st_gid : group;
-
- if (chown (path, u, g) < 0) {
- perror (path);
- problems = 1;
- }
- return 0;
- }
-
- int
- isnumber (str)
- char *str;
- {
- register int ret = 1;
-
- for (; *str; str++) {
- if (! isdigit (*str)) {
- ret = 0;
- break;
- }
- }
- return (ret);
- }
-
- int
- isdir (file)
- char *file;
- {
- struct stat buf;
-
- return (stat (file, &buf) == 0 &&
- (buf.st_mode & S_IFMT) == S_IFDIR);
- }
-
- int
- usage ()
- {
- fprintf (stderr, "usage: %s [ -R ] user%s file ...\n", myname,
- strcmp (myname, chown_name) == 0 ? "[.group]" : "");
- exit (1);
- }
-
- #ifdef debug
- /* for debugging --- delete for real */
-
- int
- chown (path, user, group)
- char *path;
- int user, group;
- {
- printf ("chown (\"%s\", %d, %d);\n", path, user, group);
- return 0;
- }
- #endif
- --
- Arnold Robbins -- guest account at Emory Math/CS | Laundry increases
- DOMAIN: arnold@emory.mathcs.emory.edu | exponentially in the
- UUCP: gatech!emory!arnold PHONE: +1 404 636-7221 | number of children.
- BITNET: arnold@emory | -- Miriam Hartholz
-
-