home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / usr.sbin / chown / chown.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-05-20  |  5.1 KB  |  224 lines

  1. /*
  2.  * Copyright (c) 1988 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  */
  33.  
  34. #ifndef lint
  35. char copyright[] =
  36. "@(#) Copyright (c) 1988 Regents of the University of California.\n\
  37.  All rights reserved.\n";
  38. #endif /* not lint */
  39.  
  40. #ifndef lint
  41. static char sccsid[] = "@(#)chown.c    5.18 (Berkeley) 3/9/91";
  42. #endif /* not lint */
  43.  
  44. #include <sys/param.h>
  45. #include <sys/stat.h>
  46. #include <sys/errno.h>
  47. #include <dirent.h>
  48. #include <fts.h>
  49. #include <pwd.h>
  50. #include <grp.h>
  51. #include <unistd.h>
  52. #include <stdio.h>
  53. #include <ctype.h>
  54. #include <stdlib.h>
  55. #include <string.h>
  56.  
  57. int ischown, uid, gid, fflag, rflag, retval;
  58. char *gname, *myname;
  59.  
  60. main(argc, argv)
  61.     int argc;
  62.     char **argv;
  63. {
  64.     extern int optind;
  65.     register FTS *fts;
  66.     register FTSENT *p;
  67.     register char *cp;
  68.     int ch;
  69.  
  70.     myname = (cp = rindex(*argv, '/')) ? cp + 1 : *argv;
  71.     ischown = myname[2] == 'o';
  72.  
  73.     while ((ch = getopt(argc, argv, "Rf")) != EOF)
  74.         switch((char)ch) {
  75.         case 'R':
  76.             rflag = 1;
  77.             break;
  78.         case 'f':
  79.             fflag = 1;
  80.             break;
  81.         case '?':
  82.         default:
  83.             usage();
  84.         }
  85.     argv += optind;
  86.     argc -= optind;
  87.  
  88.     if (argc < 2)
  89.         usage();
  90.  
  91.     uid = gid = -1;
  92.     if (ischown) {
  93. #ifdef SUPPORT_DOT
  94.         if (cp = index(*argv, '.')) {
  95.             *cp++ = '\0';
  96.             a_gid(cp);
  97.         } else
  98. #endif
  99.         if (cp = index(*argv, ':')) {
  100.             *cp++ = '\0';
  101.             a_gid(cp);
  102.         } 
  103.         a_uid(*argv);
  104.     }
  105.     else 
  106.         a_gid(*argv);
  107.  
  108.     if (rflag) {
  109.         if (!(fts = fts_open(++argv, FTS_NOSTAT|FTS_PHYSICAL, 0))) {
  110.             (void)fprintf(stderr,
  111.                 "%s: %s.\n", myname, strerror(errno));
  112.             exit(1);
  113.         }
  114.         while (p = fts_read(fts)) {
  115.             if (p->fts_info == FTS_D)
  116.                 continue;
  117.             if (p->fts_info == FTS_ERR) {
  118.                 error(p->fts_path);
  119.                 continue;
  120.             }
  121.             if (chown(p->fts_accpath, uid, gid) && !fflag)
  122.                 chownerr(p->fts_path);
  123.         }
  124.         exit(retval);
  125.     }
  126.     while (*++argv)
  127.         if (chown(*argv, uid, gid) && !fflag)
  128.             chownerr(*argv);
  129.     exit(retval);
  130. }
  131.  
  132. a_gid(s)
  133.     register char *s;
  134. {
  135.     struct group *gr;
  136.  
  137.     if (!*s) {
  138.         gid = -1;            /* argument was "uid." */
  139.         return;
  140.     }
  141.     gname = s;
  142.     if (gr = getgrnam(s))
  143.         gid = gr->gr_gid;
  144.     else {
  145.         for (; *s && isdigit(*s); ++s);
  146.         if (!*s)
  147.             gid = atoi(gname);
  148.         else {
  149.             (void)fprintf(stderr, "%s: unknown group id: %s\n",
  150.                 myname, gname);
  151.             exit(1);
  152.         }
  153.     }
  154. }
  155.  
  156. a_uid(s)
  157.     register char *s;
  158. {
  159.     struct passwd *pw;
  160.     char *uname;
  161.  
  162.     if (!*s) {
  163.         uid = -1;            /* argument was ".gid" */
  164.         return;
  165.     }
  166.     if (pw = getpwnam(s))
  167.         uid = pw->pw_uid;
  168.     else {
  169.         for (uname = s; *s && isdigit(*s); ++s);
  170.         if (!*s)
  171.             uid = atoi(uname);
  172.         else {
  173.             (void)fprintf(stderr,
  174.                 "chown: unknown user id: %s\n", uname);
  175.             exit(1);
  176.         }
  177.     }
  178. }
  179.  
  180. chownerr(file)
  181.     char *file;
  182. {
  183.     static int euid = -1, ngroups = -1;
  184.  
  185.     /* check for chown without being root */
  186.     if (errno != EPERM || uid != -1 && euid == -1 && (euid = geteuid())) {
  187.         if (fflag)
  188.             exit(0);
  189.         error(file);
  190.         exit(1);
  191.     }
  192.     /* check group membership; kernel just returns EPERM */
  193.     if (gid != -1 && ngroups == -1) {
  194.         int groups[NGROUPS];
  195.  
  196.         ngroups = getgroups(NGROUPS, groups);
  197.         while (--ngroups >= 0 && gid != groups[ngroups]);
  198.         if (ngroups < 0) {
  199.             if (fflag)
  200.                 exit(0);
  201.             (void)fprintf(stderr,
  202.                 "%s: you are not a member of group %s.\n",
  203.                 myname, gname);
  204.             exit(1);
  205.         }
  206.     }
  207.     if (!fflag)
  208.         error(file);
  209. }
  210.  
  211. error(name)
  212.     char *name;
  213. {
  214.     (void)fprintf(stderr, "%s: %s: %s\n", myname, name, strerror(errno));
  215.     retval = 1;
  216. }
  217.  
  218. usage()
  219. {
  220.     (void)fprintf(stderr, "usage: %s [-Rf] %s file ...\n", myname,
  221.         ischown ? "[owner][:group]" : "group");
  222.     exit(1);
  223. }
  224.