--- htpasswd.c 2006-08-07 11:19:54.000000000 +0300 +++ htpasswd.c.merge 2006-08-13 23:43:42.000000000 +0300 @@ -98,6 +98,7 @@ #define APHTP_NOFILE 2 #define APHTP_NONINTERACTIVE 4 #define APHTP_DELUSER 8 +#define APHTP_READSTDIN 16 apr_file_t *errfile; apr_file_t *ftemp = NULL; @@ -207,10 +208,10 @@ { apr_file_printf(errfile, "Usage:" NL); apr_file_printf(errfile, "\thtpasswd [-cmdpsD] passwordfile username" NL); - apr_file_printf(errfile, "\thtpasswd -b[cmdpsD] passwordfile username " + apr_file_printf(errfile, "\thtpasswd -b[cmdpsiD] passwordfile username " "password" NL NL); apr_file_printf(errfile, "\thtpasswd -n[mdps] username" NL); - apr_file_printf(errfile, "\thtpasswd -nb[mdps] username password" NL); + apr_file_printf(errfile, "\thtpasswd -nb[mdpsi] username password" NL); apr_file_printf(errfile, " -c Create a new file." NL); apr_file_printf(errfile, " -n Don't update file; display results on " "stdout." NL); @@ -227,7 +228,8 @@ apr_file_printf(errfile, " -p Do not encrypt the password (plaintext)." NL); apr_file_printf(errfile, " -s Force SHA encryption of the password." NL); apr_file_printf(errfile, " -b Use the password from the command line " - "rather than prompting for it." NL); + "or stdin rather than prompting for it." NL); + apr_file_printf(errfile, " -i Read passwd from stdin." NL); apr_file_printf(errfile, " -D Delete the specified user." NL); apr_file_printf(errfile, "On Windows, NetWare and TPF systems the '-m' flag is used by " @@ -322,6 +324,10 @@ *mask |= APHTP_NONINTERACTIVE; args_left++; } + else if (*arg == 'i') { + *mask |= APHTP_READSTDIN; + args_left--; + } else if (*arg == 'D') { *mask |= APHTP_DELUSER; } @@ -331,6 +337,10 @@ } } + if ((*mask & APHTP_READSTDIN) & !(*mask & APHTP_NONINTERACTIVE)) { + args_left++; + } + if ((*mask & APHTP_NEWFILE) && (*mask & APHTP_NOFILE)) { apr_file_printf(errfile, "%s: -c and -n options conflict" NL, argv[0]); exit(ERR_SYNTAX); @@ -374,12 +384,34 @@ exit(ERR_BADUSER); } if (*mask & APHTP_NONINTERACTIVE) { - if (strlen(argv[i + 2]) > (MAX_STRING_LEN - 1)) { - apr_file_printf(errfile, "%s: password too long (> %d)" NL, - argv[0], MAX_STRING_LEN); - exit(ERR_OVERFLOW); + if (*mask & APHTP_READSTDIN) { + apr_file_t *file_stdin; + char buf[MAX_STRING_LEN + 1]; + apr_size_t nread; + if (apr_file_open_stdin(&file_stdin, pool) != APR_SUCCESS) { + apr_file_printf(errfile, "%s: Unable to read from stdin." NL, + argv[0]); + exit(ERR_FILEPERM); /* What else. */ + } + if (apr_file_read_full(file_stdin, &buf, + MAX_STRING_LEN, &nread) != APR_EOF || + nread == MAX_STRING_LEN) { + apr_file_printf(errfile, "%s: passsword too long (> %d)" NL, + argv[0], MAX_STRING_LEN - 1); + exit(ERR_OVERFLOW); + } + buf[nread] = '\0'; + *password = apr_pstrdup(pool, buf); + apr_file_close(file_stdin); + } + else { + if (strlen(argv[i + 2]) > (MAX_STRING_LEN - 1)) { + apr_file_printf(errfile, "%s: password too long (> %d)\n" NL, + argv[0], MAX_STRING_LEN - 1); + exit(ERR_OVERFLOW); + } + *password = apr_pstrdup(pool, argv[i + 2]); } - *password = apr_pstrdup(pool, argv[i + 2]); } }