示例#1
0
static void
process_children(void)
{
  int		status;			/* Exit status of child */
  int		pid,			/* Process ID of child */
		job_id;			/* Job ID of child */
  cupsd_job_t	*job;			/* Current job */
  int		i;			/* Looping var */
  char		name[1024];		/* Process name */
  const char	*type;			/* Type of program */


  cupsdLogMessage(CUPSD_LOG_DEBUG2, "process_children()");

 /*
  * Reset the dead_children flag...
  */

  dead_children = 0;

 /*
  * Collect the exit status of some children...
  */

#ifdef HAVE_WAITPID
  while ((pid = waitpid(-1, &status, WNOHANG)) > 0)
#elif defined(HAVE_WAIT3)
  while ((pid = wait3(&status, WNOHANG, NULL)) > 0)
#else
  if ((pid = wait(&status)) > 0)
#endif /* HAVE_WAITPID */
  {
   /*
    * Collect the name of the process that finished...
    */

    cupsdFinishProcess(pid, name, sizeof(name), &job_id);

   /*
    * Delete certificates for CGI processes...
    */

    if (pid)
      cupsdDeleteCert(pid);

   /*
    * Handle completed job filters...
    */

    if (job_id > 0)
      job = cupsdFindJob(job_id);
    else
      job  = NULL;

    if (job)
    {
      for (i = 0; job->filters[i]; i ++)
	if (job->filters[i] == pid)
	  break;

      if (job->filters[i] || job->backend == pid)
      {
       /*
	* OK, this process has gone away; what's left?
	*/

	if (job->filters[i])
	{
	  job->filters[i] = -pid;
	  type            = "Filter";
	}
	else
	{
	  job->backend = -pid;
	  type         = "Backend";
	}

	if (status && status != SIGTERM && status != SIGKILL &&
	    status != SIGPIPE)
	{
	 /*
	  * An error occurred; save the exit status so we know to stop
	  * the printer or cancel the job when all of the filters finish...
	  *
	  * A negative status indicates that the backend failed and the
	  * printer needs to be stopped.
	  *
	  * In order to preserve the most serious status, we always log
	  * when a process dies due to a signal (e.g. SIGABRT, SIGSEGV,
	  * and SIGBUS) and prefer to log the backend exit status over a
	  * filter's.
	  */

	  int old_status = abs(job->status);

          if (WIFSIGNALED(status) ||	/* This process crashed, or */
              !job->status ||		/* No process had a status, or */
              (!job->filters[i] && WIFEXITED(old_status)))
          {				/* Backend and filter didn't crash */
	    if (job->filters[i])
	      job->status = status;	/* Filter failed */
	    else
	      job->status = -status;	/* Backend failed */
          }

	  if (job->state_value == IPP_JOB_PROCESSING &&
	      job->status_level > CUPSD_LOG_ERROR &&
	      (job->filters[i] || !WIFEXITED(status)))
	  {
	    char	message[1024];	/* New printer-state-message */


	    job->status_level = CUPSD_LOG_ERROR;

	    snprintf(message, sizeof(message), "%s failed", type);

            if (job->printer)
	    {
	      strlcpy(job->printer->state_message, message,
		       sizeof(job->printer->state_message));
	    }

	    if (!job->attrs)
	      cupsdLoadJob(job);

	    if (!job->printer_message && job->attrs)
	    {
	      if ((job->printer_message =
	               ippFindAttribute(job->attrs, "job-printer-state-message",
					IPP_TAG_TEXT)) == NULL)
		job->printer_message = ippAddString(job->attrs, IPP_TAG_JOB,
		                                    IPP_TAG_TEXT,
						    "job-printer-state-message",
						    NULL, NULL);
	    }

	    if (job->printer_message)
	      cupsdSetString(&(job->printer_message->values[0].string.text),
			     message);
	  }
	}

       /*
	* If this is not the last file in a job, see if all of the
	* filters are done, and if so move to the next file.
	*/

	if (job->current_file < job->num_files && job->printer)
	{
	  for (i = 0; job->filters[i] < 0; i ++);

	  if (!job->filters[i] &&
	      (!job->printer->pc || !job->printer->pc->single_file ||
	       job->backend <= 0))
	  {
	   /*
	    * Process the next file...
	    */

	    cupsdContinueJob(job);
	  }
	}
	else if (job->state_value >= IPP_JOB_CANCELED)
	{
	 /*
	  * Remove the job from the active list if there are no processes still
	  * running for it...
	  */

	  for (i = 0; job->filters[i] < 0; i++);

	  if (!job->filters[i] && job->backend <= 0)
	    cupsArrayRemove(ActiveJobs, job);
	}
      }
    }

   /*
    * Show the exit status as needed, ignoring SIGTERM and SIGKILL errors
    * since they come when we kill/end a process...
    */

    if (status == SIGTERM || status == SIGKILL)
    {
      cupsdLogJob(job, CUPSD_LOG_DEBUG,
		  "PID %d (%s) was terminated normally with signal %d.", pid,
		  name, status);
    }
    else if (status == SIGPIPE)
    {
      cupsdLogJob(job, CUPSD_LOG_DEBUG,
		  "PID %d (%s) did not catch or ignore signal %d.", pid, name,
		  status);
    }
    else if (status)
    {
      if (WIFEXITED(status))
      {
        int code = WEXITSTATUS(status);	/* Exit code */

        if (code > 100)
	  cupsdLogJob(job, CUPSD_LOG_DEBUG,
		      "PID %d (%s) stopped with status %d (%s)", pid, name,
		      code, strerror(code - 100));
	else
	  cupsdLogJob(job, CUPSD_LOG_DEBUG,
		      "PID %d (%s) stopped with status %d.", pid, name, code);
      }
      else
	cupsdLogJob(job, CUPSD_LOG_DEBUG, "PID %d (%s) crashed on signal %d.",
		    pid, name, WTERMSIG(status));

      if (LogLevel < CUPSD_LOG_DEBUG)
        cupsdLogJob(job, CUPSD_LOG_INFO,
		    "Hint: Try setting the LogLevel to \"debug\" to find out "
		    "more.");
    }
    else
      cupsdLogJob(job, CUPSD_LOG_DEBUG, "PID %d (%s) exited with no errors.",
		  pid, name);
  }

 /*
  * If wait*() is interrupted by a signal, tell main() to call us again...
  */

  if (pid < 0 && errno == EINTR)
    dead_children = 1;
}
示例#2
0
文件: subscriptions.c 项目: aosm/cups
void
cupsdLoadAllSubscriptions(void)
{
  int			i;		/* Looping var */
  cups_file_t		*fp;		/* subscriptions.conf file */
  int			linenum;	/* Current line number */
  char			line[1024],	/* Line from file */
			*value,		/* Pointer to value */
			*valueptr;	/* Pointer into value */
  cupsd_subscription_t	*sub;		/* Current subscription */
  int			hex;		/* Non-zero if reading hex data */
  int			delete_sub;	/* Delete subscription? */


 /*
  * Open the subscriptions.conf file...
  */

  snprintf(line, sizeof(line), "%s/subscriptions.conf", ServerRoot);
  if ((fp = cupsdOpenConfFile(line)) == NULL)
    return;

 /*
  * Read all of the lines from the file...
  */

  linenum    = 0;
  sub        = NULL;
  delete_sub = 0;

  while (cupsFileGetConf(fp, line, sizeof(line), &value, &linenum))
  {
    if (!_cups_strcasecmp(line, "NextSubscriptionId") && value)
    {
     /*
      * NextSubscriptionId NNN
      */

      i = atoi(value);
      if (i >= NextSubscriptionId && i > 0)
        NextSubscriptionId = i;
    }
    else if (!_cups_strcasecmp(line, "<Subscription"))
    {
     /*
      * <Subscription #>
      */

      if (!sub && value && isdigit(value[0] & 255))
      {
        sub = cupsdAddSubscription(CUPSD_EVENT_NONE, NULL, NULL, NULL,
	                           atoi(value));
      }
      else
      {
        cupsdLogMessage(CUPSD_LOG_ERROR,
	                "Syntax error on line %d of subscriptions.conf.",
	                linenum);
        break;
      }
    }
    else if (!_cups_strcasecmp(line, "</Subscription>"))
    {
      if (!sub)
      {
        cupsdLogMessage(CUPSD_LOG_ERROR,
	                "Syntax error on line %d of subscriptions.conf.",
	                linenum);
        break;
      }

      if (delete_sub)
        cupsdDeleteSubscription(sub, 0);

      sub        = NULL;
      delete_sub = 0;
    }
    else if (!sub)
    {
      cupsdLogMessage(CUPSD_LOG_ERROR,
                      "Syntax error on line %d of subscriptions.conf.",
	              linenum);
    }
    else if (!_cups_strcasecmp(line, "Events"))
    {
     /*
      * Events name
      * Events name name name ...
      */

      if (!value)
      {
	cupsdLogMessage(CUPSD_LOG_ERROR,
	                "Syntax error on line %d of subscriptions.conf.",
	                linenum);
	break;
      }

      while (*value)
      {
       /*
        * Separate event names...
	*/

        for (valueptr = value; !isspace(*valueptr) && *valueptr; valueptr ++);

	while (isspace(*valueptr & 255))
	  *valueptr++ = '\0';

       /*
        * See if the name exists...
	*/

        if ((sub->mask |= cupsdEventValue(value)) == CUPSD_EVENT_NONE)
	{
	  cupsdLogMessage(CUPSD_LOG_ERROR,
	                  "Unknown event name \'%s\' on line %d of subscriptions.conf.",
	                  value, linenum);
	  break;
	}

	value = valueptr;
      }
    }
    else if (!_cups_strcasecmp(line, "Owner"))
    {
     /*
      * Owner
      */

      if (value)
	cupsdSetString(&sub->owner, value);
      else
      {
	cupsdLogMessage(CUPSD_LOG_ERROR,
	                "Syntax error on line %d of subscriptions.conf.",
	                linenum);
	break;
      }
    }
    else if (!_cups_strcasecmp(line, "Recipient"))
    {
     /*
      * Recipient uri
      */

      if (value)
	cupsdSetString(&sub->recipient, value);
      else
      {
	cupsdLogMessage(CUPSD_LOG_ERROR,
	                "Syntax error on line %d of subscriptions.conf.",
	                linenum);
	break;
      }
    }
    else if (!_cups_strcasecmp(line, "JobId"))
    {
     /*
      * JobId #
      */

      if (value && isdigit(*value & 255))
      {
        if ((sub->job = cupsdFindJob(atoi(value))) == NULL)
	{
	  cupsdLogMessage(CUPSD_LOG_ERROR,
	                  "Job %s not found on line %d of subscriptions.conf.",
	                  value, linenum);
	  delete_sub = 1;
	}
      }
      else
      {
	cupsdLogMessage(CUPSD_LOG_ERROR,
	                "Syntax error on line %d of subscriptions.conf.",
	                linenum);
	break;
      }
    }
    else if (!_cups_strcasecmp(line, "PrinterName"))
    {
     /*
      * PrinterName name
      */

      if (value)
      {
        if ((sub->dest = cupsdFindDest(value)) == NULL)
	{
	  cupsdLogMessage(CUPSD_LOG_ERROR,
	                  "Printer \'%s\' not found on line %d of subscriptions.conf.",
	                  value, linenum);
	  delete_sub = 1;
	}
      }
      else
      {
	cupsdLogMessage(CUPSD_LOG_ERROR,
	                "Syntax error on line %d of subscriptions.conf.",
	                linenum);
	break;
      }
    }
    else if (!_cups_strcasecmp(line, "UserData"))
    {
     /*
      * UserData encoded-string
      */

      if (value)
      {
        for (i = 0, valueptr = value, hex = 0; i < 63 && *valueptr; i ++)
	{
	  if (*valueptr == '<' && !hex)
	  {
	    hex = 1;
	    valueptr ++;
	  }

	  if (hex)
	  {
	    if (isxdigit(valueptr[0]) && isxdigit(valueptr[1]))
	    {
	      if (isdigit(valueptr[0]))
	        sub->user_data[i] = (unsigned char)((valueptr[0] - '0') << 4);
	      else
	        sub->user_data[i] = (unsigned char)((tolower(valueptr[0]) - 'a' + 10) << 4);

	      if (isdigit(valueptr[1]))
	        sub->user_data[i] |= valueptr[1] - '0';
	      else
	        sub->user_data[i] |= tolower(valueptr[1]) - 'a' + 10;

              valueptr += 2;

	      if (*valueptr == '>')
	      {
	        hex = 0;
		valueptr ++;
	      }
	    }
	    else
	      break;
	  }
	  else
	    sub->user_data[i] = (unsigned char)*valueptr++;
	}

	if (*valueptr)
	{
	  cupsdLogMessage(CUPSD_LOG_ERROR,
	                  "Bad UserData \'%s\' on line %d of subscriptions.conf.",
	                  value, linenum);
	}
	else
	  sub->user_data_len = i;
      }
      else
      {
	cupsdLogMessage(CUPSD_LOG_ERROR,
	                "Syntax error on line %d of subscriptions.conf.",
	                linenum);
	break;
      }
    }
    else if (!_cups_strcasecmp(line, "LeaseDuration"))
    {
     /*
      * LeaseDuration #
      */

      if (value && isdigit(*value & 255))
      {
        sub->lease  = atoi(value);
        sub->expire = sub->lease ? time(NULL) + sub->lease : 0;
      }
      else
      {
	cupsdLogMessage(CUPSD_LOG_ERROR,
	                "Syntax error on line %d of subscriptions.conf.",
	                linenum);
	break;
      }
    }
    else if (!_cups_strcasecmp(line, "Interval"))
    {
     /*
      * Interval #
      */

      if (value && isdigit(*value & 255))
        sub->interval = atoi(value);
      else
      {
	cupsdLogMessage(CUPSD_LOG_ERROR,
	                "Syntax error on line %d of subscriptions.conf.",
	                linenum);
	break;
      }
    }
    else if (!_cups_strcasecmp(line, "ExpirationTime"))
    {
     /*
      * ExpirationTime #
      */

      if (value && isdigit(*value & 255))
        sub->expire = atoi(value);
      else
      {
	cupsdLogMessage(CUPSD_LOG_ERROR,
	                "Syntax error on line %d of subscriptions.conf.",
	                linenum);
	break;
      }
    }
    else if (!_cups_strcasecmp(line, "NextEventId"))
    {
     /*
      * NextEventId #
      */

      if (value && isdigit(*value & 255))
        sub->next_event_id = sub->first_event_id = atoi(value);
      else
      {
	cupsdLogMessage(CUPSD_LOG_ERROR,
	                "Syntax error on line %d of subscriptions.conf.",
	                linenum);
	break;
      }
    }
    else
    {
     /*
      * Something else we don't understand...
      */

      cupsdLogMessage(CUPSD_LOG_ERROR,
                      "Unknown configuration directive %s on line %d of subscriptions.conf.",
	              line, linenum);
    }
  }

  cupsFileClose(fp);
}