Windows PSCP now links against winsftp.c, and scp.c is now a
[u/mdw/putty] / unix / uxsftp.c
1 /*
2 * uxsftp.c: the Unix-specific parts of PSFTP and PSCP.
3 */
4
5 #include <sys/time.h>
6 #include <sys/types.h>
7 #include <unistd.h>
8 #include <errno.h>
9
10 #include "putty.h"
11 #include "psftp.h"
12
13 /*
14 * In PSFTP our selects are synchronous, so these functions are
15 * empty stubs.
16 */
17 int uxsel_input_add(int fd, int rwx) { return 0; }
18 void uxsel_input_remove(int id) { }
19
20 char *x_get_default(const char *key)
21 {
22 return NULL; /* this is a stub */
23 }
24
25 void platform_get_x11_auth(char *display, int *protocol,
26 unsigned char *data, int *datalen)
27 {
28 /* Do nothing, therefore no auth. */
29 }
30
31 /*
32 * Default settings that are specific to PSFTP.
33 */
34 char *platform_default_s(const char *name)
35 {
36 return NULL;
37 }
38
39 int platform_default_i(const char *name, int def)
40 {
41 return def;
42 }
43
44 FontSpec platform_default_fontspec(const char *name)
45 {
46 FontSpec ret;
47 *ret.name = '\0';
48 return ret;
49 }
50
51 Filename platform_default_filename(const char *name)
52 {
53 Filename ret;
54 if (!strcmp(name, "LogFileName"))
55 strcpy(ret.path, "putty.log");
56 else
57 *ret.path = '\0';
58 return ret;
59 }
60
61 /*
62 * Stubs for the GUI feedback mechanism in Windows PSCP.
63 */
64 void gui_update_stats(char *name, unsigned long size,
65 int percentage, unsigned long elapsed,
66 unsigned long done, unsigned long eta,
67 unsigned long ratebs) {}
68 void gui_send_errcount(int list, int errs) {}
69 void gui_send_char(int is_stderr, int c) {}
70 void gui_enable(char *arg) {}
71
72
73 /*
74 * Set local current directory. Returns NULL on success, or else an
75 * error message which must be freed after printing.
76 */
77 char *psftp_lcd(char *dir)
78 {
79 if (chdir(dir) < 0)
80 return dupprintf("%s: chdir: %s", dir, strerror(errno));
81 else
82 return NULL;
83 }
84
85 /*
86 * Get local current directory. Returns a string which must be
87 * freed.
88 */
89 char *psftp_getcwd(void)
90 {
91 char *buffer, *ret;
92 int size = 256;
93
94 buffer = snewn(size, char);
95 while (1) {
96 ret = getcwd(buffer, size);
97 if (ret != NULL)
98 return ret;
99 if (errno != ERANGE) {
100 sfree(buffer);
101 return dupprintf("[cwd unavailable: %s]", strerror(errno));
102 }
103 /*
104 * Otherwise, ERANGE was returned, meaning the buffer
105 * wasn't big enough.
106 */
107 size = size * 3 / 2;
108 buffer = sresize(buffer, size, char);
109 }
110 }
111
112 /*
113 * Wait for some network data and process it.
114 */
115 int ssh_sftp_loop_iteration(void)
116 {
117 fd_set rset, wset, xset;
118 int i, fdcount, fdsize, *fdlist;
119 int fd, fdstate, rwx, ret, maxfd;
120
121 fdlist = NULL;
122 fdcount = fdsize = 0;
123
124 /* Count the currently active fds. */
125 i = 0;
126 for (fd = first_fd(&fdstate, &rwx); fd >= 0;
127 fd = next_fd(&fdstate, &rwx)) i++;
128
129 if (i < 1)
130 return -1; /* doom */
131
132 /* Expand the fdlist buffer if necessary. */
133 if (i > fdsize) {
134 fdsize = i + 16;
135 fdlist = sresize(fdlist, fdsize, int);
136 }
137
138 FD_ZERO(&rset);
139 FD_ZERO(&wset);
140 FD_ZERO(&xset);
141 maxfd = 0;
142
143 /*
144 * Add all currently open fds to the select sets, and store
145 * them in fdlist as well.
146 */
147 fdcount = 0;
148 for (fd = first_fd(&fdstate, &rwx); fd >= 0;
149 fd = next_fd(&fdstate, &rwx)) {
150 fdlist[fdcount++] = fd;
151 if (rwx & 1)
152 FD_SET_MAX(fd, maxfd, rset);
153 if (rwx & 2)
154 FD_SET_MAX(fd, maxfd, wset);
155 if (rwx & 4)
156 FD_SET_MAX(fd, maxfd, xset);
157 }
158
159 do {
160 ret = select(maxfd, &rset, &wset, &xset, NULL);
161 } while (ret < 0 && errno == EINTR);
162
163 if (ret < 0) {
164 perror("select");
165 exit(1);
166 }
167
168 for (i = 0; i < fdcount; i++) {
169 fd = fdlist[i];
170 /*
171 * We must process exceptional notifications before
172 * ordinary readability ones, or we may go straight
173 * past the urgent marker.
174 */
175 if (FD_ISSET(fd, &xset))
176 select_result(fd, 4);
177 if (FD_ISSET(fd, &rset))
178 select_result(fd, 1);
179 if (FD_ISSET(fd, &wset))
180 select_result(fd, 2);
181 }
182
183 sfree(fdlist);
184
185 return 0;
186 }
187
188 /*
189 * Main program: do platform-specific initialisation and then call
190 * psftp_main().
191 */
192 int main(int argc, char *argv[])
193 {
194 uxsel_init();
195 return psftp_main(argc, argv);
196 }