Reformated comments and long lines
[mmh] / sbr / ruserpass.c
1 /*
2 ** Portions of this code are
3 ** Copyright (c) 1985 Regents of the University of California.
4 ** All rights reserved.
5 **
6 ** Redistribution and use in source and binary forms are permitted
7 ** provided that the above copyright notice and this paragraph are
8 ** duplicated in all such forms and that any documentation,
9 ** advertising materials, and other materials related to such
10 ** distribution and use acknowledge that the software was developed
11 ** by the University of California, Berkeley.  The name of the
12 ** University may not be used to endorse or promote products derived
13 ** from this software without specific prior written permission.
14 ** THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
15 ** IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
16 ** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
17 */
18
19 #include <h/mh.h>
20 #include <h/utils.h>
21 #include <pwd.h>
22 #include <errno.h>
23
24 static FILE *cfile;
25
26 #ifndef MAXHOSTNAMELEN
27 # define MAXHOSTNAMELEN 64
28 #endif
29
30 #define DEFAULT 1
31 #define LOGIN   2
32 #define PASSWD  3
33 #define ACCOUNT 4
34 #define MACDEF  5
35 #define ID     10
36 #define MACH   11
37
38 static char tokval[100];
39
40 struct toktab {
41         char *tokstr;
42         int tval;
43 };
44
45 static struct toktab toktabs[] = {
46         { "default",  DEFAULT },
47         { "login",    LOGIN },
48         { "password", PASSWD },
49         { "passwd",   PASSWD },
50         { "account",  ACCOUNT },
51         { "machine",  MACH },
52         { "macdef",   MACDEF },
53         { 0,          0 }
54 };
55
56 /*
57 ** prototypes
58 */
59 static int token(void);
60
61
62 void
63 ruserpass(char *host, char **aname, char **apass)
64 {
65         char *hdir, buf[BUFSIZ];
66         int t, usedefault = 0;
67         struct stat stb;
68
69         hdir = getenv("HOME");
70         if (hdir == NULL)
71                 hdir = ".";
72         snprintf(buf, sizeof(buf), "%s/.netrc", hdir);
73         cfile = fopen(buf, "r");
74         if (cfile == NULL) {
75                 if (errno != ENOENT)
76                         perror(buf);
77                 goto done;
78         }
79
80         while ((t = token())) {
81                 switch(t) {
82                 case DEFAULT:
83                         usedefault = 1;
84                         /* FALL THROUGH */
85
86                 case MACH:
87                         if (!usedefault) {
88                                 if (token() != ID)
89                                         continue;
90                                 /*
91                                  * Allow match either for user's host name.
92                                  */
93                                 if (mh_strcasecmp(host, tokval) == 0)
94                                         goto match;
95                                 continue;
96                         }
97 match:
98                         while ((t = token()) && t != MACH && t != DEFAULT) {
99                                 switch(t) {
100                                 case LOGIN:
101                                         if (token() && *aname == 0) {
102                                                 *aname = mh_xmalloc((size_t) strlen(tokval) + 1);
103                                                 strcpy(*aname, tokval);
104                                         }
105                                         break;
106                                 case PASSWD:
107                                         if (fstat(fileno(cfile), &stb) >= 0 &&
108                                                 (stb.st_mode & 077) != 0) {
109                                                 /*
110                                                 ** We make this a fatal
111                                                 ** error to force the user
112                                                 ** to correct it
113                                                 */
114                                                 advise(NULL, "Error - ~/.netrc file must not be world or group readable.");
115                                                 adios(NULL, "Remove password or correct file permissions.");
116                                         }
117                                         if (token() && *apass == 0) {
118                                                 *apass = mh_xmalloc((size_t) strlen(tokval) + 1);
119                                                 strcpy(*apass, tokval);
120                                         }
121                                         break;
122                                 case ACCOUNT:
123                                         break;
124
125                                 case MACDEF:
126                                         goto done_close;
127                                         break;
128                                 default:
129                                         fprintf(stderr, "Unknown .netrc keyword %s\n", tokval);
130                                         break;
131                                 }
132                         }
133                         goto done;
134                 }
135         }
136
137 done_close:
138         fclose(cfile);
139
140 done:
141         if (!*aname) {
142                 char tmp[80];
143                 char *myname;
144
145                 if ((myname = getlogin()) == NULL) {
146                         struct passwd *pp;
147
148                         if ((pp = getpwuid (getuid())) != NULL)
149                                 myname = pp->pw_name;
150                 }
151                 printf("Name (%s:%s): ", host, myname);
152
153                 fgets(tmp, sizeof(tmp) - 1, stdin);
154                 tmp[strlen(tmp) - 1] = '\0';
155                 if (*tmp != '\0') {
156                         myname = tmp;
157                 }
158
159                 *aname = mh_xmalloc((size_t) strlen(myname) + 1);
160                 strcpy (*aname, myname);
161         }
162
163         if (!*apass) {
164                 char prompt[256];
165                 char *mypass;
166
167                 snprintf(prompt, sizeof(prompt), "Password (%s:%s): ", host, *aname);
168                 mypass = nmh_getpass(prompt);
169
170                 if (*mypass == '\0') {
171                         mypass = *aname;
172                 }
173
174                 *apass = mh_xmalloc((size_t) strlen(mypass) + 1);
175                 strcpy (*apass, mypass);
176         }
177
178 }
179
180 static int
181 token(void)
182 {
183         char *cp;
184         int c;
185         struct toktab *t;
186
187         if (feof(cfile))
188                 return (0);
189         while ((c = getc(cfile)) != EOF &&
190                    (c == '\n' || c == '\t' || c == ' ' || c == ','))
191                 continue;
192         if (c == EOF)
193                 return (0);
194         cp = tokval;
195         if (c == '"') {
196                 while ((c = getc(cfile)) != EOF && c != '"') {
197                         if (c == '\\')
198                                 c = getc(cfile);
199                         *cp++ = c;
200                 }
201         } else {
202                 *cp++ = c;
203                 while ((c = getc(cfile)) != EOF
204                            && c != '\n' && c != '\t' && c != ' ' && c != ',') {
205                         if (c == '\\')
206                                 c = getc(cfile);
207                         *cp++ = c;
208                 }
209         }
210         *cp = 0;
211         if (tokval[0] == 0)
212                 return (0);
213         for (t = toktabs; t->tokstr; t++)
214                 if (!strcmp(t->tokstr, tokval))
215                         return (t->tval);
216         return (ID);
217 }