summaryrefslogblamecommitdiffstats
path: root/src/pwgui/main.cpp
blob: d75f2809f76739076a3aa4913b7428fc95f20900 (plain) (tree)






































































































































                                                                                                                                                
#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);
}