Hello Marek, I have created a diffile against the 980403 release that adds functionality to newusers for automatic handling of users with only anonymous ftp login (using the guestgroup feature in ftpaccess, which means that the users home directory looks like '/home/user/./'). It also adds a commandline argument to specify an initial directory structure for such users, with a tarball normally containing the bin,lib,etc directories used in the chrooted environment. I am using it to automatically create chunks of users with only ftp access for a webserver. I have tried to follow your coding standards and I believe it is bug free but.. well, who knows. :) It's not much code however. I hope you find it useful. Do what you like with it, feel free to ask if anything is unclear. Best rgds, Calle Karlsson ckn@kash.se diff -uNr shadow-980403.orig/src/newusers.c shadow-980403/src/newusers.c --- shadow-980403.orig/src/newusers.c Fri Jan 30 00:22:43 1998 +++ shadow-980403/src/newusers.c Fri Apr 17 16:55:33 1998 @@ -76,11 +76,35 @@ static void usage(void) { - fprintf(stderr, "Usage: %s [ input ]\n", Prog); + fprintf (stderr, "Usage: %s [-p prototype tarfile] [ input ]\n", Prog); + fprintf (stderr, "The prototype tarfile is only used for users\n"); + fprintf (stderr, "marked as anonymous ftp users. It must be a full pathname.\n"); exit(1); } /* + * createuserdir - create a directory and chmod it + */ + +static int +createuserdir (char * dir, int uid, int gid, int line) +{ + if (mkdir (dir, 0777 & ~getdef_num("UMASK", 077))) { + fprintf (stderr, "%s: line %d: mkdir %s failed\n", + Prog, line, dir); + return -1; + } + + if (chown (dir, uid, gid)) { + fprintf (stderr, "%s: line %d: chown %s failed\n", + Prog, line, dir); + return -1; + } + + return 0; +} + +/* * add_group - create a new group or add a user to an existing group */ @@ -328,6 +352,8 @@ main(int argc, char **argv) { char buf[BUFSIZ]; + char anonproto[BUFSIZ]; + int flag; char *fields[8]; int nfields; char *cp; @@ -340,12 +366,23 @@ Prog = Basename(argv[0]); - if (argc > 1 && argv[1][0] == '-') - usage (); + * anonproto = '\0'; + + while ((flag = getopt (argc, argv, "p:h")) != EOF) { + switch (flag) { + case 'p': + STRFCPY(anonproto, optarg); + break; + case 'h': + default: + usage (); + break; + } + } - if (argc == 2) { - if (! freopen (argv[1], "r", stdin)) { - snprintf(buf, sizeof buf, "%s: %s", Prog, argv[1]); + if (optind < argc) { + if (! freopen (argv[optind], "r", stdin)) { + snprintf(buf, sizeof buf, "%s: %s", Prog, argv[optind]); perror (buf); exit (1); } @@ -499,15 +536,36 @@ if (fields[6][0]) newpw.pw_shell = fields[6]; - if (newpw.pw_dir[0] && access(newpw.pw_dir, F_OK)) { - if (mkdir (newpw.pw_dir, - 0777 & ~getdef_num("UMASK", 077))) - fprintf (stderr, "%s: line %d: mkdir failed\n", - Prog, line); - else if (chown (newpw.pw_dir, - newpw.pw_uid, newpw.pw_gid)) - fprintf (stderr, "%s: line %d: chown failed\n", - Prog, line); + if (newpw.pw_dir[0]) { + char * userdir = strdup (newpw.pw_dir); + char * anonpart; + int rc; + + if ((anonpart = strstr (userdir, "/./"))) { + * anonpart = '\0'; + anonpart += 2; + } + + if (access(userdir, F_OK)) + rc = createuserdir (userdir, newpw.pw_uid, newpw.pw_gid, line); + else + rc = 0; + + if (rc == 0 && anonpart) { + if (* anonproto) { + char cmdbuf [BUFSIZ]; + snprintf(cmdbuf, sizeof cmdbuf, + "cd %s; tar xf %s", + userdir, anonproto); + system (cmdbuf); + } + if (strlen (anonpart) > 1) { + strcat (userdir, anonpart); + if (access (userdir, F_OK)) + createuserdir (userdir, newpw.pw_uid, newpw.pw_gid, line); + } + } + free (userdir); } /*