Doug Porter's patch that changes the order of preferences on how to find the
[platform/upstream/curl.git] / lib / netrc.c
1 /***************************************************************************
2  *                                  _   _ ____  _     
3  *  Project                     ___| | | |  _ \| |    
4  *                             / __| | | | |_) | |    
5  *                            | (__| |_| |  _ <| |___ 
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
9  *
10  * This software is licensed as described in the file COPYING, which
11  * you should have received as part of this distribution. The terms
12  * are also available at http://curl.haxx.se/docs/copyright.html.
13  * 
14  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15  * copies of the Software, and permit persons to whom the Software is
16  * furnished to do so, under the terms of the COPYING file.
17  *
18  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19  * KIND, either express or implied.
20  *
21  * $Id$
22  ***************************************************************************/
23
24 #include "setup.h"
25
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29
30 #ifdef HAVE_SYS_TYPES_H
31 #include <sys/types.h>
32 #endif
33 #ifdef HAVE_UNISTD_H
34 #include <unistd.h>
35 #endif
36 #ifdef HAVE_PWD_H
37 #include <pwd.h>
38 #endif
39 #ifdef VMS
40 #include <unixlib.h>
41 #endif
42
43 #include <curl/curl.h>
44 #include "netrc.h"
45
46 #include "strequal.h"
47 #include "strtok.h"
48
49 #define _MPRINTF_REPLACE /* use our functions only */
50 #include <curl/mprintf.h>
51
52 /* The last #include file should be: */
53 #ifdef CURLDEBUG
54 #include "memdebug.h"
55 #endif
56
57 /* Debug this single source file with:
58    'make netrc' then run './netrc'!
59
60    Oh, make sure you have a .netrc file too ;-)
61  */
62
63 /* Get user and password from .netrc when given a machine name */
64
65 enum {
66   NOTHING,
67   HOSTFOUND,    /* the 'machine' keyword was found */
68   HOSTCOMPLETE, /* the machine name following the keyword was found too */
69   HOSTVALID,    /* this is "our" machine! */
70
71   HOSTEND /* LAST enum */
72 };
73
74 /* make sure we have room for at least this size: */
75 #define LOGINSIZE 64
76 #define PASSWORDSIZE 64
77
78 /* returns -1 on failure, 0 if the host is found, 1 is the host isn't found */
79 int Curl_parsenetrc(char *host,
80                     char *login,
81                     char *password,
82                     char *netrcfile)
83 {
84   FILE *file;
85   int retcode=1;
86   int specific_login = (login[0] != 0);
87   char *home = NULL; 
88   bool home_alloc = FALSE;
89   bool netrc_alloc = FALSE;
90   int state=NOTHING;
91
92   char state_login=0;      /* Found a login keyword */
93   char state_password=0;   /* Found a password keyword */
94   char state_our_login=0;  /* With specific_login, found *our* login name */
95
96 #define NETRC DOT_CHAR "netrc"
97
98 #ifdef CURLDEBUG
99   {
100     /* This is a hack to allow testing.
101      * If compiled with --enable-debug and CURL_DEBUG_NETRC is defined,
102      * then it's the path to a substitute .netrc for testing purposes *only* */
103
104     char *override = curl_getenv("CURL_DEBUG_NETRC");
105
106     if (override) {
107       printf("NETRC: overridden " NETRC " file: %s\n", home);
108       netrcfile = override;
109       netrc_alloc = TRUE;
110     }
111   }
112 #endif /* CURLDEBUG */
113   if(!netrcfile) {
114     home = curl_getenv("HOME"); /* portable environment reader */
115     if(home) {
116       home_alloc = TRUE;
117 #if defined(HAVE_GETPWUID) && defined(HAVE_GETEUID)
118     }
119     else {
120       struct passwd *pw;
121       pw= getpwuid(geteuid());
122       if (pw) {
123 #ifdef  VMS
124         home = decc$translate_vms(pw->pw_dir);
125 #else
126         home = pw->pw_dir;
127 #endif
128       }
129 #endif
130     }
131
132     if(!home)
133       return -1;
134
135     netrcfile = curl_maprintf("%s%s%s", home, DIR_CHAR, NETRC);
136     if(!netrcfile) {
137       if(home_alloc)
138         free(home);
139       return -1;
140     }
141     netrc_alloc = TRUE;
142   }
143
144   file = fopen(netrcfile, "r");
145   if(file) {
146     char *tok;
147     char *tok_buf;
148     bool done=FALSE;
149     char netrcbuffer[256];
150
151     while(!done && fgets(netrcbuffer, sizeof(netrcbuffer), file)) {
152       tok=strtok_r(netrcbuffer, " \t\n", &tok_buf);
153       while(!done && tok) {
154
155         if (login[0] && password[0]) {
156           done=TRUE;
157           break;
158         }
159
160         switch(state) {
161         case NOTHING:
162           if(strequal("machine", tok)) {
163             /* the next tok is the machine name, this is in itself the
164                delimiter that starts the stuff entered for this machine,
165                after this we need to search for 'login' and
166                'password'. */
167             state=HOSTFOUND;
168           }
169           break;
170         case HOSTFOUND:
171           if(strequal(host, tok)) {
172             /* and yes, this is our host! */
173             state=HOSTVALID;
174 #ifdef _NETRC_DEBUG
175             printf("HOST: %s\n", tok);
176 #endif
177             retcode=0; /* we did find our host */
178           }
179           else
180             /* not our host */
181             state=NOTHING;
182           break;
183         case HOSTVALID:
184           /* we are now parsing sub-keywords concerning "our" host */
185           if(state_login) {
186             if (specific_login) {
187               state_our_login = strequal(login, tok);
188             }
189             else {
190               strncpy(login, tok, LOGINSIZE-1);
191 #ifdef _NETRC_DEBUG
192               printf("LOGIN: %s\n", login);
193 #endif
194             }
195             state_login=0;
196           }
197           else if(state_password) {
198             if (state_our_login || !specific_login) {
199               strncpy(password, tok, PASSWORDSIZE-1);
200 #ifdef _NETRC_DEBUG
201               printf("PASSWORD: %s\n", password);
202 #endif
203             }
204             state_password=0;
205           }
206           else if(strequal("login", tok))
207             state_login=1;
208           else if(strequal("password", tok))
209             state_password=1;
210           else if(strequal("machine", tok)) {
211             /* ok, there's machine here go => */
212             state = HOSTFOUND;
213             state_our_login = 0;
214           }
215           break;
216         } /* switch (state) */
217
218         tok = strtok_r(NULL, " \t\n", &tok_buf);
219       } /* while (tok) */
220     } /* while fgets() */
221
222     fclose(file);
223   }
224
225   if(home_alloc)
226     free(home);
227   if(netrc_alloc)
228     free(netrcfile);
229
230   return retcode;
231 }
232
233 #ifdef _NETRC_DEBUG
234 int main(int argc, char **argv)
235 {
236   char login[64]="";
237   char password[64]="";
238
239   if(argc<2)
240     return -1;
241
242   if(0 == ParseNetrc(argv[1], login, password)) {
243     printf("HOST: %s LOGIN: %s PASSWORD: %s\n",
244            argv[1], login, password);
245   }
246 }
247
248 #endif