From 876eefd49f8857d4e6c87b822fe29d88e9a5230d Mon Sep 17 00:00:00 2001 From: simon Date: Tue, 2 Sep 2003 09:00:35 +0000 Subject: [PATCH] Remove CRs. Oops :-/ git-svn-id: svn://svn.tartarus.org/sgt/putty@3435 cda61777-01e9-0310-a592-d414129be87e --- psftp.h | 300 +++++++++++----------- unix/uxsftp.c | 812 +++++++++++++++++++++++++++++----------------------------- 2 files changed, 556 insertions(+), 556 deletions(-) diff --git a/psftp.h b/psftp.h index 44911f59..0034f84a 100644 --- a/psftp.h +++ b/psftp.h @@ -1,150 +1,150 @@ -/* - * psftp.h: interface between psftp.c / scp.c and each - * platform-specific SFTP module. - */ - -#ifndef PUTTY_PSFTP_H -#define PUTTY_PSFTP_H - -/* - * psftp_getcwd returns the local current directory. The returned - * string must be freed by the caller. - */ -char *psftp_getcwd(void); - -/* - * psftp_lcd changes the local current directory. The return value - * is NULL on success, or else an error message which must be freed - * by the caller. - */ -char *psftp_lcd(char *newdir); - -/* - * Retrieve file times on a local file. Must return two unsigned - * longs in POSIX time_t format. - */ -void get_file_times(char *filename, unsigned long *mtime, - unsigned long *atime); - -/* - * One iteration of the PSFTP event loop: wait for network data and - * process it, once. - */ -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[]); - -/* - * These functions are used by PSCP to transmit progress updates - * and error information to a GUI window managing it. This will - * probably only ever be supported on Windows, so these functions - * can safely be stubs on all other platforms. - */ -void gui_update_stats(char *name, unsigned long size, - int percentage, unsigned long elapsed, - unsigned long done, unsigned long eta, - unsigned long ratebs); -void gui_send_errcount(int list, int errs); -void gui_send_char(int is_stderr, int c); -void gui_enable(char *arg); - -/* - * It's likely that a given platform's implementation of file - * transfer utilities is going to want to do things with them that - * aren't present in stdio. Hence we supply an alternative - * abstraction for file access functions. - * - * This abstraction tells you the size and access times when you - * open an existing file (platforms may choose the meaning of the - * file times if it's not clear; whatever they choose will be what - * PSCP sends to the server as mtime and atime), and lets you set - * the times when saving a new file. - * - * On the other hand, the abstraction is pretty simple: it supports - * only opening a file and reading it, or creating a file and - * writing it. (FIXME: to use this in PSFTP it will also need to - * support seeking to a starting point for restarted transfers.) - * None of this read-and-write, seeking-back-and-forth stuff. - */ -typedef struct RFile RFile; -typedef struct WFile WFile; -/* Output params size, mtime and atime can all be NULL if desired */ -RFile *open_existing_file(char *name, unsigned long *size, - unsigned long *mtime, unsigned long *atime); -/* Returns <0 on error, 0 on eof, or number of bytes read, as usual */ -int read_from_file(RFile *f, void *buffer, int length); -/* Closes and frees the RFile */ -void close_rfile(RFile *f); -WFile *open_new_file(char *name); -/* Returns <0 on error, 0 on eof, or number of bytes written, as usual */ -int write_to_file(WFile *f, void *buffer, int length); -void set_file_times(WFile *f, unsigned long mtime, unsigned long atime); -/* Closes and frees the WFile */ -void close_wfile(WFile *f); - -/* - * Determine the type of a file: nonexistent, file, directory or - * weird. `weird' covers anything else - named pipes, Unix sockets, - * device files, fish, badgers, you name it. Things marked `weird' - * will be skipped over in recursive file transfers, so the only - * real reason for not lumping them in with `nonexistent' is that - * it allows a slightly more sane error message. - */ -enum { - FILE_TYPE_NONEXISTENT, FILE_TYPE_FILE, FILE_TYPE_DIRECTORY, FILE_TYPE_WEIRD -}; -int file_type(char *name); - -/* - * Read all the file names out of a directory. - */ -typedef struct DirHandle DirHandle; -DirHandle *open_directory(char *name); -/* The string returned from this will need freeing if not NULL */ -char *read_filename(DirHandle *dir); -void close_directory(DirHandle *dir); - -/* - * Test a filespec to see whether it's a local wildcard or not. - * Return values: - * - * - WCTYPE_WILDCARD (this is a wildcard). - * - WCTYPE_FILENAME (this is a single file name). - * - WCTYPE_NONEXISTENT (whichever it was, nothing of that name exists). - * - * Some platforms may choose not to support local wildcards when - * they come from the command line; in this case they simply never - * return WCTYPE_WILDCARD, but still test the file's existence. - * (However, all platforms will probably want to support wildcards - * inside the PSFTP CLI.) - */ -enum { - WCTYPE_NONEXISTENT, WCTYPE_FILENAME, WCTYPE_WILDCARD -}; -int test_wildcard(char *name, int cmdline); - -/* - * Actually return matching file names for a local wildcard. - */ -typedef struct WildcardMatcher WildcardMatcher; -WildcardMatcher *begin_wildcard_matching(char *name); -/* The string returned from this will need freeing if not NULL */ -char *wildcard_get_filename(WildcardMatcher *dir); -void finish_wildcard_matching(WildcardMatcher *dir); - -/* - * Create a directory. Returns 0 on error, !=0 on success. - */ -int create_directory(char *name); - -/* - * Concatenate a directory name and a file name. The way this is - * done will depend on the OS. - */ -char *dir_file_cat(char *dir, char *file); - -#endif /* PUTTY_PSFTP_H */ +/* + * psftp.h: interface between psftp.c / scp.c and each + * platform-specific SFTP module. + */ + +#ifndef PUTTY_PSFTP_H +#define PUTTY_PSFTP_H + +/* + * psftp_getcwd returns the local current directory. The returned + * string must be freed by the caller. + */ +char *psftp_getcwd(void); + +/* + * psftp_lcd changes the local current directory. The return value + * is NULL on success, or else an error message which must be freed + * by the caller. + */ +char *psftp_lcd(char *newdir); + +/* + * Retrieve file times on a local file. Must return two unsigned + * longs in POSIX time_t format. + */ +void get_file_times(char *filename, unsigned long *mtime, + unsigned long *atime); + +/* + * One iteration of the PSFTP event loop: wait for network data and + * process it, once. + */ +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[]); + +/* + * These functions are used by PSCP to transmit progress updates + * and error information to a GUI window managing it. This will + * probably only ever be supported on Windows, so these functions + * can safely be stubs on all other platforms. + */ +void gui_update_stats(char *name, unsigned long size, + int percentage, unsigned long elapsed, + unsigned long done, unsigned long eta, + unsigned long ratebs); +void gui_send_errcount(int list, int errs); +void gui_send_char(int is_stderr, int c); +void gui_enable(char *arg); + +/* + * It's likely that a given platform's implementation of file + * transfer utilities is going to want to do things with them that + * aren't present in stdio. Hence we supply an alternative + * abstraction for file access functions. + * + * This abstraction tells you the size and access times when you + * open an existing file (platforms may choose the meaning of the + * file times if it's not clear; whatever they choose will be what + * PSCP sends to the server as mtime and atime), and lets you set + * the times when saving a new file. + * + * On the other hand, the abstraction is pretty simple: it supports + * only opening a file and reading it, or creating a file and + * writing it. (FIXME: to use this in PSFTP it will also need to + * support seeking to a starting point for restarted transfers.) + * None of this read-and-write, seeking-back-and-forth stuff. + */ +typedef struct RFile RFile; +typedef struct WFile WFile; +/* Output params size, mtime and atime can all be NULL if desired */ +RFile *open_existing_file(char *name, unsigned long *size, + unsigned long *mtime, unsigned long *atime); +/* Returns <0 on error, 0 on eof, or number of bytes read, as usual */ +int read_from_file(RFile *f, void *buffer, int length); +/* Closes and frees the RFile */ +void close_rfile(RFile *f); +WFile *open_new_file(char *name); +/* Returns <0 on error, 0 on eof, or number of bytes written, as usual */ +int write_to_file(WFile *f, void *buffer, int length); +void set_file_times(WFile *f, unsigned long mtime, unsigned long atime); +/* Closes and frees the WFile */ +void close_wfile(WFile *f); + +/* + * Determine the type of a file: nonexistent, file, directory or + * weird. `weird' covers anything else - named pipes, Unix sockets, + * device files, fish, badgers, you name it. Things marked `weird' + * will be skipped over in recursive file transfers, so the only + * real reason for not lumping them in with `nonexistent' is that + * it allows a slightly more sane error message. + */ +enum { + FILE_TYPE_NONEXISTENT, FILE_TYPE_FILE, FILE_TYPE_DIRECTORY, FILE_TYPE_WEIRD +}; +int file_type(char *name); + +/* + * Read all the file names out of a directory. + */ +typedef struct DirHandle DirHandle; +DirHandle *open_directory(char *name); +/* The string returned from this will need freeing if not NULL */ +char *read_filename(DirHandle *dir); +void close_directory(DirHandle *dir); + +/* + * Test a filespec to see whether it's a local wildcard or not. + * Return values: + * + * - WCTYPE_WILDCARD (this is a wildcard). + * - WCTYPE_FILENAME (this is a single file name). + * - WCTYPE_NONEXISTENT (whichever it was, nothing of that name exists). + * + * Some platforms may choose not to support local wildcards when + * they come from the command line; in this case they simply never + * return WCTYPE_WILDCARD, but still test the file's existence. + * (However, all platforms will probably want to support wildcards + * inside the PSFTP CLI.) + */ +enum { + WCTYPE_NONEXISTENT, WCTYPE_FILENAME, WCTYPE_WILDCARD +}; +int test_wildcard(char *name, int cmdline); + +/* + * Actually return matching file names for a local wildcard. + */ +typedef struct WildcardMatcher WildcardMatcher; +WildcardMatcher *begin_wildcard_matching(char *name); +/* The string returned from this will need freeing if not NULL */ +char *wildcard_get_filename(WildcardMatcher *dir); +void finish_wildcard_matching(WildcardMatcher *dir); + +/* + * Create a directory. Returns 0 on error, !=0 on success. + */ +int create_directory(char *name); + +/* + * Concatenate a directory name and a file name. The way this is + * done will depend on the OS. + */ +char *dir_file_cat(char *dir, char *file); + +#endif /* PUTTY_PSFTP_H */ diff --git a/unix/uxsftp.c b/unix/uxsftp.c index 69d4c456..cae66c45 100644 --- a/unix/uxsftp.c +++ b/unix/uxsftp.c @@ -1,406 +1,406 @@ -/* - * uxsftp.c: the Unix-specific parts of PSFTP and PSCP. - */ - -#include -#include -#include -#include -#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) -{ - 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; -} - -/* - * Stubs for the GUI feedback mechanism in Windows PSCP. - */ -void gui_update_stats(char *name, unsigned long size, - int percentage, unsigned long elapsed, - unsigned long done, unsigned long eta, - unsigned long ratebs) {} -void gui_send_errcount(int list, int errs) {} -void gui_send_char(int is_stderr, int c) {} -void gui_enable(char *arg) {} - - -/* - * 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); - } -} - -struct RFile { - int fd; -}; - -RFile *open_existing_file(char *name, unsigned long *size, - unsigned long *mtime, unsigned long *atime) -{ - int fd; - RFile *ret; - - fd = open(name, O_RDONLY); - if (fd < 0) - return NULL; - - ret = snew(RFile); - ret->fd = fd; - - if (size || mtime || atime) { - struct stat statbuf; - if (fstat(fd, &statbuf) < 0) { - fprintf(stderr, "%s: stat: %s\n", name, strerror(errno)); - memset(&statbuf, 0, sizeof(statbuf)); - } - - if (size) - *size = statbuf.st_size; - - if (mtime) - *mtime = statbuf.st_mtime; - - if (atime) - *atime = statbuf.st_atime; - } - - return ret; -} - -int read_from_file(RFile *f, void *buffer, int length) -{ - return read(f->fd, buffer, length); -} - -void close_rfile(RFile *f) -{ - close(f->fd); - sfree(f); -} - -struct WFile { - int fd; - char *name; -}; - -WFile *open_new_file(char *name) -{ - int fd; - WFile *ret; - - fd = open(name, O_CREAT | O_TRUNC | O_WRONLY, 0666); - if (fd < 0) - return NULL; - - ret = snew(WFile); - ret->fd = fd; - ret->name = dupstr(name); - - return ret; -} - -int write_to_file(WFile *f, void *buffer, int length) -{ - char *p = (char *)buffer; - int so_far = 0; - - /* Keep trying until we've really written as much as we can. */ - while (length > 0) { - int ret = write(f->fd, p, length); - - if (ret < 0) - return ret; - - if (ret == 0) - break; - - p += ret; - length -= ret; - so_far += ret; - } - - return so_far; -} - -void set_file_times(WFile *f, unsigned long mtime, unsigned long atime) -{ - struct utimbuf ut; - - ut.actime = atime; - ut.modtime = mtime; - - utime(f->name, &ut); -} - -/* Closes and frees the WFile */ -void close_wfile(WFile *f) -{ - close(f->fd); - sfree(f->name); - sfree(f); -} - -int file_type(char *name) -{ - struct stat statbuf; - - if (stat(name, &statbuf) < 0) { - if (errno != ENOENT) - fprintf(stderr, "%s: stat: %s\n", name, strerror(errno)); - return FILE_TYPE_NONEXISTENT; - } - - if (S_ISREG(statbuf.st_mode)) - return FILE_TYPE_FILE; - - if (S_ISDIR(statbuf.st_mode)) - return FILE_TYPE_DIRECTORY; - - return FILE_TYPE_WEIRD; -} - -struct DirHandle { - DIR *dir; -}; - -DirHandle *open_directory(char *name) -{ - DIR *dir; - DirHandle *ret; - - dir = opendir(name); - if (!dir) - return NULL; - - ret = snew(DirHandle); - ret->dir = dir; - return ret; -} - -char *read_filename(DirHandle *dir) -{ - struct dirent *de; - - do { - de = readdir(dir->dir); - if (de == NULL) - return NULL; - } while ((de->d_name[0] == '.' && - (de->d_name[1] == '\0' || - (de->d_name[1] == '.' && de->d_name[2] == '\0')))); - - return dupstr(de->d_name); -} - -void close_directory(DirHandle *dir) -{ - closedir(dir->dir); - sfree(dir); -} - -int test_wildcard(char *name, int cmdline) -{ - /* - * On Unix, we currently don't support local wildcards at all. - * We will have to do so (FIXME) once PSFTP starts implementing - * mput, but until then we can assume `cmdline' is always set. - */ - struct stat statbuf; - - assert(cmdline); - if (stat(name, &statbuf) < 0) - return WCTYPE_NONEXISTENT; - else - return WCTYPE_FILENAME; -} - -/* - * Actually return matching file names for a local wildcard. FIXME: - * we currently don't support this at all. - */ -struct WildcardMatcher { - int x; -}; -WildcardMatcher *begin_wildcard_matching(char *name) { return NULL; } -char *wildcard_get_filename(WildcardMatcher *dir) { return NULL; } -void finish_wildcard_matching(WildcardMatcher *dir) {} - -int create_directory(char *name) -{ - return mkdir(name, 0777) == 0; -} - -char *dir_file_cat(char *dir, char *file) -{ - return dupcat(dir, "/", file, NULL); -} - -/* - * 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); -} +/* + * uxsftp.c: the Unix-specific parts of PSFTP and PSCP. + */ + +#include +#include +#include +#include +#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) +{ + 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; +} + +/* + * Stubs for the GUI feedback mechanism in Windows PSCP. + */ +void gui_update_stats(char *name, unsigned long size, + int percentage, unsigned long elapsed, + unsigned long done, unsigned long eta, + unsigned long ratebs) {} +void gui_send_errcount(int list, int errs) {} +void gui_send_char(int is_stderr, int c) {} +void gui_enable(char *arg) {} + + +/* + * 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); + } +} + +struct RFile { + int fd; +}; + +RFile *open_existing_file(char *name, unsigned long *size, + unsigned long *mtime, unsigned long *atime) +{ + int fd; + RFile *ret; + + fd = open(name, O_RDONLY); + if (fd < 0) + return NULL; + + ret = snew(RFile); + ret->fd = fd; + + if (size || mtime || atime) { + struct stat statbuf; + if (fstat(fd, &statbuf) < 0) { + fprintf(stderr, "%s: stat: %s\n", name, strerror(errno)); + memset(&statbuf, 0, sizeof(statbuf)); + } + + if (size) + *size = statbuf.st_size; + + if (mtime) + *mtime = statbuf.st_mtime; + + if (atime) + *atime = statbuf.st_atime; + } + + return ret; +} + +int read_from_file(RFile *f, void *buffer, int length) +{ + return read(f->fd, buffer, length); +} + +void close_rfile(RFile *f) +{ + close(f->fd); + sfree(f); +} + +struct WFile { + int fd; + char *name; +}; + +WFile *open_new_file(char *name) +{ + int fd; + WFile *ret; + + fd = open(name, O_CREAT | O_TRUNC | O_WRONLY, 0666); + if (fd < 0) + return NULL; + + ret = snew(WFile); + ret->fd = fd; + ret->name = dupstr(name); + + return ret; +} + +int write_to_file(WFile *f, void *buffer, int length) +{ + char *p = (char *)buffer; + int so_far = 0; + + /* Keep trying until we've really written as much as we can. */ + while (length > 0) { + int ret = write(f->fd, p, length); + + if (ret < 0) + return ret; + + if (ret == 0) + break; + + p += ret; + length -= ret; + so_far += ret; + } + + return so_far; +} + +void set_file_times(WFile *f, unsigned long mtime, unsigned long atime) +{ + struct utimbuf ut; + + ut.actime = atime; + ut.modtime = mtime; + + utime(f->name, &ut); +} + +/* Closes and frees the WFile */ +void close_wfile(WFile *f) +{ + close(f->fd); + sfree(f->name); + sfree(f); +} + +int file_type(char *name) +{ + struct stat statbuf; + + if (stat(name, &statbuf) < 0) { + if (errno != ENOENT) + fprintf(stderr, "%s: stat: %s\n", name, strerror(errno)); + return FILE_TYPE_NONEXISTENT; + } + + if (S_ISREG(statbuf.st_mode)) + return FILE_TYPE_FILE; + + if (S_ISDIR(statbuf.st_mode)) + return FILE_TYPE_DIRECTORY; + + return FILE_TYPE_WEIRD; +} + +struct DirHandle { + DIR *dir; +}; + +DirHandle *open_directory(char *name) +{ + DIR *dir; + DirHandle *ret; + + dir = opendir(name); + if (!dir) + return NULL; + + ret = snew(DirHandle); + ret->dir = dir; + return ret; +} + +char *read_filename(DirHandle *dir) +{ + struct dirent *de; + + do { + de = readdir(dir->dir); + if (de == NULL) + return NULL; + } while ((de->d_name[0] == '.' && + (de->d_name[1] == '\0' || + (de->d_name[1] == '.' && de->d_name[2] == '\0')))); + + return dupstr(de->d_name); +} + +void close_directory(DirHandle *dir) +{ + closedir(dir->dir); + sfree(dir); +} + +int test_wildcard(char *name, int cmdline) +{ + /* + * On Unix, we currently don't support local wildcards at all. + * We will have to do so (FIXME) once PSFTP starts implementing + * mput, but until then we can assume `cmdline' is always set. + */ + struct stat statbuf; + + assert(cmdline); + if (stat(name, &statbuf) < 0) + return WCTYPE_NONEXISTENT; + else + return WCTYPE_FILENAME; +} + +/* + * Actually return matching file names for a local wildcard. FIXME: + * we currently don't support this at all. + */ +struct WildcardMatcher { + int x; +}; +WildcardMatcher *begin_wildcard_matching(char *name) { return NULL; } +char *wildcard_get_filename(WildcardMatcher *dir) { return NULL; } +void finish_wildcard_matching(WildcardMatcher *dir) {} + +int create_directory(char *name) +{ + return mkdir(name, 0777) == 0; +} + +char *dir_file_cat(char *dir, char *file) +{ + return dupcat(dir, "/", file, NULL); +} + +/* + * 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