latest and greatest.
[oweals/busybox.git] / chown.c
1 /*
2  * Mini chown/chgrp implementation for busybox
3  *
4  * Copyright (C) 1998 by Erik Andersen <andersee@debian.org>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  *
20  */
21
22 #include <stdio.h>
23 #include <grp.h>
24 #include <pwd.h>
25 #include "internal.h"
26
27
28 static int uid=-1;
29 static int gid=0;
30 static int chownApp;
31 static char* invocationName=NULL;
32
33
34 static const char chgrp_usage[] = "[OPTION]... GROUP FILE...\n"
35     "Change the group membership of each FILE to GROUP.\n"
36     "\n\tOptions:\n" "\t-R\tchange files and directories recursively\n";
37 static const char chown_usage[] = "[OPTION]...  OWNER[.[GROUP] FILE...\n"
38     "Change the owner and/or group of each FILE to OWNER and/or GROUP.\n"
39     "\n\tOptions:\n" "\t-R\tchange files and directories recursively\n";
40
41
42
43 static int fileAction(const char *fileName)
44 {
45     struct stat statBuf;
46     if ((stat(fileName, &statBuf) < 0) || 
47             (chown(fileName, 
48                    ((chownApp==TRUE)? uid: statBuf.st_uid), 
49                    gid) < 0)) { 
50         perror(fileName);
51         return( TRUE);
52     }
53     return( FALSE);
54 }
55
56 int chown_main(int argc, char **argv)
57 {
58     struct group *grp;
59     struct passwd *pwd;
60     int recursiveFlag=FALSE;
61     char *groupName;
62
63
64     chownApp = (strcmp(*argv, "chown")==0)? TRUE : FALSE;
65
66     if (argc < 2) {
67         fprintf(stderr, "Usage: %s %s", *argv, 
68                 (chownApp==TRUE)? chown_usage : chgrp_usage);
69         return( FALSE);
70     }
71     invocationName=*argv;
72     argc--;
73     argv++;
74
75     /* Parse options */
76     while (**argv == '-') {
77         while (*++(*argv)) switch (**argv) {
78             case 'R':
79                 recursiveFlag = TRUE;
80                 break;
81             default:
82                 fprintf(stderr, "Unknown option: %c\n", **argv);
83                 return( FALSE);
84         }
85         argc--;
86         argv++;
87     }
88     
89     /* Find the selected group */
90     groupName = strchr(*argv, '.');
91     if ( chownApp==TRUE && groupName )
92         *groupName++ = '\0';
93     else
94         groupName = *argv;
95     grp = getgrnam(groupName);
96     if (grp == NULL) {
97         fprintf(stderr, "%s: Unknown group name: %s\n", invocationName, groupName);
98         return( FALSE);
99     }
100     gid = grp->gr_gid;
101
102     /* Find the selected user (if appropriate)  */
103     if (chownApp==TRUE) {
104         pwd = getpwnam(*argv);
105         if (pwd == NULL) {
106             fprintf(stderr, "%s: Unknown user name: %s\n", invocationName, *argv);
107             return( FALSE);
108         }
109         uid = pwd->pw_uid;
110     }
111
112     /* Ok, ready to do the deed now */
113     if (argc <= 1) {
114         fprintf(stderr, "%s: too few arguments", invocationName);
115         return( FALSE);
116     }
117     while (argc-- > 1) {
118         argv++;
119         if (recursiveFlag==TRUE) 
120             recursiveAction( *argv, TRUE, fileAction, fileAction);
121         else
122             fileAction( *argv);
123     }
124     return(TRUE);
125 }