Git conversion: Make reactos the root directory, move rosapps, rostests, wallpapers...
[reactos.git] / modules / rosapps / applications / net / ncftp / ncftp / spool.c
diff --git a/modules/rosapps/applications/net/ncftp/ncftp/spool.c b/modules/rosapps/applications/net/ncftp/ncftp/spool.c
new file mode 100644 (file)
index 0000000..24962f1
--- /dev/null
@@ -0,0 +1,496 @@
+/* spool.c
+ *
+ * Copyright (c) 1992-2001 by Mike Gleason.
+ * All rights reserved.
+ *
+ */
+
+#include "syshdrs.h"
+
+#ifdef HAVE_LONG_FILE_NAMES
+
+#include "spool.h"
+#ifdef ncftp
+#      include "trace.h"
+#endif
+#include "util.h"
+
+int gSpoolSerial = 0;
+int gUnprocessedJobs = 0;
+int gJobs = 0;
+int gHaveSpool = -1;
+
+extern FTPLibraryInfo gLib;
+extern char gOurDirectoryPath[], gOurInstallationPath[];
+extern void CloseControlConnection(const FTPCIPtr);
+
+
+
+void
+TruncBatchLog(void)
+{
+       char f[256];
+       struct stat st;
+       time_t t;
+       int fd;
+
+       if (gOurDirectoryPath[0] != '\0') {
+               time(&t);
+               t -= 86400;
+               (void) OurDirectoryPath(f, sizeof(f), kSpoolLog);
+               if ((stat(f, &st) == 0) && (st.st_mtime < t)) {
+                       /* Truncate old log file.
+                        * Do not remove it, since a process
+                        * could still conceivably be going.
+                        */
+                       fd = open(f, O_WRONLY|O_TRUNC, 00600);
+                       if (fd >= 0)
+                               close(fd);
+               }
+       }
+}      /* TruncBatchLog */
+
+
+
+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(const char *const sdir, char *sp, size_t size, int flag, int serial, time_t when)
+{
+       char sname[64];
+       char dstr[32];
+       struct tm *ltp;
+
+       if ((when == (time_t) 0) || (when == (time_t) -1))
+               (void) time(&when);
+       ltp = localtime(&when);
+       if (ltp == NULL) {
+               /* impossible */
+               (void) Strncpy(dstr, "19700101-000000", size);
+       } else {
+               (void) strftime(dstr, sizeof(dstr), "%Y%m%d-%H%M%S", ltp);
+       }
+       (void) Strncpy(sp, sdir, size);
+       (void) sprintf(sname, "/%c-%010u-%04x-%s",
+               flag,
+               (unsigned int) getpid(),
+               (serial % (16 * 16 * 16 * 16)),
+               dstr
+       );
+       (void) Strncat(sp, sname, size);
+}      /* SpoolName */
+
+
+
+
+int
+HaveSpool(void)
+{
+#if defined(WIN32) || defined(_WINDOWS)
+       char ncftpbatch[260];
+
+       if (gHaveSpool < 0) {
+               gHaveSpool = 0;
+               if (gOurInstallationPath[0] != '\0') {
+                       OurInstallationPath(ncftpbatch, sizeof(ncftpbatch), "ncftpbatch.exe");
+                       gHaveSpool = (_access(ncftpbatch, F_OK) == 0) ? 1 : 0;
+               }
+       }
+#elif defined(BINDIR)
+       char ncftpbatch[256];
+
+       if (gHaveSpool < 0) {
+               STRNCPY(ncftpbatch, BINDIR);
+               STRNCAT(ncftpbatch, "/");
+               STRNCAT(ncftpbatch, "ncftpbatch");
+               gHaveSpool = (access(ncftpbatch, X_OK) == 0) ? 1 : 0;
+       }
+#else  /* BINDIR */
+       if (gHaveSpool < 0) {
+               if (geteuid() == 0) {
+                       gHaveSpool = (access("/usr/bin/ncftpbatch", X_OK) == 0) ? 1 : 0;
+               } else {
+                       gHaveSpool = (system("ncftpbatch -X") == 0) ? 1 : 0;
+               }
+       }
+#endif /* BINDIR */
+
+       return (gHaveSpool);
+}      /* HaveSpool */
+
+
+
+
+int
+CanSpool(void)
+{
+       char sdir[256];
+
+       if (gOurDirectoryPath[0] == '\0') {
+               return (-1);
+       }
+       if (MkSpoolDir(sdir, sizeof(sdir)) < 0)
+               return (-1);
+       return (0);
+}      /* CanSpool */
+
+
+
+
+int
+SpoolX(
+       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,
+       int xtype,
+       int recursive,
+       int delete,
+       int passive,
+       const char *const precmd,
+       const char *const perfilecmd,
+       const char *const postcmd,
+       time_t when)
+{
+       char sdir[256];
+       char pass[160];
+       char spathname[256];
+       char spathname2[256];
+       char ldir2[256];
+       FILE *fp;
+#if defined(WIN32) || defined(_WINDOWS)
+#else
+       mode_t um;
+#endif
+
+       if (MkSpoolDir(sdir, sizeof(sdir)) < 0)
+               return (-1);
+
+       gSpoolSerial++;
+       SpoolName(sdir, spathname2, sizeof(spathname2), op[0], gSpoolSerial, when);
+       SpoolName(sdir, spathname, sizeof(spathname), 'z', gSpoolSerial, when);
+#if defined(WIN32) || defined(_WINDOWS)
+       fp = fopen(spathname, FOPEN_WRITE_TEXT);
+#else
+       um = umask(077);
+       fp = fopen(spathname, FOPEN_WRITE_TEXT);
+       (void) umask(um);
+#endif
+       if (fp == NULL)
+               return (-1);
+
+       if (fprintf(fp, "# This is a NcFTP spool file entry.\n# Run the \"ncftpbatch\" program to process the spool directory.\n#\n") < 0)
+               goto err;
+       if (fprintf(fp, "op=%s\n", op) < 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, "anon-pass=%s\n", gLib.defaultAnonPassword) < 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 ((delete != 0) && (fprintf(fp, "delete=%s\n", YESNO(delete)) < 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;
+       } 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 ((precmd != NULL) && (precmd[0] != '\0') && (fprintf(fp, "pre-command=%s\n", precmd) < 0))
+               goto err;
+       if ((perfilecmd != NULL) && (perfilecmd[0] != '\0') && (fprintf(fp, "per-file-command=%s\n", perfilecmd) < 0))
+               goto err;
+       if ((postcmd != NULL) && (postcmd[0] != '\0') && (fprintf(fp, "post-command=%s\n", postcmd) < 0))
+               goto err;
+
+       if (fclose(fp) < 0)
+               goto err2;
+
+       /* Move the spool file into its "live" name. */
+       if (rename(spathname, spathname2) < 0) {
+               perror("rename spoolfile failed");
+               goto err3;
+       }
+       gUnprocessedJobs++;
+       return (0);
+
+err:
+       (void) fclose(fp);
+err2:
+       perror("write to spool file failed");
+err3:
+       (void) unlink(spathname);
+       return (-1);
+}
+
+
+
+#if defined(WIN32) || defined(_WINDOWS)
+#else
+static int
+PWrite(int sfd, const char *const buf0, size_t size)
+{
+       int nleft;
+       const char *buf = buf0;
+       int nwrote;
+
+       nleft = (int) size;
+       for (;;) {
+               nwrote = (int) write(sfd, buf, nleft);
+               if (nwrote < 0) {
+                       if (errno != EINTR) {
+                               nwrote = (int) size - nleft;
+                               if (nwrote == 0)
+                                       nwrote = -1;
+                               return (nwrote);
+                       } else {
+                               errno = 0;
+                               nwrote = 0;
+                               /* Try again. */
+                       }
+               }
+               nleft -= nwrote;
+               if (nleft <= 0)
+                       break;
+               buf += nwrote;
+       }
+       nwrote = (int) size - nleft;
+       return (nwrote);
+}      /* PWrite */
+#endif
+
+
+
+void
+Jobs(void)
+{
+#if defined(WIN32) || defined(_WINDOWS)
+       assert(0); // Not supported
+#else
+       char *argv[8];
+       pid_t pid;
+#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] = (char *) "ncftpbatch";
+               argv[1] = (char *) "-l";
+               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);
+       } else {
+#ifdef HAVE_WAITPID
+               (void) waitpid(pid, NULL, 0);
+#else
+               (void) wait(NULL);
+#endif
+       }
+#endif
+}      /* Jobs */
+
+
+
+
+void
+RunBatch(int Xstruct, const FTPCIPtr cip)
+{
+#if defined(WIN32) || defined(_WINDOWS)
+       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
+       int pfd[2];
+       char pfdstr[32];
+       char *argv[8];
+       pid_t pid = 0;
+#ifdef BINDIR
+       char ncftpbatch[256];
+
+       STRNCPY(ncftpbatch, BINDIR);
+       STRNCAT(ncftpbatch, "/");
+       STRNCAT(ncftpbatch, "ncftpbatch");
+#endif /* BINDIR */
+
+       if (Xstruct != 0) {
+               if (pipe(pfd) < 0) {
+                       perror("pipe");
+               }
+
+               (void) sprintf(pfdstr, "%d", pfd[0]);
+               pid = fork();
+               if (pid < 0) {
+                       (void) close(pfd[0]);
+                       (void) close(pfd[1]);
+                       perror("fork");
+               } else if (pid == 0) {
+                       (void) close(pfd[1]);   /* Child closes write end. */
+                       argv[0] = (char *) "ncftpbatch";
+#ifdef DEBUG_NCFTPBATCH
+                       argv[1] = (char *) "-SD";
+#else
+                       argv[1] = (char *) "-d";
+#endif
+                       argv[2] = (char *) "-|";
+                       argv[3] = pfdstr;
+                       argv[4] = 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);
+               }
+               (void) close(pfd[0]);   /* Parent closes read end. */
+               (void) PWrite(pfd[1], (const char *) cip->lip, sizeof(FTPLibraryInfo));
+               (void) PWrite(pfd[1], (const char *) cip, sizeof(FTPConnectionInfo));
+               (void) close(pfd[1]);   /* Parent closes read end. */
+
+               /* Close it now, or else this process would send
+                * the server a QUIT message.  This will cause it
+                * to think it already has.
+                */
+               CloseControlConnection(cip);
+       } else {
+               pid = fork();
+               if (pid < 0) {
+                       perror("fork");
+               } else if (pid == 0) {
+                       argv[0] = (char *) "ncftpbatch";
+                       argv[1] = (char *) "-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
+       }
+#endif
+}      /* RunBatch */
+
+
+
+void
+RunBatchIfNeeded(const FTPCIPtr cip)
+{
+       if (gUnprocessedJobs > 0) {
+#ifdef ncftp
+               Trace(0, "Running ncftp_batch for %d job%s.\n", gUnprocessedJobs, gUnprocessedJobs > 0 ? "s" : "");
+               gUnprocessedJobs = 0;
+               RunBatch(1, cip);
+#else
+               gUnprocessedJobs = 0;
+               RunBatch(0, cip);
+#endif
+       }
+}      /* RunBatchIfNeeded */
+
+#endif /* HAVE_LONG_FILE_NAMES */