Fixed warnings from diff on first-time install of nmh. Also added 'echo's
[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  * $Id$
19  */
20
21 #include <h/mh.h>
22 #include <pwd.h>
23 #include <errno.h>
24
25 static FILE *cfile;
26
27 #ifndef MAXHOSTNAMELEN
28 # define MAXHOSTNAMELEN 64
29 #endif
30
31 #define DEFAULT 1
32 #define LOGIN   2
33 #define PASSWD  3
34 #define ACCOUNT 4
35 #define MACDEF  5
36 #define ID      10
37 #define MACH    11
38
39 static char tokval[100];
40
41 struct toktab {
42     char *tokstr;
43     int tval;
44 };
45
46 static struct toktab toktabs[] = {
47     { "default",  DEFAULT },
48     { "login",    LOGIN },
49     { "password", PASSWD },
50     { "passwd",   PASSWD },
51     { "account",  ACCOUNT },
52     { "machine",  MACH },
53     { "macdef",   MACDEF },
54     { 0,          0 }
55 };
56
57 /*
58  * prototypes
59  */
60 static int token(void);
61
62
63 int
64 ruserpass(char *host, char **aname, char **apass)
65 {
66     char *hdir, buf[BUFSIZ];
67     int t, usedefault = 0;
68     struct stat stb;
69     extern int errno;
70
71     hdir = getenv("HOME");
72     if (hdir == NULL)
73         hdir = ".";
74     snprintf(buf, sizeof(buf), "%s/.netrc", hdir);
75     cfile = fopen(buf, "r");
76     if (cfile == NULL) {
77         if (errno != ENOENT)
78             perror(buf);
79         goto done;
80     }
81
82     while ((t = token())) {
83         switch(t) {
84         case DEFAULT:
85             usedefault = 1;
86             /* FALL THROUGH */
87
88         case MACH:
89             if (!usedefault) {
90                 if (token() != ID)
91                     continue;
92                 /*
93                  * Allow match either for user's host name.
94                  */
95                 if (strcasecmp(host, tokval) == 0)
96                     goto match;
97                 continue;
98             }
99 match:
100             while ((t = token()) && t != MACH && t != DEFAULT) {
101                 switch(t) {
102                 case LOGIN:
103                     if (token() && *aname == 0) {
104                         *aname = malloc((size_t) strlen(tokval) + 1);
105                         strcpy(*aname, tokval);
106                     }
107                     break;
108                 case PASSWD:
109                     if (fstat(fileno(cfile), &stb) >= 0 &&
110                         (stb.st_mode & 077) != 0) {
111                         fprintf(stderr, "Error - .netrc file not correct mode.\n");
112                         fprintf(stderr, "Remove password or correct mode.\n");
113                         goto bad;
114                     }
115                     if (token() && *apass == 0) {
116                         *apass = malloc((size_t) strlen(tokval) + 1);
117                         strcpy(*apass, tokval);
118                     }
119                     break;
120                 case ACCOUNT:
121                     break;
122
123                 case MACDEF:
124                     goto done_close;
125                     break;
126                 default:
127                     fprintf(stderr, "Unknown .netrc keyword %s\n", tokval);
128                     break;
129                 }
130             }
131             goto done;
132         }
133     }
134
135 done_close:
136     fclose(cfile);
137
138 done:
139     if (!*aname) {
140         char tmp[80];
141         char *myname;
142
143         if ((myname = getlogin()) == NULL) {
144             struct passwd *pp;
145
146             if ((pp = getpwuid (getuid())) != NULL)
147                 myname = pp->pw_name;
148         }
149         printf("Name (%s:%s): ", host, myname);
150
151         fgets(tmp, sizeof(tmp) - 1, stdin);
152         tmp[strlen(tmp) - 1] = '\0';
153         if (*tmp != '\0') {
154             myname = tmp;
155         }
156
157         *aname = malloc((size_t) strlen(myname) + 1);
158         strcpy (*aname, myname);
159     }
160
161     if (!*apass) {
162         char prompt[256];
163         char *mypass;
164
165         snprintf(prompt, sizeof(prompt), "Password (%s:%s): ", host, *aname);
166         mypass = nmh_getpass(prompt);
167         
168         if (*mypass == '\0') {
169             mypass = *aname;
170         }
171
172         *apass = malloc((size_t) strlen(mypass) + 1);
173         strcpy (*apass, mypass);
174     }
175
176     return(0);
177 bad:
178     fclose(cfile);
179     return(-1);
180 }
181
182 static int
183 token(void)
184 {
185     char *cp;
186     int c;
187     struct toktab *t;
188
189     if (feof(cfile))
190         return (0);
191     while ((c = getc(cfile)) != EOF &&
192            (c == '\n' || c == '\t' || c == ' ' || c == ','))
193         continue;
194     if (c == EOF)
195         return (0);
196     cp = tokval;
197     if (c == '"') {
198         while ((c = getc(cfile)) != EOF && c != '"') {
199             if (c == '\\')
200                 c = getc(cfile);
201             *cp++ = c;
202         }
203     } else {
204         *cp++ = c;
205         while ((c = getc(cfile)) != EOF
206                && c != '\n' && c != '\t' && c != ' ' && c != ',') {
207             if (c == '\\')
208                 c = getc(cfile);
209             *cp++ = c;
210         }
211     }
212     *cp = 0;
213     if (tokval[0] == 0)
214         return (0);
215     for (t = toktabs; t->tokstr; t++)
216         if (!strcmp(t->tokstr, tokval))
217             return (t->tval);
218     return (ID);
219 }