Added all of the MH sources, including RCS files, in
[mmh] / docs / historical / mh-6.8.5 / support / pop / popwrd.c
1 /* popwrd.c - set password for a POP subscriber */
2 #ifndef lint
3 static char ident[] = "@(#)$Id: popwrd.c,v 1.7 1992/12/15 00:20:22 jromine Exp $";
4 #endif  /* lint */
5
6 #include "../h/strings.h"
7 #include "../zotnet/bboards.h"
8 #include <errno.h>
9 #include <pwd.h>
10 #include <signal.h>
11 #include <stdio.h>
12 #include <sys/types.h>
13 #include <sys/file.h>
14 #ifdef  SYS5
15 #include <fcntl.h>
16 #endif  /* SYS5 */
17
18 #ifndef __STDC__
19 #ifdef  SYS5
20 struct passwd *getpwnam();
21 #endif
22 #endif
23
24 static char  temp[] = "ptmp";
25 static char  home[BUFSIZ];
26
27 extern int errno;
28
29 char   *crypt (), *getpass (), *tail ();
30 long    time ();
31
32 #define compar(s,t)     (strcmp (s, t) ? s : "")
33
34 /* \f */
35
36 /* ARGSUSED */
37
38 main (argc, argv)
39 int     argc;
40 char  **argv;
41 {
42     int     i,
43             fd,
44             flags,
45             insist;
46     long    salt;
47     char    c,
48            *cp,
49             buffer[BUFSIZ],
50             saltc[2],
51           **ap;
52     struct bboard  *bb,
53                    *bp;
54     struct passwd  *pw;
55     FILE * fp;
56
57     if ((pw = getpwnam (POPUID)) == NULL) {
58         fprintf (stderr, "no entry for ~%s.\n", POPUID);
59         exit (1);
60     }
61     if (chdir (strcpy (home, pw -> pw_dir)) < 0) {
62         fprintf (stderr, "no home directory for ~%s.\n", POPUID);
63         exit (1);
64     }
65     if (!setpwinfo (pw, POPDB, 0)) {
66         fprintf (stderr, "setbbinfo(%s, %s, 0) failed -- %s.\n",
67                 pw -> pw_name, POPDB, getbberr ());
68         exit (1);
69     }
70
71     if (argc != 2) {
72         fprintf (stderr, "usage: %s pop-subscriber\n", *argv);
73         exit (1);
74     }
75     if ((bb = getbbnam (argv[1])) == NULL
76             && (bb = getbbaka (argv[1])) == NULL) {
77         fprintf (stderr, "Permission denied.\n");
78         exit (1);
79     }
80
81     if (!ldrbb (bb) && getuid () && !ldrchk (bb))
82         exit (1);
83
84     if ((bp = getbbcpy (bb)) == NULL) {
85         fprintf (stderr, "getbbcpy loses.\n");
86         exit (1);
87     }
88
89     (void) endbbent ();
90
91 #ifdef  lint
92     flags = 0;
93 #endif  /* lint */
94     for (insist = 0; insist < 2; insist++) {
95         if (insist)
96             printf ("Please use %s.\n",
97                     flags == 1 ? "at least one non-numeric character"
98                     : "a longer password");
99
100         if ((i = strlen (strcpy (buffer, getpass ("New password:")))) == 0) {
101             fprintf (stderr, "Password unchanged.\n");
102             exit (1);
103         }
104
105         flags = 0;
106         for (cp = buffer; c = *cp++;)
107             if (c >= 'a' && c <= 'z')
108                 flags |= 2;
109             else
110                 if (c >= 'A' && c <= 'Z')
111                     flags |= 4;
112                 else
113                     if (c >= '0' && c <= '9')
114                         flags |= 1;
115                     else
116                         flags |= 8;
117
118         if ((flags >= 7 && i >= 4)
119                 || ((flags == 2 || flags == 4) && i >= 6)
120                 || ((flags == 3 || flags == 5 || flags == 6) && i >= 5))
121             break;
122     }
123
124     if (strcmp (buffer, getpass ("Retype new password:"))) {
125         fprintf (stderr, "Mismatch - password unchanged.\n");
126         exit (1);
127     }
128
129     (void) time (&salt);
130     salt ^= 9 * getpid ();
131     saltc[0] = salt & 077;
132     saltc[1] = (salt >> 6) & 077;
133     for (i = 0; i < 2; i++) {
134         c = saltc[i] + '.';
135         if (c > '9')
136             c += 7;
137         if (c > 'Z')
138             c += 6;
139         saltc[i] = c;
140     }
141     cp = crypt (buffer, saltc);
142
143     (void) signal (SIGHUP, SIG_IGN);
144     (void) signal (SIGINT, SIG_IGN);
145     (void) signal (SIGQUIT, SIG_IGN);
146
147     (void) umask (0);
148     if ((fd = open (temp, O_WRONLY | O_CREAT | O_EXCL, 0644)) < 0) {
149         switch (errno) {
150             case EEXIST: 
151                 fprintf (stderr, "POP file busy - try again later.\n");
152                 break;
153
154             default: 
155                 perror (temp);
156                 break;
157         }
158         exit (1);
159     }
160
161 #ifdef  SIGTSTP
162     (void) signal (SIGTSTP, SIG_IGN);
163 #endif  /* SIGTSTP */
164     if ((fp = fdopen (fd, "w")) == NULL) {
165         fprintf (stderr, "fdopen loses.\n");
166         (void) unlink (temp);
167         exit (1);
168     }
169
170     (void) setbbent (SB_STAY | SB_FAST);
171     while (bb = getbbent ()) {
172         if (strcmp (bb -> bb_name, bp -> bb_name) == 0)
173             bb -> bb_passwd = cp;
174         fprintf (fp, "%s:", bb -> bb_name);
175         if (ap = bb -> bb_aka)
176             for (; *ap; ap++)
177                 fprintf (fp, "%s%s", ap != bb -> bb_aka ? "," : "", *ap);
178         fprintf (fp, ":%s:%s:", tail (bb -> bb_file), bb -> bb_passwd);
179         if ((ap = bb -> bb_leader) != NULL
180                 && (strcmp (*ap, POPUID) != 0 || ap[1] != NULL))
181             for (; *ap; ap++)
182                 fprintf (fp, "%s%s", ap != bb -> bb_leader ? "," : "", *ap);
183         fprintf (fp, ":%s:%s:%s:",
184                 compar (bb -> bb_addr, bb -> bb_name),
185                 compar (bb -> bb_request, POPUID),
186                 bb -> bb_relay);
187         if (ap = bb -> bb_dist)
188             for (; *ap; ap++)
189                 fprintf (fp, "%s%s", ap != bb -> bb_dist ? "," : "", *ap);
190         fprintf (fp, ":%o\n", bb -> bb_flags);
191     }
192     (void) endbbent ();
193
194     if (rename (temp, POPDB) < 0) {
195         perror ("rename");
196         (void) unlink (temp);
197         exit (1);
198     }
199     (void) fclose (fp);
200
201     exit (0);
202 }
203
204 /* \f */
205
206 char   *tail (s)
207 char   *s;
208 {
209     int     i;
210     char   *cp;
211
212     if (strncmp (s, home, i = strlen (home)) == 0
213             && *(cp = s + i) == '/'
214             && *++cp)
215         return cp;
216
217     return s;
218 }