/* spoolutil.c * * Copyright (c) 1992-2005 by Mike Gleason. * All rights reserved. * */ #include "syshdrs.h" #ifdef PRAGMA_HDRSTOP # pragma hdrstop #endif #ifdef HAVE_LONG_FILE_NAMES #include "spool.h" #include "util.h" int gSpoolSerial = 0; extern FTPLibraryInfo gLib; extern char gOurDirectoryPath[]; #if (defined(WIN32) || defined(_WINDOWS)) && !defined(__CYGWIN__) extern char gOurInstallationPath[]; #endif #ifdef ncftp extern int gUnprocessedJobs; #endif int MkSpoolDir(char *sdir, size_t size) { struct stat st; *sdir = '\0'; /* Don't create in root directory. */ if (gOurDirectoryPath[0] != '\0') { (void) OurDirectoryPath(sdir, size, kSpoolDir); if ((stat(sdir, &st) < 0) && (MkDirs(sdir, 00700) < 0)) { perror(sdir); return (-1); } else { return (0); } } return (-1); } /* MkSpoolDir */ void SpoolName(char *const sp, const size_t size, const int flag, const int serial, time_t when) { char dstr[32]; struct tm lt; if ((when == (time_t) 0) || (when == (time_t) -1)) (void) time(&when); if (Gmtime(when, <) == NULL) { /* impossible */ (void) Strncpy(dstr, "20010101-000000", size); } else { (void) strftime(dstr, sizeof(dstr), "%Y%m%d-%H%M%S", <); } #if (defined(WIN32) || defined(_WINDOWS)) && !defined(__CYGWIN__) (void) sprintf(sp, "%c-%s-%08X-%d", flag, dstr, (unsigned int) getpid(), serial ); #else # ifdef HAVE_SNPRINTF (void) snprintf(sp, size - 1, # else (void) sprintf(sp, # endif "%c-%s-%06d-%d", flag, dstr, (unsigned int) getpid(), serial ); #endif } /* SpoolName */ static int WriteSpoolLine(FILE *const ofp, const char *const line) { int c; const char *cp; c = 0; for (cp = line; *cp; cp++) { c = (int) *cp; if ((c == '\n') && (cp[1] != '\0')) { if (putc('\\', ofp) == EOF) return (-1); } if (putc(c, ofp) == EOF) return (-1); } if (c != '\n') { c = '\n'; if (putc(c, ofp) == EOF) return (-1); } return (0); } /* WriteSpoolLine */ int SpoolX( FILE *const ofp, const char *sdir, const char *const op, const char *const rfile, const char *const rdir, const char *const lfile, const char *const ldir, const char *const host, const char *const ip, const unsigned int port, const char *const user, const char *const passclear, const char *const xacct, const int xtype, const int recursive, const int deleteflag, const int passive, const char *const preftpcmd, const char *const perfileftpcmd, const char *const postftpcmd, const char *const preshellcmd, const char *const postshellcmd, const time_t when, const unsigned int delaySinceLastFailure, const char *const manualOverrideFeatures, const int UNUSED(reserved) ) { char sdir2[256]; char pass[160]; char sname[64], sname2[64]; char spathname[256]; char spathname2[256]; char ldir2[256]; char *ldir3; FILE *fp; #if (defined(WIN32) || defined(_WINDOWS)) && !defined(__CYGWIN__) #else mode_t um; #endif LIBNCFTP_USE_VAR(reserved); gSpoolSerial++; SpoolName(sname2, sizeof(sname2), op[0], gSpoolSerial, when); if (ofp == NULL) { if (sdir == NULL) { if (MkSpoolDir(sdir2, sizeof(sdir2)) < 0) return (-1); sdir = sdir2; } Path(spathname2, sizeof(spathname2), sdir, sname2); STRNCPY(sname, sname2); sname[0] = 'z'; Path(spathname, sizeof(spathname), sdir, sname); } #if (defined(WIN32) || defined(_WINDOWS)) && !defined(__CYGWIN__) fp = (ofp == NULL) ? fopen(spathname, FOPEN_WRITE_TEXT) : ofp; #else um = umask(077); fp = (ofp == NULL) ? fopen(spathname, FOPEN_WRITE_TEXT) : ofp; (void) umask(um); #endif if (fp == NULL) return (-1); if (fprintf(fp, "# This is a NcFTP spool file entry.\n") < 0) goto err; if ((ofp == NULL) && (fprintf(fp, "# Run the \"ncftpbatch\" program to process the spool directory.\n#\n") < 0)) goto err; if (fprintf(fp, "job-name=%s\n", sname2) < 0) goto err; if (fprintf(fp, "op=%s\n", op) < 0) goto err; if ((delaySinceLastFailure != 0) && (fprintf(fp, "delay-since-last-failure=%u\n", delaySinceLastFailure) < 0)) goto err; if (fprintf(fp, "hostname=%s\n", host) < 0) goto err; if ((ip != NULL) && (ip[0] != '\0') && (fprintf(fp, "host-ip=%s\n", ip) < 0)) goto err; if ((port != 0) && (port != (unsigned int) kDefaultFTPPort) && (fprintf(fp, "port=%u\n", port) < 0)) goto err; if ((user != NULL) && (user[0] != '\0') && (strcmp(user, "anonymous") != 0) && (fprintf(fp, "user=%s\n", user) < 0)) goto err; if ((strcmp(user, "anonymous") != 0) && (passclear != NULL) && (passclear[0] != '\0')) { (void) memcpy(pass, kPasswordMagic, kPasswordMagicLen); ToBase64(pass + kPasswordMagicLen, passclear, strlen(passclear), 1); if (fprintf(fp, "pass=%s\n", pass) < 0) goto err; } else if ((strcmp(user, "anonymous") == 0) && (gLib.defaultAnonPassword[0] != '\0')) { if (fprintf(fp, "pass=%s\n", gLib.defaultAnonPassword) < 0) goto err; } if ((xacct != NULL) && (xacct[0] != '\0') && (fprintf(fp, "acct=%s\n", xacct) < 0)) goto err; if (fprintf(fp, "xtype=%c\n", xtype) < 0) goto err; if ((recursive != 0) && (fprintf(fp, "recursive=%s\n", YESNO(recursive)) < 0)) goto err; if ((deleteflag != 0) && (fprintf(fp, "delete=%s\n", YESNO(deleteflag)) < 0)) goto err; if (fprintf(fp, "passive=%d\n", passive) < 0) goto err; if (fprintf(fp, "remote-dir=%s\n", rdir) < 0) goto err; if ((ldir == NULL) || (ldir[0] == '\0') || (strcmp(ldir, ".") == 0)) { /* Use current process' working directory. */ FTPGetLocalCWD(ldir2, sizeof(ldir2)); if (fprintf(fp, "local-dir=%s\n", ldir2) < 0) goto err; #if (defined(WIN32) || defined(_WINDOWS)) && !defined(__CYGWIN__) } else if ((ldir[0] != '/') && (ldir[0] != '\\')) { FTPGetLocalCWD(ldir2, sizeof(ldir2)); if (DPathCat(&ldir3, ldir2, ldir, 1) == 0) { if (fprintf(fp, "local-dir=%s\n", ldir3) < 0) goto err; free(ldir3); } #else } else if (ldir[0] != '/') { FTPGetLocalCWD(ldir2, sizeof(ldir2)); if (DPathCat(&ldir3, ldir2, ldir, 0) == 0) { if (fprintf(fp, "local-dir=%s\n", ldir3) < 0) goto err; free(ldir3); } #endif } else { if (fprintf(fp, "local-dir=%s\n", ldir) < 0) goto err; } if (fprintf(fp, "remote-file=%s\n", rfile) < 0) goto err; if (fprintf(fp, "local-file=%s\n", lfile) < 0) goto err; if ((manualOverrideFeatures != NULL) && (manualOverrideFeatures[0] != '\0')) { if (fprintf(fp, "manual-override-features=") < 0) goto err; if (WriteSpoolLine(fp, manualOverrideFeatures) < 0) goto err; } if ((preftpcmd != NULL) && (preftpcmd[0] != '\0')) { if (fprintf(fp, "pre-ftp-command=") < 0) goto err; if (WriteSpoolLine(fp, preftpcmd) < 0) goto err; } if ((perfileftpcmd != NULL) && (perfileftpcmd[0] != '\0')) { if (fprintf(fp, "per-file-ftp-command=") < 0) goto err; if (WriteSpoolLine(fp, perfileftpcmd) < 0) goto err; } if ((postftpcmd != NULL) && (postftpcmd[0] != '\0')) { if (fprintf(fp, "post-ftp-command=") < 0) goto err; if (WriteSpoolLine(fp, postftpcmd) < 0) goto err; } if ((preshellcmd != NULL) && (preshellcmd[0] != '\0')) { if (fprintf(fp, "pre-shell-command=") < 0) goto err; if (WriteSpoolLine(fp, preshellcmd) < 0) goto err; } if ((postshellcmd != NULL) && (postshellcmd[0] != '\0')) { if (fprintf(fp, "post-shell-command=") < 0) goto err; if (WriteSpoolLine(fp, postshellcmd) < 0) goto err; } if ((fp != ofp) && (fclose(fp) < 0)) goto err2; /* Move the spool file into its "live" name. */ if ((fp != ofp) && (rename(spathname, spathname2) < 0)) { perror("rename spoolfile failed"); goto err3; } #ifdef ncftp gUnprocessedJobs++; #endif return (0); err: if (fp != ofp) (void) fclose(fp); err2: perror("write to spool file failed"); err3: if (fp != ofp) (void) unlink(spathname); return (-1); } /* SpoolX */ void RunBatch(void) { #if (defined(WIN32) || defined(_WINDOWS)) && !defined(__CYGWIN__) char ncftpbatch[260]; const char *prog; int winExecResult; if (gOurInstallationPath[0] == '\0') { (void) fprintf(stderr, "Cannot find path to %s. Please re-run Setup.\n", "ncftpbatch.exe"); return; } prog = ncftpbatch; OurInstallationPath(ncftpbatch, sizeof(ncftpbatch), "ncftpbatch.exe"); winExecResult = WinExec(prog, SW_SHOWNORMAL); if (winExecResult <= 31) switch (winExecResult) { case ERROR_BAD_FORMAT: fprintf(stderr, "Could not run %s: %s\n", prog, "The .EXE file is invalid"); return; case ERROR_FILE_NOT_FOUND: fprintf(stderr, "Could not run %s: %s\n", prog, "The specified file was not found."); return; case ERROR_PATH_NOT_FOUND: fprintf(stderr, "Could not run %s: %s\n", prog, "The specified path was not found."); return; default: fprintf(stderr, "Could not run %s: Unknown error #%d.\n", prog, winExecResult); return; } #else char *argv[8]; pid_t pid = 0; #ifdef BINDIR char ncftpbatch[256]; STRNCPY(ncftpbatch, BINDIR); STRNCAT(ncftpbatch, "/"); STRNCAT(ncftpbatch, "ncftpbatch"); #endif /* BINDIR */ pid = fork(); if (pid < 0) { perror("fork"); } else if (pid == 0) { argv[0] = strdup("ncftpbatch"); argv[1] = strdup("-d"); argv[2] = NULL; #ifdef BINDIR (void) execv(ncftpbatch, argv); (void) fprintf(stderr, "Could not run %s. Is it in installed as %s?\n", argv[0], ncftpbatch); #else /* BINDIR */ (void) execvp(argv[0], argv); (void) fprintf(stderr, "Could not run %s. Is it in your $PATH?\n", argv[0]); #endif /* BINDIR */ perror(argv[0]); exit(1); } if (pid > 1) { #ifdef HAVE_WAITPID (void) waitpid(pid, NULL, 0); #else (void) wait(NULL); #endif /* HAVE_WAITPID */ } #endif /* UNIX */ } /* RunBatch */ #else /* ! HAVE_LONG_FILE_NAMES */ int SpoolX( FILE *const ofp, const char *sdir, const char *const op, const char *const rfile, const char *const rdir, const char *const lfile, const char *const ldir, const char *const host, const char *const ip, const unsigned int port, const char *const user, const char *const passclear, const char *const xacct, const int xtype, const int recursive, const int deleteflag, const int passive, const char *const preftpcmd, const char *const perfileftpcmd, const char *const postftpcmd, const char *const preshellcmd, const char *const postshellcmd, const time_t when, const unsigned int delaySinceLastFailure) { return (-1); } void RunBatch(void) { fprintf(stderr, "Background processing not available on this platform.\n"); } /* RunBatch */ #endif /* HAVE_LONG_FILE_NAMES */