2 * htpasswd.c: simple program for manipulating password file for NCSA httpd
7 /* Modified 29aug97 by Jef Poskanzer to accept new password on stdin,
8 ** if stdin is a pipe or file. This is necessary for use from CGI.
11 #include <sys/types.h>
22 #define MAX_STRING_LEN 256
25 char temp_template[] = "/tmp/htp.XXXXXX";
27 void interrupted(int);
29 static char * strd(char *s) {
32 d=(char *)malloc(strlen(s) + 1);
37 static void getword(char *word, char *line, char stop) {
40 for(x=0;((line[x]) && (line[x] != stop));x++)
47 while((line[y++] = line[x++]));
50 static int my_getline(char *s, int n, FILE *f) {
54 s[i] = (char)fgetc(f);
59 if((s[i] == 0x4) || (s[i] == LF) || (i == (n-1))) {
61 return (feof(f) ? 1 : 0);
67 static void putline(FILE *f,char *l) {
70 for(x=0;l[x];x++) fputc(l[x],f);
75 /* From local_passwd.c (C) Regents of Univ. of California blah blah */
76 static unsigned char itoa64[] = /* 0 ... 63 => ascii - 64 */
77 "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
79 static void to64(char *s, long v, int n) {
81 *s++ = itoa64[v&0x3f];
87 /* MPE lacks getpass() and a way to suppress stdin echo. So for now, just
88 issue the prompt and read the results with echo. (Ugh). */
90 char *getpass(const char *prompt) {
92 static char password[81];
95 gets((char *)&password);
97 if (strlen((char *)&password) > 8) {
101 return (char *)&password;
106 add_password( char* user, FILE* f )
113 if ( ! isatty( fileno( stdin ) ) )
115 (void) fgets( pass, sizeof(pass), stdin );
116 if ( pass[strlen(pass) - 1] == '\n' )
117 pass[strlen(pass) - 1] = '\0';
122 pw = strd( (char*) getpass( "New password:" ) );
123 if ( strcmp( pw, (char*) getpass( "Re-type new password:" ) ) != 0 )
125 (void) fprintf( stderr, "They don't match, sorry.\n" );
127 unlink( temp_template );
131 (void) srandom( (int) time( (time_t*) 0 ) );
132 to64( &salt[0], random(), 2 );
133 cpw = crypt( pw, salt );
134 (void) fprintf( f, "%s:%s\n", user, cpw );
137 static void usage(void) {
138 fprintf(stderr,"Usage: htpasswd [-c] passwordfile username\n");
139 fprintf(stderr,"The -c flag creates a new file.\n");
143 void interrupted(int signo) {
144 fprintf(stderr,"Interrupted.\n");
145 if(tfd != -1) unlink(temp_template);
149 int main(int argc, char *argv[]) {
151 char user[MAX_STRING_LEN];
152 char line[MAX_STRING_LEN];
153 char l[MAX_STRING_LEN];
154 char w[MAX_STRING_LEN];
155 char command[MAX_STRING_LEN];
159 signal(SIGINT,(void (*)(int))interrupted);
161 if(strcmp(argv[1],"-c"))
163 if(!(tfp = fopen(argv[2],"w"))) {
164 fprintf(stderr,"Could not open passwd file %s for writing.\n",
169 printf("Adding password for %s.\n",argv[3]);
170 add_password(argv[3],tfp);
173 } else if(argc != 3) usage();
175 tfd = mkstemp(temp_template);
176 if(!(tfp = fdopen(tfd,"w"))) {
177 fprintf(stderr,"Could not open temp file.\n");
181 if(!(f = fopen(argv[1],"r"))) {
183 "Could not open passwd file %s for reading.\n",argv[1]);
184 fprintf(stderr,"Use -c option to create new one.\n");
187 strncpy(user,argv[2],sizeof(user)-1);
188 user[sizeof(user)-1] = '\0';
191 while(!(my_getline(line,MAX_STRING_LEN,f))) {
192 if(found || (line[0] == '#') || (!line[0])) {
203 printf("Changing password for user %s\n",user);
204 add_password(user,tfp);
209 printf("Adding user %s\n",user);
210 add_password(user,tfp);
214 sprintf(command,"cp %s %s",temp_template,argv[1]);
216 unlink(temp_template);