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