Blob Blame Raw
diff -up cups-1.7.5/conf/cups-files.conf.in.journal cups-1.7.5/conf/cups-files.conf.in
--- cups-1.7.5/conf/cups-files.conf.in.journal	2013-07-26 22:27:27.000000000 +0100
+++ cups-1.7.5/conf/cups-files.conf.in	2014-11-05 17:57:42.011621332 +0000
@@ -30,9 +30,10 @@ SystemGroup @CUPS_SYSTEM_GROUPS@
 #ConfigFilePerm 0@CUPS_CONFIG_FILE_PERM@
 #LogFilePerm 0@CUPS_LOG_FILE_PERM@
 
-# Location of the file logging all access to the scheduler; may be the name
-# "syslog". If not an absolute path, the value of ServerRoot is used as the
-# root directory.  Also see the "AccessLogLevel" directive in cupsd.conf.
+# Location of the file logging all access to the scheduler; may be the
+# name "syslog" or "journal". If not an absolute path, the value of
+# ServerRoot is used as the root directory.  Also see the
+# "AccessLogLevel" directive in cupsd.conf.
 AccessLog @CUPS_LOGDIR@/access_log
 
 # Location of cache files used by the scheduler...
@@ -44,11 +45,11 @@ AccessLog @CUPS_LOGDIR@/access_log
 # Location of the static web content served by the scheduler...
 #DocumentRoot @CUPS_DOCROOT@
 
-# Location of the file logging all messages produced by the scheduler and any
-# helper programs; may be the name "syslog". If not an absolute path, the value
-# of ServerRoot is used as the root directory.  Also see the "LogLevel"
-# directive in cupsd.conf.
-ErrorLog @CUPS_LOGDIR@/error_log
+# Location of the file logging all messages produced by the scheduler
+# and any helper programs; may be the name "syslog" or "journal". If
+# not an absolute path, the value of ServerRoot is used as the root
+# directory.  Also see the "LogLevel" # directive in cupsd.conf.
+ErrorLog journal
 
 # Location of fonts used by older print filters...
 #FontPath @CUPS_FONTPATH@
@@ -56,10 +57,10 @@ ErrorLog @CUPS_LOGDIR@/error_log
 # Location of LPD configuration
 #LPDConfigFile @CUPS_DEFAULT_LPD_CONFIG_FILE@
 
-# Location of the file logging all pages printed by the scheduler and any
-# helper programs; may be the name "syslog". If not an absolute path, the value
-# of ServerRoot is used as the root directory.  Also see the "PageLogFormat"
-# directive in cupsd.conf.
+# Location of the file logging all pages printed by the scheduler and
+# any helper programs; may be the name "syslog" or "journal". If not
+# an absolute path, the value of ServerRoot is used as the root
+# directory.  Also see the "PageLogFormat" directive in cupsd.conf.
 PageLog @CUPS_LOGDIR@/page_log
 
 # Location of the file listing all of the local printers...
diff -up cups-1.7.5/doc/help/ref-cups-files-conf.html.in.journal cups-1.7.5/doc/help/ref-cups-files-conf.html.in
--- cups-1.7.5/doc/help/ref-cups-files-conf.html.in.journal	2013-07-26 22:27:27.000000000 +0100
+++ cups-1.7.5/doc/help/ref-cups-files-conf.html.in	2014-11-05 17:57:42.012621337 +0000
@@ -18,6 +18,7 @@
 AccessLog /var/log/cups/access_log
 AccessLog /var/log/cups/access_log-%s
 AccessLog syslog
+AccessLog journal
 </PRE>
 
 <H3>Description</H3>
@@ -36,6 +37,9 @@ server activity.</P>
 <P>The special name "syslog" can be used to send the access
 information to the system log instead of a plain file.</P>
 
+<P>The special name "journal" can be used to send the access
+information to the systemd journal instead of a plain file.</P>
+
 <P>The default access log file is
 <VAR>/var/log/access_log</VAR>.</P>
 
@@ -108,6 +112,7 @@ language needed.</P>
 ErrorLog /var/log/cups/error_log
 ErrorLog /var/log/cups/error_log-%s
 ErrorLog syslog
+ErrorLog journal
 </PRE>
 
 <H3>Description</H3>
@@ -124,6 +129,11 @@ default error log file is <VAR>/var/log/
 <P>The special name "syslog" can be used to send the error
 information to the system log instead of a plain file.</P>
 
+<P>The special name "journal" can be used to send the error
+information to the systemd journal instead of a plain file. Information
+relating to a specific job is logged with the field
+<CODE>CUPS_JOB_ID</CODE> filled in.</P>
+
 
 <H2 CLASS="title"><SPAN CLASS="info">CUPS 1.4/OS X 10.6</SPAN><A NAME="FatalErrors">FatalErrors</A></H2>
 
@@ -266,6 +276,7 @@ is 644.</P>
 PageLog /var/log/cups/page_log
 PageLog /var/log/cups/page_log-%s
 PageLog syslog
+PageLog journal
 </PRE>
 
 <H3>Description</H3>
@@ -282,6 +293,11 @@ default page log file is <VAR>/var/log/c
 <P>The special name "syslog" can be used to send the page
 information to the system log instead of a plain file.</P>
 
+<P>The special name "journal" can be used to send the page information
+to the system journal instead of a plain file.  The fields
+<CODE>CUPS_JOB_ID</CODE> and <CODE>CUPS_PAGE_NUMBER</CODE> will be
+filled in.</P>
+
 
 <H2 CLASS="title"><A NAME="Printcap">Printcap</A></H2>
 
diff -up cups-1.7.5/man/cups-files.conf.man.in.journal cups-1.7.5/man/cups-files.conf.man.in
--- cups-1.7.5/man/cups-files.conf.man.in.journal	2013-07-26 22:27:27.000000000 +0100
+++ cups-1.7.5/man/cups-files.conf.man.in	2014-11-05 17:57:42.013621342 +0000
@@ -29,6 +29,8 @@ on-line help for detailed descriptions:
 AccessLog filename
 .TP 5
 AccessLog syslog
+.TP 5
+AccessLog journal
 .br
 Defines the access log filename.
 .TP 5
@@ -48,6 +50,8 @@ Specifies the root directory for the int
 ErrorLog filename
 .TP 5
 ErrorLog syslog
+.TP 5
+ErrorLog journal
 .br
 Specifies the error log filename.
 .TP 5
@@ -83,6 +87,8 @@ Specifies the permissions for all log fi
 PageLog filename
 .TP 5
 PageLog syslog
+.TP 5
+PageLog journal
 .br
 Specifies the page log filename.
 .TP 5
diff -up cups-1.7.5/scheduler/conf.c.journal cups-1.7.5/scheduler/conf.c
--- cups-1.7.5/scheduler/conf.c.journal	2014-11-05 17:57:41.938620961 +0000
+++ cups-1.7.5/scheduler/conf.c	2014-11-05 17:57:42.013621342 +0000
@@ -950,9 +950,9 @@ cupsdReadConfiguration(void)
   */
 
 #ifdef HAVE_VSYSLOG
-  if (!strcmp(AccessLog, "syslog") ||
-      !strcmp(ErrorLog, "syslog") ||
-      !strcmp(PageLog, "syslog"))
+  if (!strcmp(AccessLog, "syslog") || !strcmp(AccessLog, "journal") ||
+      !strcmp(ErrorLog, "syslog") || !strcmp(ErrorLog, "journal") ||
+      !strcmp(PageLog, "syslog") || !strcmp(PageLog, "journal"))
     openlog("cupsd", LOG_PID | LOG_NOWAIT | LOG_NDELAY, LOG_LPR);
 #endif /* HAVE_VSYSLOG */
 
@@ -960,13 +960,13 @@ cupsdReadConfiguration(void)
   * Make sure each of the log files exists and gets rotated as necessary...
   */
 
-  if (strcmp(AccessLog, "syslog"))
+  if (strcmp(AccessLog, "syslog") && strcmp(AccessLog, "journal"))
     cupsdCheckLogFile(&AccessFile, AccessLog);
 
-  if (strcmp(ErrorLog, "syslog"))
+  if (strcmp(ErrorLog, "syslog") && strcmp(ErrorLog, "journal"))
     cupsdCheckLogFile(&ErrorFile, ErrorLog);
 
-  if (strcmp(PageLog, "syslog"))
+  if (strcmp(PageLog, "syslog") && strcmp(PageLog, "journal"))
     cupsdCheckLogFile(&PageFile, PageLog);
 
  /*
diff -up cups-1.7.5/scheduler/conf.h.journal cups-1.7.5/scheduler/conf.h
--- cups-1.7.5/scheduler/conf.h.journal	2014-11-05 17:57:41.938620961 +0000
+++ cups-1.7.5/scheduler/conf.h	2014-11-05 17:57:42.014621347 +0000
@@ -290,16 +290,69 @@ extern int	cupsdLogGSSMessage(int level,
 		                   int minor_status,
 		                   const char *message, ...);
 #endif /* HAVE_GSSAPI */
-extern int	cupsdLogJob(cupsd_job_t *job, int level, const char *message,
-		            ...) __attribute__((__format__(__printf__, 3, 4)));
-extern int	cupsdLogMessage(int level, const char *message, ...)
-		__attribute__ ((__format__ (__printf__, 2, 3)));
+extern int	_cupsdLogJobWithLocation(const char *file,
+					 const char *line,
+					 const char *func,
+					 cupsd_job_t *job,
+					 int level,
+					 const char *message,
+					 ...)
+		__attribute__((__format__(__printf__, 6, 7)));
+extern int	_cupsdLogMessageWithLocation(const char *file,
+					     const char *line,
+					     const char *func,
+					     int level,
+					     const char *message,
+					     ...)
+		__attribute__ ((__format__ (__printf__, 5, 6)));
 extern int	cupsdLogPage(cupsd_job_t *job, const char *page);
 extern int	cupsdLogRequest(cupsd_client_t *con, http_status_t code);
 extern int	cupsdReadConfiguration(void);
-extern int	cupsdWriteErrorLog(int level, const char *message);
+extern int	_cupsdWriteErrorLogJobWithLocation(const char *file,
+						   const char *line,
+						   const char *func,
+						   cupsd_job_t *job,
+						   int level,
+						   const char *message);
+extern int	_cupsdWriteErrorLogWithLocation(const char *file,
+						const char *line,
+						const char *func,
+						int level, const char *message);
 
 
+#ifndef _CUPSD_STRINGIFY
+#define _CUPSD_XSTRINGIFY(x) #x
+#define _CUPSD_STRINGIFY(x) _CUPSD_XSTRINGIFY(x)
+#endif /* !defined(_CUPSD_STRINGIFY) */
+
+#define cupsdLogJob(...)						\
+	_cupsdLogJobWithLocation("CODE_FILE=" __FILE__,			\
+				 "CODE_LINE="				\
+				 _CUPSD_STRINGIFY(__LINE__),		\
+				 __func__,				\
+				 __VA_ARGS__)
+
+#define cupsdLogMessage(...)						\
+	_cupsdLogMessageWithLocation("CODE_FILE=" __FILE__,		\
+				     "CODE_LINE="			\
+				     _CUPSD_STRINGIFY(__LINE__),	\
+				     __func__,				\
+				     __VA_ARGS__)
+
+#define cupsdWriteErrorLogJob(...)					\
+	_cupsdWriteErrorLogJobWithLocation("CODE_FILE=" __FILE__,	\
+			       "CODE_LINE="				\
+			       _CUPSD_STRINGIFY(__LINE__),		\
+			       __func__,				\
+			       __VA_ARGS__)
+
+#define cupsdWriteErrorLog(...)					\
+	_cupsdWriteErrorLogWithLocation("CODE_FILE=" __FILE__,	\
+			    "CODE_LINE="			\
+			    _CUPSD_STRINGIFY(__LINE__),		\
+			    __func__,				\
+			    __VA_ARGS__)
+
 /*
  * End of "$Id: conf.h 11202 2013-07-26 21:31:54Z msweet $".
  */
diff -up cups-1.7.5/scheduler/log.c.journal cups-1.7.5/scheduler/log.c
--- cups-1.7.5/scheduler/log.c.journal	2014-11-05 17:57:41.967621108 +0000
+++ cups-1.7.5/scheduler/log.c	2014-11-05 17:58:18.297805575 +0000
@@ -17,10 +17,11 @@
  *   cupsdCheckLogFile()     - Open/rotate a log file if it needs it.
  *   cupsdGetDateTime()   - Returns a pointer to a date/time string.
  *   cupsdLogGSSMessage() - Log a GSSAPI error...
- *   cupsdLogJob()        - Log a job message.
+ *   _cupsdLogJobWithLocation() - Log a job message.
  *   cupsdLogMessage()    - Log a message to the error log file.
  *   cupsdLogPage()       - Log a page to the page log file.
  *   cupsdLogRequest()    - Log an HTTP request in Common Log Format.
+ *   cupsdWriteErrorLogJob() - Write a job message to the ErrorLog.
  *   cupsdWriteErrorLog() - Write a line to the ErrorLog.
  *   format_log_line()    - Format a line for a log file.
  */
@@ -34,7 +35,13 @@
 #include <syslog.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <sys/uio.h>
 #include <unistd.h>
+#ifdef HAVE_SYSTEMD
+/* We handle location fields ourselves */
+# define SD_JOURNAL_SUPPRESS_LOCATION
+# include <systemd/sd-journal.h>
+#endif /* HAVE_SYSTEMD */
 
 
 /*
@@ -465,21 +472,140 @@ cupsdLogGSSMessage(
 #endif /* HAVE_GSSAPI */
 
 
+#ifdef HAVE_SYSTEMD
+static int
+dup_iovec_string(struct iovec *vec,
+		 const char *str)
+{
+  vec->iov_base = strdup (str);
+  vec->iov_len = strlen (str);
+  return (vec->iov_base ? 1 : 0);
+}
+
+
+/*
+ * '_cupsdLogToJournal()' - Log to journal with fields
+ */
+static int				/* O - 1 on success, 0 on error */
+_cupsdLogToJournal(const char	*file,	/* I - Code file */
+		   const char	*line,	/* I - Code line */
+		   const char	*func,	/* I - Code func */
+		   cupsd_job_t	*job,	/* I - Job or NULL */
+		   int		level,	/* I - Log level */
+		   const char	*message)/* I - Formatted message */
+{
+  size_t		n_journal_fields;
+  struct iovec		*journal_fields = NULL;
+  char			buffer[256];
+  int			result = 1;
+
+ /*
+  * There will be at least 5 fields:
+  * CODE_FILE, CODE_LINE, CODE_FUNC, MESSAGE, PRIORITY
+  */
+
+  n_journal_fields = 5;
+
+  if (job)
+  {
+    n_journal_fields++; /* CUPS_JOB_ID */
+
+    if (job->dest)
+      n_journal_fields++; /* CUPS_DEST */
+
+    if (job->printer)
+      n_journal_fields++; /* CUPS_PRINTER */
+  }
+
+  journal_fields = calloc (n_journal_fields, sizeof (struct iovec));
+  if (!journal_fields)
+    return (0);
+
+  n_journal_fields = 0;
+
+  result = dup_iovec_string (&journal_fields[n_journal_fields], file);
+
+  if (result)
+  {
+    n_journal_fields++;
+    result = dup_iovec_string (&journal_fields[n_journal_fields], line);
+  }
+
+  if (result)
+  {
+    n_journal_fields++;
+    snprintf (buffer, sizeof (buffer), "CODE_FUNC=%s", func);
+    result = dup_iovec_string (&journal_fields[n_journal_fields], buffer);
+  }
+
+  if (result)
+  {
+    n_journal_fields++;
+    snprintf (buffer, sizeof (buffer), "MESSAGE=%s", log_line);
+    result = dup_iovec_string (&journal_fields[n_journal_fields], buffer);
+  }
+
+  if (result)
+  {
+    n_journal_fields++;
+    snprintf (buffer, sizeof (buffer), "PRIORITY=%i", syslevels[level]);
+    result = dup_iovec_string (&journal_fields[n_journal_fields], buffer);
+  }
+
+  if (result && job)
+  {
+    n_journal_fields++;
+    snprintf (buffer, sizeof (buffer), "CUPS_JOB_ID=%d", job->id);
+    result = dup_iovec_string (&journal_fields[n_journal_fields], buffer);
+
+    if (result && job->dest)
+    {
+      n_journal_fields++;
+      snprintf (buffer, sizeof (buffer), "CUPS_DEST=%s", job->dest);
+      result = dup_iovec_string (&journal_fields[n_journal_fields], buffer);
+    }
+
+    if (result && job->printer)
+    {
+      n_journal_fields++;
+      snprintf (buffer, sizeof (buffer), "CUPS_PRINTER=%s",
+		job->printer->name);
+      result = dup_iovec_string (&journal_fields[n_journal_fields], buffer);
+    }
+  }
+
+  if (result)
+  {
+    n_journal_fields++;
+    result = sd_journal_sendv (journal_fields, n_journal_fields);
+  }
+
+  while (n_journal_fields > 0)
+    free (journal_fields[--n_journal_fields].iov_base);
+
+  free (journal_fields);
+  return (result);
+}
+#endif /* HAVE_SYSTEMD */
+
+
 /*
  * 'cupsdLogJob()' - Log a job message.
  */
 
-int					/* O - 1 on success, 0 on error */
-cupsdLogJob(cupsd_job_t *job,		/* I - Job */
-            int         level,		/* I - Log level */
-	    const char  *message,	/* I - Printf-style message string */
-	    ...)			/* I - Additional arguments as needed */
+int						/* O - 1 on success, 0 on error */
+_cupsdLogJobWithLocation(const char *file,	/* I - Code file */
+			 const char *line,	/* I - Code line */
+			 const char *func,	/* I - Code func */
+			 cupsd_job_t *job,	/* I - Job */
+			 int         level,	/* I - Log level */
+			 const char  *message,	/* I - Printf-style message string */
+			 ...)			/* I - Additional arguments as needed */
 {
   va_list		ap, ap2;	/* Argument pointers */
   char			jobmsg[1024];	/* Format string for job message */
   int			status;		/* Formatting status */
 
-
  /*
   * See if we want to log this message...
   */
@@ -559,8 +685,14 @@ cupsdLogJob(cupsd_job_t *job,		/* I - Jo
     }
     else if (level <= LogLevel &&
              (level != CUPSD_LOG_INFO || LogLevel >= CUPSD_LOG_DEBUG))
-      return (cupsdWriteErrorLog(level, log_line));
-    else
+    {
+#ifdef HAVE_SYSTEMD
+      if (!strcmp (ErrorLog, "journal"))
+	return (_cupsdLogToJournal (file, line, func, job, level, log_line));
+      else
+#endif /* HAVE_SYSTEMD */
+	return (cupsdWriteErrorLog(level, log_line));
+    } else
       return (1);
   }
   else
@@ -573,10 +705,13 @@ cupsdLogJob(cupsd_job_t *job,		/* I - Jo
  * 'cupsdLogMessage()' - Log a message to the error log file.
  */
 
-int					/* O - 1 on success, 0 on error */
-cupsdLogMessage(int        level,	/* I - Log level */
-                const char *message,	/* I - printf-style message string */
-	        ...)			/* I - Additional args as needed */
+int						/* O - 1 on success, 0 on error */
+_cupsdLogMessageWithLocation(const char *file,	/* I - Code file */
+			     const char *line,	/* I - Code line */
+			     const char *func,	/* I - Code func */
+			     int        level,	/* I - Log level */
+			     const char *message, /* I - printf-style message string */
+			     ...)		/* I - Additional args as needed */
 {
   va_list		ap, ap2;	/* Argument pointers */
   int			status;		/* Formatting status */
@@ -620,10 +755,10 @@ cupsdLogMessage(int        level,	/* I -
   va_end(ap);
 
   if (status > 0)
-    return (cupsdWriteErrorLog(level, log_line));
+    return (_cupsdWriteErrorLogWithLocation(file, line, func, level, log_line));
   else
-    return (cupsdWriteErrorLog(CUPSD_LOG_ERROR,
-                               "Unable to allocate memory for log line!"));
+    return (_cupsdWriteErrorLogWithLocation(file, line, func, CUPSD_LOG_ERROR,
+					    "Unable to allocate memory for log line!"));
 }
 
 
@@ -789,6 +924,17 @@ cupsdLogPage(cupsd_job_t *job,		/* I - J
 
   *bufptr = '\0';
 
+#ifdef HAVE_SYSTEMD
+  if (!strcmp(PageLog, "journal"))
+    return (sd_journal_send ("MESSAGE=%s", buffer,
+			     "PRIORITY=%d", LOG_INFO,
+			     "CUPS_JOB_ID=%d", job->id,
+			     "CUPS_DEST=%s", job->dest,
+			     "CUPS_PRINTER=%s", job->printer->name,
+			     "CUPS_PAGE_NUMBER=%s", number,
+			     NULL) ? 0 : 1);
+#endif /* HAVE_SYSTEMD */
+
 #ifdef HAVE_VSYSLOG
  /*
   * See if we are logging pages via syslog...
@@ -964,7 +1110,7 @@ cupsdLogRequest(cupsd_client_t *con,	/*
   * See if we are logging accesses via syslog...
   */
 
-  if (!strcmp(AccessLog, "syslog"))
+  if (!strcmp(AccessLog, "syslog") || !strcmp(AccessLog, "journal"))
   {
     syslog(LOG_INFO,
            "REQUEST %s - %s \"%s %s HTTP/%d.%d\" %d " CUPS_LLFMT " %s %s\n",
@@ -1018,8 +1164,12 @@ cupsdLogRequest(cupsd_client_t *con,	/*
  */
 
 int					/* O - 1 on success, 0 on failure */
-cupsdWriteErrorLog(int        level,	/* I - Log level */
-                   const char *message)	/* I - Message string */
+_cupsdWriteErrorLogJobWithLocation(const char *file,	/* I - Code file */
+				   const char *line,	/* I - Code line */
+				   const char *func,	/* I - Code func */
+				   cupsd_job_t *job,	/* I - Job or NULL */
+				   int         level,	/* I - Log level */
+				   const char *message) /* I - Message string */
 {
   static const char	levels[] =	/* Log levels... */
 		{
@@ -1036,6 +1186,10 @@ cupsdWriteErrorLog(int        level,	/*
 		};
 
 
+#ifdef HAVE_SYSTEMD
+  if (!strcmp(ErrorLog, "journal"))
+    return (_cupsdLogToJournal (file, line, func, job, level, message));
+#endif /* HAVE_SYSTEMD */
 #ifdef HAVE_VSYSLOG
  /*
   * See if we are logging errors via syslog...
@@ -1067,6 +1221,22 @@ cupsdWriteErrorLog(int        level,	/*
 }
 
 
+/*
+ * 'cupsdWriteErrorLog()' - Write a line to the ErrorLog.
+ */
+
+int					/* O - 1 on success, 0 on failure */
+_cupsdWriteErrorLogWithLocation(const char *file,	/* I - Code file */
+				const char *line,	/* I - Code line */
+				const char *func,	/* I - Code func */
+				int          level,	/* I - Log level */
+				const char  *message)	/* I - Message string */
+{
+  return (_cupsdWriteErrorLogJobWithLocation(file, line, func,
+					     NULL, level, message));
+}
+
+
 /*
  * 'format_log_line()' - Format a line for a log file.
  *