Initial revision
diff --git a/chown.c b/chown.c
new file mode 100644
index 0000000..a611f92
--- /dev/null
+++ b/chown.c
@@ -0,0 +1,63 @@
+#include "internal.h"
+#include <pwd.h>
+#include <grp.h>
+#include <string.h>
+#include <stdio.h>
+
+const char chown_usage[] = "chown [-R] user-name file [file ...]\n"
+"\n\tThe group list is kept in the file /etc/groups.\n\n"
+"\t-R:\tRecursively change the mode of all files and directories\n"
+"\t\tunder the argument directory.";
+
+int
+parse_user_name(const char * s, struct FileInfo * i)
+{
+ struct passwd * p;
+ char * dot = strchr(s, '.');
+
+ if (! dot )
+ dot = strchr(s, ':');
+
+ if ( dot )
+ *dot = '\0';
+
+ if ( (p = getpwnam(s)) == 0 ) {
+ fprintf(stderr, "%s: no such user.\n", s);
+ return 1;
+ }
+ i->userID = p->pw_uid;
+
+ if ( dot ) {
+ struct group * g = getgrnam(++dot);
+ if ( g == 0 ) {
+ fprintf(stderr, "%s: no such group.\n", dot);
+ return 1;
+ }
+ i->groupID = g->gr_gid;
+ i->changeGroupID = 1;
+ }
+ return 0;
+}
+
+extern int
+chown_main(struct FileInfo * i, int argc, char * * argv)
+{
+ int status;
+
+ while ( argc >= 3 && strcmp("-R", argv[1]) == 0 ) {
+ i->recursive = 1;
+ argc--;
+ argv++;
+ }
+
+ if ( (status = parse_user_name(argv[1], i)) != 0 )
+ return status;
+
+ argv++;
+ argc--;
+
+ i->changeUserID = 1;
+ i->complainInPostProcess = 1;
+
+ return monadic_main(i, argc, argv);
+}