diff options
Diffstat (limited to 'src/pwgui/main.cpp')
-rw-r--r-- | src/pwgui/main.cpp | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/src/pwgui/main.cpp b/src/pwgui/main.cpp new file mode 100644 index 0000000..d75f280 --- /dev/null +++ b/src/pwgui/main.cpp @@ -0,0 +1,135 @@ +#include "pwgui.h" +#include "config.h" +#include <QApplication> +#include <cups/backend.h> +#include <fcntl.h> +#include <sys/stat.h> +#include <time.h> +#include <stdio.h> +#include <stdlib.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <unistd.h> + +#define NAMELEN 400 +#define BUFLEN 1000 + +static int run_backend(char *backend, char *uri, char *jobid, char *user, char *title, char *copies, char *options, char *file, char *password); + +int main(int argc, char *argv[]) +{ + char tmpfile[NAMELEN]; + char device[NAMELEN]; + char backend[NAMELEN]; + int spoolres; + + // Pretty much what smbspool does, but in a generalized way + if (argc > 2 && strstr(argv[0], ":/") == NULL && strstr(argv[1], ":/") != NULL) { + argv++; + argc--; + } + + // First check parameter count + if (argc != 6 && argc != 7) { + fputs("ERROR: Invalid number of arguments passed.\n", stderr); + return CUPS_BACKEND_FAILED; + } + + if (argc == 6) { + // Data comes from stdin, save... + snprintf(tmpfile, NAMELEN, "/tmp/print-%s-%d-%s-%d", argv[1], (int)time(NULL), argv[2], (int)getpid()); + int fh = open(tmpfile, O_CREAT | O_WRONLY | O_TRUNC, 0600); + if (fh < 0) { + fprintf(stderr, "ERROR: Could not open %s for writing..\n", tmpfile); + return CUPS_BACKEND_FAILED; + } + char buffer[BUFLEN]; + size_t bytes, ret; + while (!feof(stdin)) { + bytes = fread(buffer, BUFLEN, 1, stdin); + if (bytes == 0) break; + if ((ret = write(fh, buffer, bytes)) != bytes) { + fprintf(stderr, "ERROR: Could not write %d bytes to %s (wrote %d)\n", (int)bytes, tmpfile, (int)ret); + remove(tmpfile); + return CUPS_BACKEND_FAILED; + } + } + close(fh); + // + } else { + // File given, check if file exists + snprintf(tmpfile, NAMELEN, "%s", argv[6]); + int fh = open(tmpfile, O_RDONLY); + if (fh < 0) { + fprintf(stderr, "ERROR: Could not open %s for reading..\n", tmpfile); + return CUPS_BACKEND_FAILED; + } + close(fh); + // + } + + // Determine device uri + char *env = getenv("DEVICE_URI"); + if (env != NULL && strchr(env, ':') != NULL) { + snprintf(device, NAMELEN, "%s", env); + } else if (strstr(argv[0], ":/") != NULL) { + snprintf(device, NAMELEN, "%s", argv[0]); + } else { + fputs("ERROR: No device URI given.\n", stderr); + return CUPS_BACKEND_FAILED; + } + + // Get backend from uri + char *colon = strchr(device, ':'); + *colon = '\0'; + snprintf(backend, NAMELEN, "%s/%s", BACKEND_PATH, device); + *colon = ':'; + // Is valid? + if (access(backend, X_OK | R_OK) != 0) { + fprintf(stderr, "ERROR: Backend %s is not executable.\n", backend); + return CUPS_BACKEND_FAILED; + } + + // Try right away with what we got + spoolres = run_backend(backend, device, argv[1], argv[2], argv[3], argv[4], argv[5], tmpfile, NULL); + if (spoolres == CUPS_BACKEND_OK) return spoolres; // Yay + + // Dialog - TODO: Drop privileges here! + QApplication a(argc, argv); + PwGui w(NULL); + w.show(); + return a.exec(); + // TODO ..... +} + +static int run_backend(char *backend, char *uri, char *jobid, char *user, char *title, char *copies, char *options, char *file, char *password) +{ + pid_t pid = fork(); + if (pid == 0) { + // Child + if (user != NULL) setenv("AUTH_USERNAME", user, 1); + if (password != NULL) setenv("AUTH_PASSWORD", password, 1); + char *args[8]; + args[0] = uri; + args[1] = jobid; + args[2] = user; + args[3] = title; + args[4] = copies; + args[5] = options; + args[6] = file; + args[7] = NULL; + execv(backend, args); + exit(127); + return 127; + } + + // Main - wait for it... + int status; + waitpid(pid, &status, 0); + if (!WIFEXITED(status)) { + fprintf(stderr, "ERROR: Running backend %s failed!\n", backend); + return CUPS_BACKEND_FAILED; + } + return WEXITSTATUS(status); +} + |