diff -ur ./ncftp/cmdlist.c ../ncftp-3.1.9_patched/ncftp/cmdlist.c --- ./ncftp/cmdlist.c 2005-01-01 22:23:25.000000000 +0100 +++ ../ncftp-3.1.9_patched/ncftp/cmdlist.c 2005-04-24 00:22:02.814840464 +0200 @@ -163,6 +163,13 @@ kCmdHidden, kNoMin, kNoMax, }, + { "edit", + EditCmd, + "file1 [file2...]", + "edit remote files", + kCmdMustBeConnected | kCompleteRemoteFile, + 1, kNoMax, + }, { "exit", (CmdProc) QuitCmd, "", diff -ur ./ncftp/cmds.c ../ncftp-3.1.9_patched/ncftp/cmds.c --- ./ncftp/cmds.c 2005-01-01 22:23:28.000000000 +0100 +++ ../ncftp-3.1.9_patched/ncftp/cmds.c 2005-04-24 00:22:02.816840160 +0200 @@ -87,7 +87,7 @@ extern char gFirewallUser[32]; extern char gFirewallPass[32]; extern char gFirewallExceptionList[]; -extern char gPager[], gHome[], gShell[]; +extern char gPager[], gEditor[], gHome[], gShell[]; extern char gOS[]; extern int gAutoResume; extern int gAutoSaveChangesToExistingBookmarks; @@ -775,6 +775,243 @@ +#if (defined(WIN32) || defined(_WINDOWS)) && !defined(__CYGWIN__) +#else +void +InitFilePair(FilePair* filePair) +{ + filePair->size = 0; + filePair->first = NULL; + filePair->last = NULL; +} + +FilePairElement* +AddFilePair(FilePair* filePair, char* remoteFile) +{ + char* name; + static char mask[] = ".XXXXXX"; /* for mkstemp template */ + static char temp[] = "/tmp/"; + + FilePairElement* newElement; + + /* allocate memory */ + newElement = malloc(sizeof(FilePairElement)); + if (newElement == NULL) { + free(newElement); + return NULL; + } + + /* remoteFile */ + newElement->remoteFile = malloc(strlen(remoteFile) + 1); + if (newElement->remoteFile == NULL) { + free(newElement->remoteFile); + free(newElement); + return NULL; + } + strcpy(newElement->remoteFile, remoteFile); + + /* localTmpFile */ + name = remoteFile; + if (name && strrchr(name, '/')) + name = strrchr(name, '/') + 1; + + newElement->localTmpFile = malloc(strlen(temp) + strlen(name) + strlen(mask) + 1); + if (newElement->localTmpFile == NULL) { + free(newElement->localTmpFile); + free(newElement->remoteFile); + free(newElement); + return NULL; + } + strcpy(newElement->localTmpFile, temp); + strcat(newElement->localTmpFile, name); + strcat(newElement->localTmpFile, mask); + + /* FTPGetOneFile3 does not take a file descriptor as dstfile! */ + close(mkstemp(newElement->localTmpFile)); + + /* insert last in list */ + newElement->next = NULL; + if (filePair->first == NULL) { + filePair->first = filePair->last = newElement; + } else { + filePair->last->next = newElement; + filePair->last = newElement; + } + filePair->size++; + + return newElement; +} + +void +FreeFilePair(FilePair* filePair) +{ + FilePairElement *fpe, *fpe_next; + + for (fpe_next = filePair->first; fpe_next != NULL; ) { + fpe = fpe_next; + fpe_next = fpe_next->next; + if (fpe->remoteFile) { + free(fpe->remoteFile); + fpe->remoteFile = NULL; + } + if (fpe->localTmpFile) { + unlink(fpe->localTmpFile); + free(fpe->localTmpFile); + fpe->localTmpFile = NULL; + } + free(fpe); + } + InitFilePair(filePair); +} + +void +EditCmd(const int argc, char **const argv, const CommandPtr cmdp, const ArgvInfoPtr aip) +{ + int i, result; + + char ans[32]; + char cmdbuf[2048]; + + FTPLineList globlist; + FTPLinePtr lp = NULL; + FilePair filePair; + FilePairElement* fpe; + + InitFilePair(&filePair); + + ARGSUSED(gUnusedArg); + for (i = 1; i < argc; i++) { + InitLineList(&globlist); + result = FTPRemoteGlob(&gConn, &globlist, argv[i], kGlobYes); + if (result == 0) { + for (lp = globlist.first; lp != NULL; lp = lp->next) { + result = FTPIsRegularFile(&gConn, lp->line); + switch (result) { + case 1: + if (AddFilePair(&filePair, lp->line) == NULL) { + (void) fprintf(stderr, "failed to AddFilePair %s\n", lp->line); + DisposeLineListContents(&globlist); + FreeFilePair(&filePair); + return; + } + break; + case 0: + (void) fprintf(stderr, "Can not edit directory - ignoring '%s'\n", lp->line); + break; + default: + for (;;) { + (void) printf("'%s' does not exist! Do you wish to create it? [Y]es [N]o > ", lp->line); + fflush(stdin); + (void) memset(ans, 0, sizeof(ans)); + (void) fgets(ans, sizeof(ans) - 1, stdin); + switch ((int) ans[0]) { + case 'y': + case 'Y': + if (AddFilePair(&filePair, argv[i]) == NULL) { + (void) fprintf(stderr, "failed to AddFilePair %s\n", lp->line); + DisposeLineListContents(&globlist); + FreeFilePair(&filePair); + return; + } + break; + case 'n': + case 'N': + ans[0] = 'N'; + ans[1] = '\0'; + break; + default: + ans[0] = '\0'; + + } + if (ans[0] != '\0') + break; + } + } + } + } else { + FTPPerror(&gConn, result, kErrCouldNotStartDataTransfer, "glob", argv[i]); + } + DisposeLineListContents(&globlist); + } + + if (filePair.first == NULL) { + (void) printf("nothing to edit!\n"); + FreeFilePair(&filePair); + return; + } + + for (fpe = filePair.first; fpe != NULL; fpe = fpe->next) { + /* get the files */ + if (FTPFileExists(&gConn, fpe->remoteFile) == kNoErr) { + result = FTPGetOneFile3(&gConn, fpe->remoteFile, fpe->localTmpFile, kTypeBinary, -1, kResumeNo, + kAppendNo, kDeleteNo, kNoFTPConfirmResumeDownloadProc, 0); + if (result < 0) { + FTPPerror(&gConn, result, kErrCouldNotStartDataTransfer, "get", fpe->remoteFile); + FreeFilePair(&filePair); + return; + } + } + } + + /* edit the files */ + /* use exec to avoid having a shell hanging around */ + (void) STRNCPY(cmdbuf, "exec "); + (void) STRNCAT(cmdbuf, gEditor); + for (fpe = filePair.first; fpe != NULL; fpe = fpe->next) { + (void) STRNCAT(cmdbuf, " "); + (void) STRNCAT(cmdbuf, fpe->localTmpFile); + } + result = system(cmdbuf); + if (result < 0) { + FreeFilePair(&filePair); + return; + } + + /* upload the changed files */ + for (fpe = filePair.first; fpe != NULL; fpe = fpe->next) { + + for (;;) { + (void) printf("Put edited file '%s'? [Y]es [N]o > ", fpe->remoteFile); + fflush(stdin); + (void) memset(ans, 0, sizeof(ans)); + (void) fgets(ans, sizeof(ans) - 1, stdin); + switch ((int) ans[0]) { + case 'y': + case 'Y': + result = FTPPutOneFile3(&gConn, fpe->localTmpFile, fpe->remoteFile, kTypeBinary, -1, kAppendNo, + NULL, NULL, kResumeNo, kDeleteNo, kNoFTPConfirmResumeUploadProc, 0); + if (result < 0) { + FTPPerror(&gConn, result, kErrCouldNotStartDataTransfer, "put", fpe->remoteFile); + (void) fprintf(stderr, "Local changes to '%s' can be recovered from '%s'\n", + fpe->remoteFile, fpe->localTmpFile); + fpe->localTmpFile = NULL; + } + break; + case 'n': + case 'N': + ans[0] = 'N'; + ans[1] = '\0'; + break; + default: + ans[0] = '\0'; + + } + if (ans[0] != '\0') + break; + } + } + FreeFilePair(&filePair); + FlushLsCache(); + + return; + +} /* EditCmd */ +#endif + + + + + static int NcFTPConfirmResumeDownloadProc( const FTPCIPtr cipUNUSED, @@ -4228,3 +4465,5 @@ if (gOS[0] != '\0') (void) printf("Platform: %s\n", gOS); } /* VersionCmd */ + +/* vim: set noet sw=8: */ diff -ur ./ncftp/cmds.h ../ncftp-3.1.9_patched/ncftp/cmds.h --- ./ncftp/cmds.h 2004-01-06 22:39:30.000000000 +0100 +++ ../ncftp-3.1.9_patched/ncftp/cmds.h 2005-04-24 00:22:02.817840008 +0200 @@ -5,6 +5,21 @@ * */ +typedef struct FilePairElement { + struct FilePairElement* next; + char* remoteFile; + char* localTmpFile; +} FilePairElement; + +typedef struct FilePair { + struct FilePairElement *first, *last; + unsigned int size; +} FilePair; + +extern void InitFilePair(FilePair*); +extern void FreeFilePair(FilePair*); +extern FilePairElement* AddFilePair(FilePair*, char*); + /* cmds.c */ int PromptForBookmarkName(BookmarkPtr); void CurrentURL(char *, size_t, int); @@ -23,6 +38,7 @@ void DebugCmd(const int, char **const, const CommandPtr, const ArgvInfoPtr); void DeleteCmd(const int, char **const, const CommandPtr, const ArgvInfoPtr); void EchoCmd(const int, char **const, const CommandPtr, const ArgvInfoPtr); +void EditCmd(const int, char **const, const CommandPtr, const ArgvInfoPtr); void InitTransferType(void); void GetCmd(const int, char **const, const CommandPtr, const ArgvInfoPtr); void HelpCmd(const int, char **const, const CommandPtr, const ArgvInfoPtr); @@ -62,3 +78,5 @@ void TypeCmd(const int, char **const, const CommandPtr, const ArgvInfoPtr); void UmaskCmd(const int, char **const, const CommandPtr, const ArgvInfoPtr); void VersionCmd(const int, char **const, const CommandPtr, const ArgvInfoPtr); + +/* vim: set noet sw=8: */ diff -ur ./ncftp/pref.c ../ncftp-3.1.9_patched/ncftp/pref.c --- ./ncftp/pref.c 2005-01-01 22:23:44.000000000 +0100 +++ ../ncftp-3.1.9_patched/ncftp/pref.c 2005-04-24 00:22:02.817840008 +0200 @@ -23,6 +23,9 @@ /* Their $PAGER. */ char gPager[128]; +/* Their $EDITOR. */ +char gEditor[128]; + /* These correspond to the various timeouts from LibNcFTP. */ int gConnTimeout, gXferTimeout, gCtrlTimeout; @@ -600,6 +603,7 @@ InitPrefs(void) { char *tok1; + char *tok2; /* Set default values. */ gPager[0] = '\0'; @@ -655,6 +659,15 @@ } else { (void) STRNCPY(gPager, "more"); } + +#if (defined(WIN32) || defined(_WINDOWS)) && !defined(__CYGWIN__) +#else + tok2 = getenv("EDITOR"); + if ((tok2 != NULL) && (tok2[0] != '\0')) + (void) STRNCPY(gEditor, tok2); + else + (void) STRNCPY(gEditor, "vi"); +#endif } /* InitPrefs */