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