+ if (chown(file, uid, gid)) {
+ chownerr(file);
+ return;
+ }
+ if (!rflag)
+ return;
+ if (lstat(file, &buf)) {
+ err(file);
+ return;
+ }
+ if ((buf.st_mode & S_IFMT) == S_IFDIR) {
+ if (chdir(file) < 0 || !(dirp = opendir("."))) {
+ err(file);
+ return;
+ }
+ for (dp = readdir(dirp); dp; dp = readdir(dirp)) {
+ if (dp->d_name[0] == '.' && (!dp->d_name[1] ||
+ dp->d_name[1] == '.' && !dp->d_name[2]))
+ continue;
+ change(dp->d_name);
+ }
+ closedir(dirp);
+ if (chdir("..")) {
+ err("..");
+ exit(fflag ? 0 : -1);
+ }
+ }
+}
+
+static
+chownerr(file)
+ char *file;
+{
+ static int euid = -1, ngroups = -1;
+
+ /* check for chown without being root */
+ if (uid != -1 && euid == -1 && (euid = geteuid())) {
+ if (fflag)
+ exit(0);
+ err(file);
+ exit(-1);
+ }
+ /* check group membership; kernel just returns EPERM */
+ if (gid != -1 && ngroups == -1) {
+ int groups[NGROUPS];
+
+ ngroups = getgroups(NGROUPS, groups);
+ while (--ngroups >= 0 && gid != groups[ngroups]);
+ if (ngroups < 0) {
+ if (fflag)
+ exit(0);
+ fprintf(stderr,
+ "%s: you are not a member of group %s.\n",
+ myname, gname);
+ exit(-1);
+ }
+ }
+ err(file);
+}
+
+static
+err(s)
+ char *s;
+{
+ if (fflag)
+ return;
+ fprintf(stderr, "%s: ", myname);
+ perror(s);
+ retval = -1;
+}
+
+static
+usage()
+{
+ fprintf(stderr, "usage: %s [-Rf] %s file ...\n", myname,
+ ischown ? "owner[.group]" : "group");
+ exit(-1);