]> asedeno.scripts.mit.edu Git - PuTTY_svn.git/blob - unix/uxsftp.c
e9c9f6e6ae61a362b42ee2add4eec12ad95ce36d
[PuTTY_svn.git] / unix / uxsftp.c
1 /*\r
2  * uxsftp.c: the Unix-specific parts of PSFTP.\r
3  */\r
4 \r
5 #include <sys/time.h>\r
6 #include <sys/types.h>\r
7 #include <unistd.h>\r
8 #include <errno.h>\r
9 #include <pwd.h>\r
10 \r
11 #include "putty.h"\r
12 #include "psftp.h"\r
13 \r
14 /*\r
15  * In PSFTP our selects are synchronous, so these functions are\r
16  * empty stubs.\r
17  */\r
18 int uxsel_input_add(int fd, int rwx) { return 0; }\r
19 void uxsel_input_remove(int id) { }\r
20 \r
21 char *x_get_default(const char *key)\r
22 {\r
23     return NULL;                       /* this is a stub */\r
24 }\r
25 \r
26 void platform_get_x11_auth(char *display, int *protocol,\r
27                            unsigned char *data, int *datalen)\r
28 {\r
29     /* Do nothing, therefore no auth. */\r
30 }\r
31 \r
32 /*\r
33  * Default settings that are specific to PSFTP.\r
34  */\r
35 char *platform_default_s(const char *name)\r
36 {\r
37     if (!strcmp(name, "UserName")) {\r
38         /*\r
39          * Remote login username will default to the local username.\r
40          */\r
41         struct passwd *p;\r
42         uid_t uid = getuid();\r
43         char *user, *ret = NULL;\r
44 \r
45         /*\r
46          * First, find who we think we are using getlogin. If this\r
47          * agrees with our uid, we'll go along with it. This should\r
48          * allow sharing of uids between several login names whilst\r
49          * coping correctly with people who have su'ed.\r
50          */\r
51         user = getlogin();\r
52         setpwent();\r
53         if (user)\r
54             p = getpwnam(user);\r
55         else\r
56             p = NULL;\r
57         if (p && p->pw_uid == uid) {\r
58             /*\r
59              * The result of getlogin() really does correspond to\r
60              * our uid. Fine.\r
61              */\r
62             ret = user;\r
63         } else {\r
64             /*\r
65              * If that didn't work, for whatever reason, we'll do\r
66              * the simpler version: look up our uid in the password\r
67              * file and map it straight to a name.\r
68              */\r
69             p = getpwuid(uid);\r
70             ret = p->pw_name;\r
71         }\r
72         endpwent();\r
73 \r
74         return ret;\r
75     }\r
76     return NULL;\r
77 }\r
78 \r
79 int platform_default_i(const char *name, int def)\r
80 {\r
81     return def;\r
82 }\r
83 \r
84 FontSpec platform_default_fontspec(const char *name)\r
85 {\r
86     FontSpec ret;\r
87     *ret.name = '\0';\r
88     return ret;\r
89 }\r
90 \r
91 Filename platform_default_filename(const char *name)\r
92 {\r
93     Filename ret;\r
94     if (!strcmp(name, "LogFileName"))\r
95         strcpy(ret.path, "putty.log");\r
96     else\r
97         *ret.path = '\0';\r
98     return ret;\r
99 }\r
100 \r
101 /*\r
102  * Set local current directory. Returns NULL on success, or else an\r
103  * error message which must be freed after printing.\r
104  */\r
105 char *psftp_lcd(char *dir)\r
106 {\r
107     if (chdir(dir) < 0)\r
108         return dupprintf("%s: chdir: %s", dir, strerror(errno));\r
109     else\r
110         return NULL;\r
111 }\r
112 \r
113 /*\r
114  * Get local current directory. Returns a string which must be\r
115  * freed.\r
116  */\r
117 char *psftp_getcwd(void)\r
118 {\r
119     char *buffer, *ret;\r
120     int size = 256;\r
121 \r
122     buffer = snewn(size, char);\r
123     while (1) {\r
124         ret = getcwd(buffer, size);\r
125         if (ret != NULL)\r
126             return ret;\r
127         if (errno != ERANGE) {\r
128             sfree(buffer);\r
129             return dupprintf("[cwd unavailable: %s]", strerror(errno));\r
130         }\r
131         /*\r
132          * Otherwise, ERANGE was returned, meaning the buffer\r
133          * wasn't big enough.\r
134          */\r
135         size = size * 3 / 2;\r
136         buffer = sresize(buffer, size, char);\r
137     }\r
138 }\r
139 \r
140 /*\r
141  * Wait for some network data and process it.\r
142  */\r
143 int ssh_sftp_loop_iteration(void)\r
144 {\r
145     fd_set rset, wset, xset;\r
146     int i, fdcount, fdsize, *fdlist;\r
147     int fd, fdstate, rwx, ret, maxfd;\r
148 \r
149     fdlist = NULL;\r
150     fdcount = fdsize = 0;\r
151 \r
152     /* Count the currently active fds. */\r
153     i = 0;\r
154     for (fd = first_fd(&fdstate, &rwx); fd >= 0;\r
155          fd = next_fd(&fdstate, &rwx)) i++;\r
156 \r
157     if (i < 1)\r
158         return -1;                     /* doom */\r
159 \r
160     /* Expand the fdlist buffer if necessary. */\r
161     if (i > fdsize) {\r
162         fdsize = i + 16;\r
163         fdlist = sresize(fdlist, fdsize, int);\r
164     }\r
165 \r
166     FD_ZERO(&rset);\r
167     FD_ZERO(&wset);\r
168     FD_ZERO(&xset);\r
169     maxfd = 0;\r
170 \r
171     /*\r
172      * Add all currently open fds to the select sets, and store\r
173      * them in fdlist as well.\r
174      */\r
175     fdcount = 0;\r
176     for (fd = first_fd(&fdstate, &rwx); fd >= 0;\r
177          fd = next_fd(&fdstate, &rwx)) {\r
178         fdlist[fdcount++] = fd;\r
179         if (rwx & 1)\r
180             FD_SET_MAX(fd, maxfd, rset);\r
181         if (rwx & 2)\r
182             FD_SET_MAX(fd, maxfd, wset);\r
183         if (rwx & 4)\r
184             FD_SET_MAX(fd, maxfd, xset);\r
185     }\r
186 \r
187     do {\r
188         ret = select(maxfd, &rset, &wset, &xset, NULL);\r
189     } while (ret < 0 && errno == EINTR);\r
190 \r
191     if (ret < 0) {\r
192         perror("select");\r
193         exit(1);\r
194     }\r
195 \r
196     for (i = 0; i < fdcount; i++) {\r
197         fd = fdlist[i];\r
198         /*\r
199          * We must process exceptional notifications before\r
200          * ordinary readability ones, or we may go straight\r
201          * past the urgent marker.\r
202          */\r
203         if (FD_ISSET(fd, &xset))\r
204             select_result(fd, 4);\r
205         if (FD_ISSET(fd, &rset))\r
206             select_result(fd, 1);\r
207         if (FD_ISSET(fd, &wset))\r
208             select_result(fd, 2);\r
209     }\r
210 \r
211     sfree(fdlist);\r
212 \r
213     return 0;\r
214 }\r
215 \r
216 /*\r
217  * Main program: do platform-specific initialisation and then call\r
218  * psftp_main().\r
219  */\r
220 int main(int argc, char *argv[])\r
221 {\r
222     uxsel_init();\r
223     return psftp_main(argc, argv);\r
224 }\r