summaryrefslogtreecommitdiffstats
path: root/src/pwgui/main.cpp
diff options
context:
space:
mode:
authorSimon Rettberg2014-02-25 16:08:37 +0100
committerSimon Rettberg2014-02-25 16:08:37 +0100
commit2e46cd015d4c3c1f6b9842bafd623a4ca60fc35b (patch)
tree04dfd30fdab88c3fbce1e050d9311d1cf9dbdb3e /src/pwgui/main.cpp
parentAdd auth support for iprint via ipp14 (diff)
downloadprintergui-2e46cd015d4c3c1f6b9842bafd623a4ca60fc35b.tar.gz
printergui-2e46cd015d4c3c1f6b9842bafd623a4ca60fc35b.tar.xz
printergui-2e46cd015d4c3c1f6b9842bafd623a4ca60fc35b.zip
[printpwgui] Show message boxes on error whereever possible
Diffstat (limited to 'src/pwgui/main.cpp')
-rw-r--r--src/pwgui/main.cpp89
1 files changed, 85 insertions, 4 deletions
diff --git a/src/pwgui/main.cpp b/src/pwgui/main.cpp
index dc14006..1f7ddab 100644
--- a/src/pwgui/main.cpp
+++ b/src/pwgui/main.cpp
@@ -1,6 +1,7 @@
#include "pwgui.h"
#include "config.h"
#include <QApplication>
+#include <QMessageBox>
#include <cups/backend.h>
#include <fcntl.h>
#include <sys/stat.h>
@@ -35,6 +36,8 @@ static bool helper_loadlpuser();
static void helper_dropprivs();
static void helper_copyenv();
static char *helper_urlencode(char *s, char *enc);
+static int helper_cupsError(const int code);
+static void helper_error(const char *caption, const char *text);
int main(int argc, char *argv[])
{
@@ -73,6 +76,8 @@ int main(int argc, char *argv[])
*colon = ':';
// Is valid?
if (access(backend, X_OK | R_OK) != 0) {
+ helper_getpiduid(argv[2], argv[3]);
+ helper_error("PrinterGUI", "Kein Backend für den gewählten Drucker vorhanden.");
fprintf(stderr, "ERROR: Backend %s is not executable.\n", backend);
return CUPS_BACKEND_FAILED;
}
@@ -96,6 +101,7 @@ int main(int argc, char *argv[])
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) {
+ helper_error("PrinterGUI", "Konnte temporäre Datei für den Druckjob nicht anlegen.");
fprintf(stderr, "ERROR: Could not open %s for writing..\n", tmpfile);
return CUPS_BACKEND_FAILED;
}
@@ -106,11 +112,13 @@ int main(int argc, char *argv[])
bytes = read(STDIN_FILENO, buffer, BUFLEN);
if (bytes == 0) break;
if (bytes < 0) {
+ helper_error("PrinterGUI", "Konnte den Druckjob nicht auf STDIN empfangen.");
fprintf(stderr, "ERROR: Could not read print job from STDIN.\n");
remove(tmpfile);
return CUPS_BACKEND_FAILED;
}
if ((ret = write(fh, buffer, bytes)) != bytes) {
+ helper_error("PrinterGUI", "Konnte Druckjob nicht in temporäre Datei schreiben.");
fprintf(stderr, "ERROR: Could not write %d bytes to %s (wrote %d)\n", (int)bytes, tmpfile, (int)ret);
remove(tmpfile);
return CUPS_BACKEND_FAILED;
@@ -125,6 +133,7 @@ int main(int argc, char *argv[])
snprintf(tmpfile, NAMELEN, "%s", argv[6]);
int fh = open(tmpfile, O_RDONLY);
if (fh < 0) {
+ helper_error("PrinterGUI", "Konnte den Druckjob nicht vom Dateisystem lesen.");
fprintf(stderr, "ERROR: Could not open %s for reading..\n", tmpfile);
return CUPS_BACKEND_FAILED;
}
@@ -135,7 +144,7 @@ int main(int argc, char *argv[])
// 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_AUTH_REQUIRED) return spoolres; // Yay
+ if (spoolres != CUPS_BACKEND_AUTH_REQUIRED) return helper_cupsError(spoolres); // Yay
// Seems we need the dialog
int status;
@@ -144,10 +153,11 @@ int main(int argc, char *argv[])
do {
int pfd[2];
if (pipe(pfd) != 0) {
+ helper_error("PrinterGUI", "Konnte pipe für die GUI nicht anlegen.");
fputs("ERROR: Could not create pipe for GUI.\n", stderr);
return CUPS_BACKEND_FAILED;
}
- pid_t pid = fork();
+ const pid_t pid = fork();
if (pid == 0) {
// Child - GUI
close(pfd[0]);
@@ -166,7 +176,8 @@ int main(int argc, char *argv[])
close(pfd[0]);
// Wait for child to die
waitpid(pid, NULL, 0); // Don't check status, just look at pipe data
- if (bytes <= 0) {
+ if (bytes <= 0) { // Probably means user pressed cancel
+ helper_error("PrinterGUI", "Druckauftrag abgebrochen.");
fputs("ERROR: Could not read anything from pipe after showing GUI.\n", stderr);
remove(tmpfile);
return CUPS_BACKEND_CANCEL;
@@ -176,6 +187,7 @@ int main(int argc, char *argv[])
if (len < bytes) pass = creds + len + 1;
// Run backend with pimped user/pass
status = run_backend(backend, device, argv[1], creds, argv[3], argv[4], argv[5], tmpfile, pass);
+ helper_cupsError(status);
} while (status != CUPS_BACKEND_OK);
remove(tmpfile);
fprintf(stderr, "ERROR: Job submitted.\n");
@@ -234,7 +246,7 @@ static int run_backend(char *backend, char *uri, char *jobid, char *user, char *
int readlen = 0;
while ((readlen = read(pipefd[0], buffer, BUFLEN-1)) > 0) {
buffer[readlen] = '\0';
- if (strstr(buffer, "Unable to get printer status (Unauthorized)!") != NULL) {
+ if (strstr(buffer, "Unable to get printer status (Unauthorized)") != NULL) {
needAuth = true;
if (kill(pid, SIGTERM) < 0) {
fprintf(stderr, "ERROR: Sending kill1 to backend %d failed: %d\n", (int)pid, errno);
@@ -389,3 +401,72 @@ static char *helper_urlencode(char *source, char *enc)
return enc;
}
+/**
+ * Show an error message according to the given cups return code (coming from the real backend)
+ * Return a suitable cups return code to pass back to cups. This will be "hold job" in most
+ * cases, so the job will still be visible in cups for debugging.
+ */
+static int helper_cupsError(const int code)
+{
+ switch (code) {
+ case CUPS_BACKEND_OK:
+ return CUPS_BACKEND_OK;
+
+ case CUPS_BACKEND_FAILED:
+ // The print file was not successfully transmitted to the device or remote server. The scheduler will respond to this by canceling the job, retrying the job, or stopping the queue depending on the state of the error-policy attribute.
+ helper_error("CUPS Fehler", "Fehler beim lokalen Verarbeiten des Druckauftrags");
+ return CUPS_BACKEND_HOLD;
+
+ case CUPS_BACKEND_AUTH_REQUIRED:
+ // The print file was not successfully transmitted because valid authentication information is required. The scheduler will respond to this by holding the job and adding the "cups-held-for-authentication" keyword to the "job-reasons" attribute.
+ helper_error("CUPS Fehler", "Authentifizierung am Druckserver/Drucker fehlgeschlagen");
+ break;
+
+ case CUPS_BACKEND_HOLD:
+ // The print file was not successfully transmitted because it cannot be printed at this time. The scheduler will respond to this by holding the job.
+ helper_error("CUPS Fehler", "Der Drucker hat die Annahme des Druckauftrags verweigert (3)");
+ break;
+
+ case CUPS_BACKEND_STOP:
+ // The print file was not successfully transmitted because it cannot be printed at this time. The scheduler will respond to this by stopping the queue.
+ helper_error("CUPS Fehler", "Der Drucker hat die Annahme des Druckauftrags verweigert (4)");
+ return CUPS_BACKEND_HOLD;
+
+ case CUPS_BACKEND_CANCEL:
+ // The print file was not successfully transmitted because one or more attributes are not supported or the job was canceled at the printer. The scheduler will respond to this by canceling the job.
+ helper_error("CUPS Fehler", "Fehler 5 beim lokalen Verarbeiten des Druckauftrags");
+ return CUPS_BACKEND_HOLD;
+
+ case CUPS_BACKEND_RETRY:
+ // The print file was not successfully transmitted because of a temporary issue. The scheduler will retry the job at a future time - other jobs may print before this one.
+ helper_error("CUPS Fehler", "Fehler 6 beim lokalen Verarbeiten des Druckauftrags");
+ return CUPS_BACKEND_HOLD;
+
+ case CUPS_BACKEND_RETRY_CURRENT:
+ // The print file was not successfully transmitted because of a temporary issue. The scheduler will retry the job immediately without allowing intervening jobs.
+ helper_error("CUPS Fehler", "Fehler 7 beim lokalen Verarbeiten des Druckauftrags");
+ return CUPS_BACKEND_HOLD;
+ }
+ return code;
+}
+
+static void helper_error(const char *caption, const char *text)
+{
+ const pid_t pid = fork();
+ if (pid == 0) {
+ // Child - Qt
+ char *argv[1];
+ argv[1] = (char*)"bla";
+ int argc;
+ helper_dropprivs();
+ helper_copyenv();
+ QApplication a(argc, argv);
+ QMessageBox::critical(NULL, QString::fromUtf8(caption), QString::fromUtf8(text));
+ exit(a.exec());
+ return;
+ }
+ // Main (Parent)
+ // Wait for child to die
+ waitpid(pid, NULL, 0);
+}
+