From b51259f6a879f69bec5348bddb604d9b3d499941 Mon Sep 17 00:00:00 2001 From: simon Date: Sun, 24 Aug 2003 13:22:17 +0000 Subject: [PATCH] And just to prove that psftp.c really is now platform-independent ... here's a Unix port of PSFTP. Woo. (Oddly PSCP looks to be somewhat harder; there's more Windows code interleaved than there was in PSFTP.) git-svn-id: svn://svn.tartarus.org/sgt/putty@3419 cda61777-01e9-0310-a592-d414129be87e --- Recipe | 2 +- psftp.c | 19 +++-- psftp.h | 6 ++ sftp.c | 5 +- unix/.cvsignore | 2 +- unix/unix.h | 11 ++- unix/uxcons.c | 10 ++- unix/uxplink.c | 9 +-- unix/uxsftp.c | 224 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 9 files changed, 267 insertions(+), 21 deletions(-) create mode 100644 unix/uxsftp.c diff --git a/Recipe b/Recipe index 7e7295b7..4422441b 100644 --- a/Recipe +++ b/Recipe @@ -159,7 +159,7 @@ puttytel : [X] UXTERM uxmisc misc ldisc settings pty uxsel be_nossh uxstore plink : [U] uxplink uxcons NONSSH UXSSH be_all logging UXMISC signal ux_x11 -# psftp : [U] psftp uxsftp console UXSSH be_none SFTP UXMISC +psftp : [U] psftp uxsftp uxcons UXSSH be_none SFTP UXMISC PuTTY : [M] terminal wcwidth ldiscucs logging be_all mac macdlg macevlog + macterm macucs mac_res.rsrc testback NONSSH MACSSH MACMISC CHARSET diff --git a/psftp.c b/psftp.c index a032c70c..53896598 100644 --- a/psftp.c +++ b/psftp.c @@ -894,20 +894,20 @@ int sftp_cmd_chmod(struct sftp_command *cmd) default: printf("chmod: file mode '%.*s' contains unrecognised" " user/group/other specifier '%c'\n", - strcspn(modebegin, ","), modebegin, *mode); + (int)strcspn(modebegin, ","), modebegin, *mode); return 0; } mode++; } if (!*mode || *mode == ',') { printf("chmod: file mode '%.*s' is incomplete\n", - strcspn(modebegin, ","), modebegin); + (int)strcspn(modebegin, ","), modebegin); return 0; } action = *mode++; if (!*mode || *mode == ',') { printf("chmod: file mode '%.*s' is incomplete\n", - strcspn(modebegin, ","), modebegin); + (int)strcspn(modebegin, ","), modebegin); return 0; } perms = 0; @@ -922,7 +922,7 @@ int sftp_cmd_chmod(struct sftp_command *cmd) (subset & 06777) != 02070) { printf("chmod: file mode '%.*s': set[ug]id bit should" " be used with exactly one of u or g only\n", - strcspn(modebegin, ","), modebegin); + (int)strcspn(modebegin, ","), modebegin); return 0; } perms |= 06000; @@ -930,7 +930,7 @@ int sftp_cmd_chmod(struct sftp_command *cmd) default: printf("chmod: file mode '%.*s' contains unrecognised" " permission specifier '%c'\n", - strcspn(modebegin, ","), modebegin, *mode); + (int)strcspn(modebegin, ","), modebegin, *mode); return 0; } mode++; @@ -938,7 +938,7 @@ int sftp_cmd_chmod(struct sftp_command *cmd) if (!(subset & 06777) && (perms &~ subset)) { printf("chmod: file mode '%.*s' contains no user/group/other" " specifier and permissions other than 't' \n", - strcspn(modebegin, ","), modebegin); + (int)strcspn(modebegin, ","), modebegin); return 0; } perms &= subset; @@ -1740,6 +1740,7 @@ static int psftp_connect(char *userhost, char *user, int portnumber) { char *host, *realhost; const char *err; + void *logctx; /* Separate host and username */ host = userhost; @@ -1925,7 +1926,11 @@ int psftp_main(int argc, char *argv[]) char *batchfile = NULL; int errors = 0; - flags = FLAG_STDERR | FLAG_INTERACTIVE | FLAG_SYNCAGENT; + flags = FLAG_STDERR | FLAG_INTERACTIVE +#ifdef FLAG_SYNCAGENT + | FLAG_SYNCAGENT +#endif + ; cmdline_tooltype = TOOLTYPE_FILETRANSFER; ssh_get_line = &console_get_line; sk_init(); diff --git a/psftp.h b/psftp.h index 092d10ac..30fbd881 100644 --- a/psftp.h +++ b/psftp.h @@ -25,4 +25,10 @@ char *psftp_lcd(char *newdir); */ int ssh_sftp_loop_iteration(void); +/* + * The main program in psftp.c. Called from main() in the platform- + * specific code, after doing any platform-specific initialisation. + */ +int psftp_main(int argc, char *argv[]); + #endif /* PUTTY_PSFTP_H */ diff --git a/sftp.c b/sftp.c index e19c9857..b9dc44b2 100644 --- a/sftp.c +++ b/sftp.c @@ -67,10 +67,12 @@ static struct sftp_packet *sftp_pkt_init(int pkt_type) sftp_pkt_addbyte(pkt, (unsigned char) pkt_type); return pkt; } +/* static void sftp_pkt_addbool(struct sftp_packet *pkt, unsigned char value) { sftp_pkt_adddata(pkt, &value, 1); } +*/ static void sftp_pkt_adduint32(struct sftp_packet *pkt, unsigned long value) { @@ -282,7 +284,6 @@ static tree234 *sftp_requests; static struct sftp_request *sftp_alloc_request(void) { - const unsigned CHANNEL_NUMBER_OFFSET = 256; unsigned low, high, mid; int tsize; struct sftp_request *r; @@ -296,7 +297,7 @@ static struct sftp_request *sftp_alloc_request(void) * B-tree to find the largest ID which is in a contiguous * sequence from the beginning. (Precisely everything in that * sequence must have ID equal to its tree index plus - * SEQUENCE_NUMBER_OFFSET.) + * REQUEST_ID_OFFSET.) */ tsize = count234(sftp_requests); diff --git a/unix/.cvsignore b/unix/.cvsignore index 781d9dbb..24c9bd8c 100644 --- a/unix/.cvsignore +++ b/unix/.cvsignore @@ -1,4 +1,4 @@ Makefile.gtk Makefile local -plink pterm putty puttytel +plink pterm putty puttytel psftp *.log diff --git a/unix/unix.h b/unix/unix.h index dbb28d6f..f12f576d 100644 --- a/unix/unix.h +++ b/unix/unix.h @@ -51,8 +51,6 @@ unsigned long getticks(void); /* based on gettimeofday(2) */ #define WCHAR wchar_t #define BYTE unsigned char -GLOBAL void *logctx; - /* Things pty.c needs from pterm.c */ char *get_x_display(void *frontend); int font_dimension(void *frontend, int which);/* 0 for width, 1 for height */ @@ -128,4 +126,13 @@ int init_ucs(struct unicode_data *ucsdata, */ int sk_getxdmdata(void *sock, unsigned long *ip, int *port); +/* + * General helpful Unix stuff: more helpful version of the FD_SET + * macro, which also handles maxfd. + */ +#define FD_SET_MAX(fd, max, set) do { \ + FD_SET(fd, &set); \ + if (max < fd + 1) max = fd + 1; \ +} while (0) + #endif diff --git a/unix/uxcons.c b/unix/uxcons.c index 881b6bfe..5e3949b3 100644 --- a/unix/uxcons.c +++ b/unix/uxcons.c @@ -16,6 +16,8 @@ int console_batch_mode = FALSE; +static void *console_logctx = NULL; + /* * Clean up and exit. */ @@ -258,9 +260,15 @@ void old_keyfile_warning(void) fputs(message, stderr); } +void console_provide_logctx(void *logctx) +{ + console_logctx = logctx; +} + void logevent(void *frontend, const char *string) { - log_eventlog(logctx, string); + if (console_logctx) + log_eventlog(console_logctx, string); } int console_get_line(const char *prompt, char *str, diff --git a/unix/uxplink.c b/unix/uxplink.c index 5d3efb29..e8b616eb 100644 --- a/unix/uxplink.c +++ b/unix/uxplink.c @@ -14,12 +14,6 @@ #include #include -/* More helpful version of the FD_SET macro, to also handle maxfd. */ -#define FD_SET_MAX(fd, max, set) do { \ - FD_SET(fd, &set); \ - if (max < fd + 1) max = fd + 1; \ -} while (0) - #define PUTTY_DO_GLOBALS /* actually _define_ globals */ #include "putty.h" #include "storage.h" @@ -287,7 +281,7 @@ int main(int argc, char **argv) int connopen; int exitcode; int errors; - void *ldisc; + void *ldisc, *logctx; ssh_get_line = console_get_line; @@ -573,6 +567,7 @@ int main(int argc, char **argv) * Start up the connection. */ logctx = log_init(NULL, &cfg); + console_provide_logctx(logctx); { const char *error; char *realhost; diff --git a/unix/uxsftp.c b/unix/uxsftp.c new file mode 100644 index 00000000..e9c9f6e6 --- /dev/null +++ b/unix/uxsftp.c @@ -0,0 +1,224 @@ +/* + * uxsftp.c: the Unix-specific parts of PSFTP. + */ + +#include +#include +#include +#include +#include + +#include "putty.h" +#include "psftp.h" + +/* + * In PSFTP our selects are synchronous, so these functions are + * empty stubs. + */ +int uxsel_input_add(int fd, int rwx) { return 0; } +void uxsel_input_remove(int id) { } + +char *x_get_default(const char *key) +{ + return NULL; /* this is a stub */ +} + +void platform_get_x11_auth(char *display, int *protocol, + unsigned char *data, int *datalen) +{ + /* Do nothing, therefore no auth. */ +} + +/* + * Default settings that are specific to PSFTP. + */ +char *platform_default_s(const char *name) +{ + if (!strcmp(name, "UserName")) { + /* + * Remote login username will default to the local username. + */ + struct passwd *p; + uid_t uid = getuid(); + char *user, *ret = NULL; + + /* + * First, find who we think we are using getlogin. If this + * agrees with our uid, we'll go along with it. This should + * allow sharing of uids between several login names whilst + * coping correctly with people who have su'ed. + */ + user = getlogin(); + setpwent(); + if (user) + p = getpwnam(user); + else + p = NULL; + if (p && p->pw_uid == uid) { + /* + * The result of getlogin() really does correspond to + * our uid. Fine. + */ + ret = user; + } else { + /* + * If that didn't work, for whatever reason, we'll do + * the simpler version: look up our uid in the password + * file and map it straight to a name. + */ + p = getpwuid(uid); + ret = p->pw_name; + } + endpwent(); + + return ret; + } + return NULL; +} + +int platform_default_i(const char *name, int def) +{ + return def; +} + +FontSpec platform_default_fontspec(const char *name) +{ + FontSpec ret; + *ret.name = '\0'; + return ret; +} + +Filename platform_default_filename(const char *name) +{ + Filename ret; + if (!strcmp(name, "LogFileName")) + strcpy(ret.path, "putty.log"); + else + *ret.path = '\0'; + return ret; +} + +/* + * Set local current directory. Returns NULL on success, or else an + * error message which must be freed after printing. + */ +char *psftp_lcd(char *dir) +{ + if (chdir(dir) < 0) + return dupprintf("%s: chdir: %s", dir, strerror(errno)); + else + return NULL; +} + +/* + * Get local current directory. Returns a string which must be + * freed. + */ +char *psftp_getcwd(void) +{ + char *buffer, *ret; + int size = 256; + + buffer = snewn(size, char); + while (1) { + ret = getcwd(buffer, size); + if (ret != NULL) + return ret; + if (errno != ERANGE) { + sfree(buffer); + return dupprintf("[cwd unavailable: %s]", strerror(errno)); + } + /* + * Otherwise, ERANGE was returned, meaning the buffer + * wasn't big enough. + */ + size = size * 3 / 2; + buffer = sresize(buffer, size, char); + } +} + +/* + * Wait for some network data and process it. + */ +int ssh_sftp_loop_iteration(void) +{ + fd_set rset, wset, xset; + int i, fdcount, fdsize, *fdlist; + int fd, fdstate, rwx, ret, maxfd; + + fdlist = NULL; + fdcount = fdsize = 0; + + /* Count the currently active fds. */ + i = 0; + for (fd = first_fd(&fdstate, &rwx); fd >= 0; + fd = next_fd(&fdstate, &rwx)) i++; + + if (i < 1) + return -1; /* doom */ + + /* Expand the fdlist buffer if necessary. */ + if (i > fdsize) { + fdsize = i + 16; + fdlist = sresize(fdlist, fdsize, int); + } + + FD_ZERO(&rset); + FD_ZERO(&wset); + FD_ZERO(&xset); + maxfd = 0; + + /* + * Add all currently open fds to the select sets, and store + * them in fdlist as well. + */ + fdcount = 0; + for (fd = first_fd(&fdstate, &rwx); fd >= 0; + fd = next_fd(&fdstate, &rwx)) { + fdlist[fdcount++] = fd; + if (rwx & 1) + FD_SET_MAX(fd, maxfd, rset); + if (rwx & 2) + FD_SET_MAX(fd, maxfd, wset); + if (rwx & 4) + FD_SET_MAX(fd, maxfd, xset); + } + + do { + ret = select(maxfd, &rset, &wset, &xset, NULL); + } while (ret < 0 && errno == EINTR); + + if (ret < 0) { + perror("select"); + exit(1); + } + + for (i = 0; i < fdcount; i++) { + fd = fdlist[i]; + /* + * We must process exceptional notifications before + * ordinary readability ones, or we may go straight + * past the urgent marker. + */ + if (FD_ISSET(fd, &xset)) + select_result(fd, 4); + if (FD_ISSET(fd, &rset)) + select_result(fd, 1); + if (FD_ISSET(fd, &wset)) + select_result(fd, 2); + } + + sfree(fdlist); + + return 0; +} + +/* + * Main program: do platform-specific initialisation and then call + * psftp_main(). + */ +int main(int argc, char *argv[]) +{ + uxsel_init(); + return psftp_main(argc, argv); +} -- 2.11.0