]> git.ipfire.org Git - thirdparty/cups.git/blobdiff - scheduler/log.c
Merge changes from CUPS 1.4svn-r7961.
[thirdparty/cups.git] / scheduler / log.c
index 4a21b0856bac03e0a58006d409f71e7aa306de8a..19cb0cc86711388a328348e0fe248c4940d8aabe 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: log.c 6875 2007-08-27 23:25:06Z mike $"
+ * "$Id: log.c 7918 2008-09-08 22:03:01Z mike $"
  *
  *   Log file routines for the Common UNIX Printing System (CUPS).
  *
  *
  *   cupsdGetDateTime()   - Returns a pointer to a date/time string.
  *   cupsdLogGSSMessage() - Log a GSSAPI error...
+ *   cupsdLogJob()        - 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.
+ *   cupsdWriteErrorLog() - Write a line to the ErrorLog.
  *   check_log_file()     - Open/rotate a log file if it needs it.
+ *   format_log_line()    - Format a line for a log file.
  */
 
 /*
 #include <syslog.h>
 
 
+/*
+ * Local globals...
+ */
+
+static int     log_linesize = 0;       /* Size of line for output file */
+static char    *log_line = NULL;       /* Line for output file */
+
+
 /*
  * Local functions...
  */
 
-static int     check_log_file(cups_file_t **, const char *);
+static int     check_log_file(cups_file_t **lf, const char *logname);
+static int     format_log_line(const char *message, va_list ap);
 
 
 /*
@@ -138,12 +150,8 @@ cupsdLogGSSMessage(
                                           &major_status_string);
 
   if (!GSS_ERROR(err_major_status))
-    err_major_status = gss_display_status(&err_minor_status,
-                                         minor_status,
-                                         GSS_C_MECH_CODE,
-                                         GSS_C_NULL_OID,
-                                         &msg_ctx,
-                                         &minor_status_string);
+    gss_display_status(&err_minor_status, minor_status, GSS_C_MECH_CODE,
+                       GSS_C_NULL_OID, &msg_ctx, &minor_status_string);
 
   ret = cupsdLogMessage(level, "%s: %s, %s", message,
                        (char *)major_status_string.value,
@@ -157,176 +165,99 @@ cupsdLogGSSMessage(
 
 
 /*
- * 'cupsdLogMessage()' - Log a message to the error log file.
+ * 'cupsdLogJob()' - Log a job message.
  */
 
 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 */
+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                  len;            /* Length of message */
   va_list              ap;             /* Argument pointer */
-  static const char    levels[] =      /* Log levels... */
-               {
-                 ' ',
-                 'X',
-                 'A',
-                 'C',
-                 'E',
-                 'W',
-                 'N',
-                 'I',
-                 'D',
-                 'd'
-               };
-#ifdef HAVE_VSYSLOG
-  static const int     syslevels[] =   /* SYSLOG levels... */
-               {
-                 0,
-                 LOG_EMERG,
-                 LOG_ALERT,
-                 LOG_CRIT,
-                 LOG_ERR,
-                 LOG_WARNING,
-                 LOG_NOTICE,
-                 LOG_INFO,
-                 LOG_DEBUG,
-                 LOG_DEBUG
-               };
-#endif /* HAVE_VSYSLOG */
-  static int           linesize = 0;   /* Size of line for output file */
-  static char          *line = NULL;   /* Line for output file */
+  char                 jobmsg[1024];   /* Format string for job message */
+  int                  status;         /* Formatting status */
 
 
  /*
   * See if we want to log this message...
   */
 
-  if (TestConfigFile)
-  {
-    if (level <= CUPSD_LOG_WARN)
-    {
-      va_start(ap, message);
-      vfprintf(stderr, message, ap);
-      putc('\n', stderr);
-      va_end(ap);
-    }
-
+  if (TestConfigFile || level > LogLevel || !ErrorLog)
     return (1);
-  }
 
-  if (level > LogLevel || !ErrorLog)
-    return (1);
-
-#ifdef HAVE_VSYSLOG
  /*
-  * See if we are logging errors via syslog...
+  * Format and write the log message...
   */
 
-  if (!strcmp(ErrorLog, "syslog"))
+  snprintf(jobmsg, sizeof(jobmsg), "[Job %d] %s", job->id, message);
+
+  do
   {
     va_start(ap, message);
-    vsyslog(syslevels[level], message, ap);
+    status = format_log_line(jobmsg, ap);
     va_end(ap);
-
-    return (1);
   }
-#endif /* HAVE_VSYSLOG */
+  while (status == 0);
 
- /*
-  * Not using syslog; check the log file...
-  */
+  if (status > 0)
+    return (cupsdWriteErrorLog(level, log_line));
+  else
+    return (cupsdWriteErrorLog(CUPSD_LOG_ERROR,
+                               "Unable to allocate memory for log line!"));
+}
 
-  if (!check_log_file(&ErrorFile, ErrorLog))
-    return (0);
 
- /*
-  * Print the log level and date/time...
-  */
+/*
+ * '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 */
+{
+  va_list              ap;             /* Argument pointer */
+  int                  status;         /* Formatting status */
 
-  cupsFilePrintf(ErrorFile, "%c %s ", levels[level], cupsdGetDateTime(time(NULL)));
 
  /*
-  * Allocate the line buffer as needed...
+  * See if we want to log this message...
   */
 
-  if (!linesize)
+  if (TestConfigFile)
   {
-    linesize = 8192;
-    line     = malloc(linesize);
-
-    if (!line)
+    if (level <= CUPSD_LOG_WARN)
     {
-      cupsFilePrintf(ErrorFile,
-                     "ERROR: Unable to allocate memory for line - %s\n",
-                     strerror(errno));
-      cupsFileFlush(ErrorFile);
-
-      return (0);
+      va_start(ap, message);
+      vfprintf(stderr, message, ap);
+      putc('\n', stderr);
+      va_end(ap);
     }
-  }
 
- /*
-  * Format the log message...
-  */
+    return (1);
+  }
 
-  va_start(ap, message);
-  len = vsnprintf(line, linesize, message, ap);
-  va_end(ap);
+  if (level > LogLevel || !ErrorLog)
+    return (1);
 
  /*
-  * Resize the buffer as needed...
+  * Format and write the log message...
   */
 
-  if (len >= linesize)
+  do
   {
-    char       *temp;                  /* Temporary string pointer */
-
-
-    len ++;
-
-    if (len < 8192)
-      len = 8192;
-    else if (len > 65536)
-      len = 65536;
-
-    temp = realloc(line, len);
-
-    if (temp)
-    {
-      line     = temp;
-      linesize = len;
-    }
-
     va_start(ap, message);
-    len = vsnprintf(line, linesize, message, ap);
+    status = format_log_line(message, ap);
     va_end(ap);
   }
+  while (status == 0);
 
-  if (len >= linesize)
-    len = linesize - 1;
-
- /*
-  * Then the log message...
-  */
-
-  cupsFilePuts(ErrorFile, line);
-
- /*
-  * Then a newline...
-  */
-
-  if (len > 0 && line[len - 1] != '\n')
-    cupsFilePutChar(ErrorFile, '\n');
-
- /*
-  * Flush the line to the file and return...
-  */
-
-  cupsFileFlush(ErrorFile);
-
-  return (1);
+  if (status > 0)
+    return (cupsdWriteErrorLog(level, log_line));
+  else
+    return (cupsdWriteErrorLog(CUPSD_LOG_ERROR,
+                               "Unable to allocate memory for log line!"));
 }
 
 
@@ -414,8 +345,10 @@ cupsdLogPage(cupsd_job_t *job,             /* I - Job being printed */
              * Pull the name from inside the brackets...
              */
 
-             memcpy(name, format + 1, nameend - format - 2);
-             name[nameend - format - 2] = '\0';
+             memcpy(name, format + 1, nameend - format - 1);
+             name[nameend - format - 1] = '\0';
+
+             format = nameend;
 
              if ((attr = ippFindAttribute(job->attrs, name,
                                           IPP_TAG_ZERO)) != NULL)
@@ -424,8 +357,6 @@ cupsdLogPage(cupsd_job_t *job,              /* I - Job being printed */
                * Add the attribute value...
                */
 
-               format = nameend;
-
                 for (i = 0;
                     i < attr->num_values &&
                         bufptr < (buffer + sizeof(buffer) - 1);
@@ -554,6 +485,112 @@ cupsdLogRequest(cupsd_client_t *con,      /* I - Request to log */
                };
 
 
+ /*
+  * Filter requests as needed...
+  */
+
+  if (AccessLogLevel < CUPSD_ACCESSLOG_ALL)
+  {
+   /*
+    * Eliminate simple GET requests...
+    */
+
+    if ((con->operation == HTTP_GET &&
+         strncmp(con->uri, "/admin/conf", 11) &&
+        strncmp(con->uri, "/admin/log", 10)) ||
+       (con->operation == HTTP_POST && !con->request &&
+        strncmp(con->uri, "/admin", 6)) ||
+       (con->operation != HTTP_POST && con->operation != HTTP_PUT))
+      return (1);
+
+    if (con->request && con->response &&
+        con->response->request.status.status_code < IPP_REDIRECTION_OTHER_SITE)
+    {
+     /*
+      * Check successful requests...
+      */
+
+      ipp_op_t op = con->request->request.op.operation_id;
+      static cupsd_accesslog_t standard_ops[] =
+      {
+        CUPSD_ACCESSLOG_ALL,   /* reserved */
+        CUPSD_ACCESSLOG_ALL,   /* reserved */
+        CUPSD_ACCESSLOG_ACTIONS,/* Print-Job */
+        CUPSD_ACCESSLOG_ACTIONS,/* Print-URI */
+        CUPSD_ACCESSLOG_ACTIONS,/* Validate-Job */
+        CUPSD_ACCESSLOG_ACTIONS,/* Create-Job */
+        CUPSD_ACCESSLOG_ACTIONS,/* Send-Document */
+        CUPSD_ACCESSLOG_ACTIONS,/* Send-URI */
+        CUPSD_ACCESSLOG_ACTIONS,/* Cancel-Job */
+        CUPSD_ACCESSLOG_ALL,   /* Get-Job-Attributes */
+        CUPSD_ACCESSLOG_ALL,   /* Get-Jobs */
+        CUPSD_ACCESSLOG_ALL,   /* Get-Printer-Attributes */
+        CUPSD_ACCESSLOG_ACTIONS,/* Hold-Job */
+        CUPSD_ACCESSLOG_ACTIONS,/* Release-Job */
+        CUPSD_ACCESSLOG_ACTIONS,/* Restart-Job */
+       CUPSD_ACCESSLOG_ALL,    /* reserved */
+        CUPSD_ACCESSLOG_CONFIG,        /* Pause-Printer */
+        CUPSD_ACCESSLOG_CONFIG,        /* Resume-Printer */
+        CUPSD_ACCESSLOG_CONFIG,        /* Purge-Jobs */
+        CUPSD_ACCESSLOG_CONFIG,        /* Set-Printer-Attributes */
+        CUPSD_ACCESSLOG_ACTIONS,/* Set-Job-Attributes */
+        CUPSD_ACCESSLOG_CONFIG,        /* Get-Printer-Supported-Values */
+        CUPSD_ACCESSLOG_ACTIONS,/* Create-Printer-Subscription */
+        CUPSD_ACCESSLOG_ACTIONS,/* Create-Job-Subscription */
+        CUPSD_ACCESSLOG_ALL,   /* Get-Subscription-Attributes */
+        CUPSD_ACCESSLOG_ALL,   /* Get-Subscriptions */
+        CUPSD_ACCESSLOG_ACTIONS,/* Renew-Subscription */
+        CUPSD_ACCESSLOG_ACTIONS,/* Cancel-Subscription */
+        CUPSD_ACCESSLOG_ALL,   /* Get-Notifications */
+        CUPSD_ACCESSLOG_ACTIONS,/* Send-Notifications */
+        CUPSD_ACCESSLOG_ALL,   /* reserved */
+        CUPSD_ACCESSLOG_ALL,   /* reserved */
+        CUPSD_ACCESSLOG_ALL,   /* reserved */
+        CUPSD_ACCESSLOG_ALL,   /* Get-Print-Support-Files */
+        CUPSD_ACCESSLOG_CONFIG,        /* Enable-Printer */
+        CUPSD_ACCESSLOG_CONFIG,        /* Disable-Printer */
+        CUPSD_ACCESSLOG_CONFIG,        /* Pause-Printer-After-Current-Job */
+        CUPSD_ACCESSLOG_ACTIONS,/* Hold-New-Jobs */
+        CUPSD_ACCESSLOG_ACTIONS,/* Release-Held-New-Jobs */
+        CUPSD_ACCESSLOG_CONFIG,        /* Deactivate-Printer */
+        CUPSD_ACCESSLOG_CONFIG,        /* Activate-Printer */
+        CUPSD_ACCESSLOG_CONFIG,        /* Restart-Printer */
+        CUPSD_ACCESSLOG_CONFIG,        /* Shutdown-Printer */
+        CUPSD_ACCESSLOG_CONFIG,        /* Startup-Printer */
+        CUPSD_ACCESSLOG_ACTIONS,/* Reprocess-Job */
+        CUPSD_ACCESSLOG_ACTIONS,/* Cancel-Current-Job */
+        CUPSD_ACCESSLOG_ACTIONS,/* Suspend-Current-Job */
+        CUPSD_ACCESSLOG_ACTIONS,/* Resume-Job */
+        CUPSD_ACCESSLOG_ACTIONS,/* Promote-Job */
+        CUPSD_ACCESSLOG_ACTIONS        /* Schedule-Job-After */
+      };
+      static cupsd_accesslog_t cups_ops[] =
+      {
+        CUPSD_ACCESSLOG_ALL,   /* CUPS-Get-Default */
+        CUPSD_ACCESSLOG_ALL,   /* CUPS-Get-Printers */
+        CUPSD_ACCESSLOG_CONFIG,        /* CUPS-Add-Modify-Printer */
+        CUPSD_ACCESSLOG_CONFIG,        /* CUPS-Delete-Printer */
+        CUPSD_ACCESSLOG_ALL,   /* CUPS-Get-Classes */
+        CUPSD_ACCESSLOG_CONFIG,        /* CUPS-Add-Modify-Class */
+        CUPSD_ACCESSLOG_CONFIG,        /* CUPS-Delete-Class */
+        CUPSD_ACCESSLOG_CONFIG,        /* CUPS-Accept-Jobs */
+        CUPSD_ACCESSLOG_CONFIG,        /* CUPS-Reject-Jobs */
+        CUPSD_ACCESSLOG_CONFIG,        /* CUPS-Set-Default */
+        CUPSD_ACCESSLOG_CONFIG,        /* CUPS-Get-Devices */
+        CUPSD_ACCESSLOG_CONFIG,        /* CUPS-Get-PPDs */
+        CUPSD_ACCESSLOG_ACTIONS,/* CUPS-Move-Job */
+        CUPSD_ACCESSLOG_ACTIONS,/* CUPS-Authenticate-Job */
+        CUPSD_ACCESSLOG_ALL    /* CUPS-Get-PPD */
+      };
+      
+
+      if ((op <= IPP_SCHEDULE_JOB_AFTER && standard_ops[op] > AccessLogLevel) ||
+          (op >= CUPS_GET_DEFAULT && op <= CUPS_GET_PPD &&
+          cups_ops[op - CUPS_GET_DEFAULT] > AccessLogLevel))
+        return (1);
+    }
+  }
+
 #ifdef HAVE_VSYSLOG
  /*
   * See if we are logging accesses via syslog...
@@ -606,6 +643,75 @@ cupsdLogRequest(cupsd_client_t *con,       /* I - Request to log */
 }
 
 
+/*
+ * 'cupsdWriteErrorLog()' - Write a line to the ErrorLog.
+ */
+
+int                                    /* O - 1 on success, 0 on failure */
+cupsdWriteErrorLog(int        level,   /* I - Log level */
+                   const char *message)        /* I - Message string */
+{
+  static const char    levels[] =      /* Log levels... */
+               {
+                 ' ',
+                 'X',
+                 'A',
+                 'C',
+                 'E',
+                 'W',
+                 'N',
+                 'I',
+                 'D',
+                 'd'
+               };
+#ifdef HAVE_VSYSLOG
+  static const int     syslevels[] =   /* SYSLOG levels... */
+               {
+                 0,
+                 LOG_EMERG,
+                 LOG_ALERT,
+                 LOG_CRIT,
+                 LOG_ERR,
+                 LOG_WARNING,
+                 LOG_NOTICE,
+                 LOG_INFO,
+                 LOG_DEBUG,
+                 LOG_DEBUG
+               };
+#endif /* HAVE_VSYSLOG */
+
+
+#ifdef HAVE_VSYSLOG
+ /*
+  * See if we are logging errors via syslog...
+  */
+
+  if (!strcmp(ErrorLog, "syslog"))
+  {
+    syslog(syslevels[level], "%s", message);
+    return (1);
+  }
+#endif /* HAVE_VSYSLOG */
+
+ /*
+  * Not using syslog; check the log file...
+  */
+
+  if (!check_log_file(&ErrorFile, ErrorLog))
+    return (0);
+
+ /*
+  * Write the log message...
+  */
+
+  cupsFilePrintf(ErrorFile, "%c %s %s\n", levels[level],
+                 cupsdGetDateTime(time(NULL)), message);
+  cupsFileFlush(ErrorFile);
+
+  return (1);
+}
+
+
 /*
  * 'check_log_file()' - Open/rotate a log file if it needs it.
  */
@@ -701,7 +807,20 @@ check_log_file(cups_file_t **lf,   /* IO - Log file */
 
       if (!strncmp(filename, CUPS_LOGDIR, strlen(CUPS_LOGDIR)))
       {
-        cupsdCheckPermissions(CUPS_LOGDIR, NULL, 0755, RunUser, Group, 1, -1);
+       /*
+        * Try updating the permissions of the containing log directory, using
+       * the log file permissions as a basis...
+       */
+
+        int log_dir_perm = 0300 | LogFilePerm;
+                                       /* LogFilePerm + owner write/search */
+       if (log_dir_perm & 0040)
+         log_dir_perm |= 0010;         /* Add group search */
+       if (log_dir_perm & 0004)
+         log_dir_perm |= 0001;         /* Add other search */
+
+        cupsdCheckPermissions(CUPS_LOGDIR, NULL, log_dir_perm, RunUser, Group,
+                             1, -1);
 
         *lf = cupsFileOpen(filename, "a");
       }
@@ -710,6 +829,10 @@ check_log_file(cups_file_t **lf,   /* IO - Log file */
       {
        syslog(LOG_ERR, "Unable to open log file \"%s\" - %s", filename,
               strerror(errno));
+
+        if (FatalErrors & CUPSD_FATAL_LOG)
+         cupsdEndProcess(getpid(), 0);
+
        return (0);
       }
     }
@@ -749,6 +872,9 @@ check_log_file(cups_file_t **lf,    /* IO - Log file */
       syslog(LOG_ERR, "Unable to open log file \"%s\" - %s", filename,
              strerror(errno));
 
+      if (FatalErrors & CUPSD_FATAL_LOG)
+       cupsdEndProcess(getpid(), 0);
+
       return (0);
     }
 
@@ -765,5 +891,70 @@ check_log_file(cups_file_t **lf,   /* IO - Log file */
 
 
 /*
- * End of "$Id: log.c 6875 2007-08-27 23:25:06Z mike $".
+ * 'format_log_line()' - Format a line for a log file.
+ *
+ * This function resizes a global string buffer as needed.  Each call returns
+ * a pointer to this buffer, so the contents are only good until the next call
+ * to format_log_line()...
+ */
+
+static int                             /* O - -1 for fatal, 0 for retry, 1 for success */
+format_log_line(const char *message,   /* I - Printf-style format string */
+                va_list    ap)         /* I - Argument list */
+{
+  int          len;                    /* Length of formatted line */
+
+
+ /*
+  * Allocate the line buffer as needed...
+  */
+
+  if (!log_linesize)
+  {
+    log_linesize = 8192;
+    log_line     = malloc(log_linesize);
+
+    if (!log_line)
+      return (-1);
+  }
+
+ /*
+  * Format the log message...
+  */
+
+  len = vsnprintf(log_line, log_linesize, message, ap);
+
+ /*
+  * Resize the buffer as needed...
+  */
+
+  if (len >= log_linesize)
+  {
+    char       *temp;                  /* Temporary string pointer */
+
+
+    len ++;
+
+    if (len < 8192)
+      len = 8192;
+    else if (len > 65536)
+      len = 65536;
+
+    temp = realloc(log_line, len);
+
+    if (temp)
+    {
+      log_line     = temp;
+      log_linesize = len;
+
+      return (0);
+    }
+  }
+
+  return (1);
+}
+
+
+/*
+ * End of "$Id: log.c 7918 2008-09-08 22:03:01Z mike $".
  */