+/*\r
+ * uxsftp.c: the Unix-specific parts of PSFTP.\r
+ */\r
+\r
+#include <sys/time.h>\r
+#include <sys/types.h>\r
+#include <unistd.h>\r
+#include <errno.h>\r
+#include <pwd.h>\r
+\r
+#include "putty.h"\r
+#include "psftp.h"\r
+\r
+/*\r
+ * In PSFTP our selects are synchronous, so these functions are\r
+ * empty stubs.\r
+ */\r
+int uxsel_input_add(int fd, int rwx) { return 0; }\r
+void uxsel_input_remove(int id) { }\r
+\r
+char *x_get_default(const char *key)\r
+{\r
+ return NULL; /* this is a stub */\r
+}\r
+\r
+void platform_get_x11_auth(char *display, int *protocol,\r
+ unsigned char *data, int *datalen)\r
+{\r
+ /* Do nothing, therefore no auth. */\r
+}\r
+\r
+/*\r
+ * Default settings that are specific to PSFTP.\r
+ */\r
+char *platform_default_s(const char *name)\r
+{\r
+ if (!strcmp(name, "UserName")) {\r
+ /*\r
+ * Remote login username will default to the local username.\r
+ */\r
+ struct passwd *p;\r
+ uid_t uid = getuid();\r
+ char *user, *ret = NULL;\r
+\r
+ /*\r
+ * First, find who we think we are using getlogin. If this\r
+ * agrees with our uid, we'll go along with it. This should\r
+ * allow sharing of uids between several login names whilst\r
+ * coping correctly with people who have su'ed.\r
+ */\r
+ user = getlogin();\r
+ setpwent();\r
+ if (user)\r
+ p = getpwnam(user);\r
+ else\r
+ p = NULL;\r
+ if (p && p->pw_uid == uid) {\r
+ /*\r
+ * The result of getlogin() really does correspond to\r
+ * our uid. Fine.\r
+ */\r
+ ret = user;\r
+ } else {\r
+ /*\r
+ * If that didn't work, for whatever reason, we'll do\r
+ * the simpler version: look up our uid in the password\r
+ * file and map it straight to a name.\r
+ */\r
+ p = getpwuid(uid);\r
+ ret = p->pw_name;\r
+ }\r
+ endpwent();\r
+\r
+ return ret;\r
+ }\r
+ return NULL;\r
+}\r
+\r
+int platform_default_i(const char *name, int def)\r
+{\r
+ return def;\r
+}\r
+\r
+FontSpec platform_default_fontspec(const char *name)\r
+{\r
+ FontSpec ret;\r
+ *ret.name = '\0';\r
+ return ret;\r
+}\r
+\r
+Filename platform_default_filename(const char *name)\r
+{\r
+ Filename ret;\r
+ if (!strcmp(name, "LogFileName"))\r
+ strcpy(ret.path, "putty.log");\r
+ else\r
+ *ret.path = '\0';\r
+ return ret;\r
+}\r
+\r
+/*\r
+ * Set local current directory. Returns NULL on success, or else an\r
+ * error message which must be freed after printing.\r
+ */\r
+char *psftp_lcd(char *dir)\r
+{\r
+ if (chdir(dir) < 0)\r
+ return dupprintf("%s: chdir: %s", dir, strerror(errno));\r
+ else\r
+ return NULL;\r
+}\r
+\r
+/*\r
+ * Get local current directory. Returns a string which must be\r
+ * freed.\r
+ */\r
+char *psftp_getcwd(void)\r
+{\r
+ char *buffer, *ret;\r
+ int size = 256;\r
+\r
+ buffer = snewn(size, char);\r
+ while (1) {\r
+ ret = getcwd(buffer, size);\r
+ if (ret != NULL)\r
+ return ret;\r
+ if (errno != ERANGE) {\r
+ sfree(buffer);\r
+ return dupprintf("[cwd unavailable: %s]", strerror(errno));\r
+ }\r
+ /*\r
+ * Otherwise, ERANGE was returned, meaning the buffer\r
+ * wasn't big enough.\r
+ */\r
+ size = size * 3 / 2;\r
+ buffer = sresize(buffer, size, char);\r
+ }\r
+}\r
+\r
+/*\r
+ * Wait for some network data and process it.\r
+ */\r
+int ssh_sftp_loop_iteration(void)\r
+{\r
+ fd_set rset, wset, xset;\r
+ int i, fdcount, fdsize, *fdlist;\r
+ int fd, fdstate, rwx, ret, maxfd;\r
+\r
+ fdlist = NULL;\r
+ fdcount = fdsize = 0;\r
+\r
+ /* Count the currently active fds. */\r
+ i = 0;\r
+ for (fd = first_fd(&fdstate, &rwx); fd >= 0;\r
+ fd = next_fd(&fdstate, &rwx)) i++;\r
+\r
+ if (i < 1)\r
+ return -1; /* doom */\r
+\r
+ /* Expand the fdlist buffer if necessary. */\r
+ if (i > fdsize) {\r
+ fdsize = i + 16;\r
+ fdlist = sresize(fdlist, fdsize, int);\r
+ }\r
+\r
+ FD_ZERO(&rset);\r
+ FD_ZERO(&wset);\r
+ FD_ZERO(&xset);\r
+ maxfd = 0;\r
+\r
+ /*\r
+ * Add all currently open fds to the select sets, and store\r
+ * them in fdlist as well.\r
+ */\r
+ fdcount = 0;\r
+ for (fd = first_fd(&fdstate, &rwx); fd >= 0;\r
+ fd = next_fd(&fdstate, &rwx)) {\r
+ fdlist[fdcount++] = fd;\r
+ if (rwx & 1)\r
+ FD_SET_MAX(fd, maxfd, rset);\r
+ if (rwx & 2)\r
+ FD_SET_MAX(fd, maxfd, wset);\r
+ if (rwx & 4)\r
+ FD_SET_MAX(fd, maxfd, xset);\r
+ }\r
+\r
+ do {\r
+ ret = select(maxfd, &rset, &wset, &xset, NULL);\r
+ } while (ret < 0 && errno == EINTR);\r
+\r
+ if (ret < 0) {\r
+ perror("select");\r
+ exit(1);\r
+ }\r
+\r
+ for (i = 0; i < fdcount; i++) {\r
+ fd = fdlist[i];\r
+ /*\r
+ * We must process exceptional notifications before\r
+ * ordinary readability ones, or we may go straight\r
+ * past the urgent marker.\r
+ */\r
+ if (FD_ISSET(fd, &xset))\r
+ select_result(fd, 4);\r
+ if (FD_ISSET(fd, &rset))\r
+ select_result(fd, 1);\r
+ if (FD_ISSET(fd, &wset))\r
+ select_result(fd, 2);\r
+ }\r
+\r
+ sfree(fdlist);\r
+\r
+ return 0;\r
+}\r
+\r
+/*\r
+ * Main program: do platform-specific initialisation and then call\r
+ * psftp_main().\r
+ */\r
+int main(int argc, char *argv[])\r
+{\r
+ uxsel_init();\r
+ return psftp_main(argc, argv);\r
+}\r