Example #1
0
void
cupsdAddEvent(
    cupsd_eventmask_t event,		/* I - Event */
    cupsd_printer_t   *dest,		/* I - Printer associated with event */
    cupsd_job_t       *job,		/* I - Job associated with event */
    const char        *text,		/* I - Notification text */
    ...)				/* I - Additional arguments as needed */
{
  va_list		ap;		/* Pointer to additional arguments */
  char			ftext[1024];	/* Formatted text buffer */
  ipp_attribute_t	*attr;		/* Printer/job attribute */
  cupsd_event_t		*temp;		/* New event pointer */
  cupsd_subscription_t	*sub;		/* Current subscription */


  cupsdLogMessage(CUPSD_LOG_DEBUG2,
                  "cupsdAddEvent(event=%s, dest=%p(%s), job=%p(%d), text=\"%s\", ...)",
		  cupsdEventName(event), dest, dest ? dest->name : "",
		  job, job ? job->id : 0, text);

 /*
  * Keep track of events with any OS-supplied notification mechanisms...
  */

  LastEvent |= event;

#ifdef HAVE_DBUS
  cupsd_send_dbus(event, dest, job);
#endif /* HAVE_DBUS */

 /*
  * Return if we aren't keeping events...
  */

  if (MaxEvents <= 0)
  {
    cupsdLogMessage(CUPSD_LOG_WARN,
                    "cupsdAddEvent: Discarding %s event since MaxEvents is %d!",
                    cupsdEventName(event), MaxEvents);
    return;
  }

 /*
  * Then loop through the subscriptions and add the event to the corresponding
  * caches...
  */

  for (temp = NULL, sub = (cupsd_subscription_t *)cupsArrayFirst(Subscriptions);
       sub;
       sub = (cupsd_subscription_t *)cupsArrayNext(Subscriptions))
  {
   /*
    * Check if this subscription requires this event...
    */

    if ((sub->mask & event) != 0 &&
        (sub->dest == dest || !sub->dest) &&
	(sub->job == job || !sub->job))
    {
     /*
      * Need this event, so create a new event record...
      */

      if ((temp = (cupsd_event_t *)calloc(1, sizeof(cupsd_event_t))) == NULL)
      {
	cupsdLogMessage(CUPSD_LOG_CRIT,
	                "Unable to allocate memory for event - %s",
        	        strerror(errno));
	return;
      }

      temp->event = event;
      temp->time  = time(NULL);
      temp->attrs = ippNew();
      temp->job   = job;

      if (dest)
        temp->dest = dest;
      else if (job)
        temp->dest = dest = cupsdFindPrinter(job->dest);

     /*
      * Add common event notification attributes...
      */

      ippAddString(temp->attrs, IPP_TAG_EVENT_NOTIFICATION, IPP_TAG_CHARSET,
                   "notify-charset", NULL, "utf-8");

      ippAddString(temp->attrs, IPP_TAG_EVENT_NOTIFICATION, IPP_TAG_LANGUAGE,
                   "notify-natural-language", NULL, "en-US");

      ippAddInteger(temp->attrs, IPP_TAG_EVENT_NOTIFICATION, IPP_TAG_INTEGER,
	            "notify-subscription-id", sub->id);

      ippAddInteger(temp->attrs, IPP_TAG_EVENT_NOTIFICATION, IPP_TAG_INTEGER,
	            "notify-sequence-number", sub->next_event_id);

      ippAddString(temp->attrs, IPP_TAG_EVENT_NOTIFICATION, IPP_TAG_KEYWORD,
	           "notify-subscribed-event", NULL, cupsdEventName(event));

      if (sub->user_data_len > 0)
        ippAddOctetString(temp->attrs, IPP_TAG_EVENT_NOTIFICATION,
	                  "notify-user-data", sub->user_data,
			  sub->user_data_len);

      ippAddInteger(temp->attrs, IPP_TAG_EVENT_NOTIFICATION, IPP_TAG_INTEGER,
	            "printer-up-time", time(NULL));

      va_start(ap, text);
      vsnprintf(ftext, sizeof(ftext), text, ap);
      va_end(ap);

      ippAddString(temp->attrs, IPP_TAG_EVENT_NOTIFICATION, IPP_TAG_TEXT,
	           "notify-text", NULL, ftext);

      if (dest)
      {
       /*
	* Add printer attributes...
	*/

	ippAddString(temp->attrs, IPP_TAG_EVENT_NOTIFICATION, IPP_TAG_URI,
	             "notify-printer-uri", NULL, dest->uri);

	ippAddString(temp->attrs, IPP_TAG_EVENT_NOTIFICATION, IPP_TAG_NAME,
	             "printer-name", NULL, dest->name);

	ippAddInteger(temp->attrs, IPP_TAG_EVENT_NOTIFICATION, IPP_TAG_ENUM,
	              "printer-state", dest->state);

	if (dest->num_reasons == 0)
	  ippAddString(temp->attrs, IPP_TAG_EVENT_NOTIFICATION,
	               IPP_TAG_KEYWORD, "printer-state-reasons", NULL,
		       dest->state == IPP_PRINTER_STOPPED ? "paused" : "none");
	else
	  ippAddStrings(temp->attrs, IPP_TAG_EVENT_NOTIFICATION,
	                IPP_TAG_KEYWORD, "printer-state-reasons",
			dest->num_reasons, NULL,
			(const char * const *)dest->reasons);

	ippAddBoolean(temp->attrs, IPP_TAG_EVENT_NOTIFICATION,
	              "printer-is-accepting-jobs", (char)dest->accepting);
      }

      if (job)
      {
       /*
	* Add job attributes...
	*/

	ippAddInteger(temp->attrs, IPP_TAG_EVENT_NOTIFICATION, IPP_TAG_INTEGER,
	              "notify-job-id", job->id);
	ippAddInteger(temp->attrs, IPP_TAG_EVENT_NOTIFICATION, IPP_TAG_ENUM,
	              "job-state", job->state_value);

        if ((attr = ippFindAttribute(job->attrs, "job-name",
	                             IPP_TAG_NAME)) != NULL)
	  ippAddString(temp->attrs, IPP_TAG_EVENT_NOTIFICATION, IPP_TAG_NAME,
	               "job-name", NULL, attr->values[0].string.text);

	switch (job->state_value)
	{
	  case IPP_JOB_PENDING :
              if (dest && dest->state == IPP_PRINTER_STOPPED)
        	ippAddString(temp->attrs, IPP_TAG_EVENT_NOTIFICATION,
		             IPP_TAG_KEYWORD, "job-state-reasons", NULL,
			     "printer-stopped");
              else
        	ippAddString(temp->attrs, IPP_TAG_EVENT_NOTIFICATION,
		             IPP_TAG_KEYWORD, "job-state-reasons", NULL,
			     "none");
              break;

	  case IPP_JOB_HELD :
              if (ippFindAttribute(job->attrs, "job-hold-until", IPP_TAG_KEYWORD) != NULL ||
		  ippFindAttribute(job->attrs, "job-hold-until", IPP_TAG_NAME) != NULL)
        	ippAddString(temp->attrs, IPP_TAG_EVENT_NOTIFICATION,
		             IPP_TAG_KEYWORD, "job-state-reasons", NULL,
			     "job-hold-until-specified");
              else
        	ippAddString(temp->attrs, IPP_TAG_EVENT_NOTIFICATION,
		             IPP_TAG_KEYWORD, "job-state-reasons", NULL,
			     "job-incoming");
              break;

	  case IPP_JOB_PROCESSING :
              ippAddString(temp->attrs, IPP_TAG_EVENT_NOTIFICATION,
		           IPP_TAG_KEYWORD, "job-state-reasons", NULL,
			   "job-printing");
              break;

	  case IPP_JOB_STOPPED :
              ippAddString(temp->attrs, IPP_TAG_EVENT_NOTIFICATION,
		           IPP_TAG_KEYWORD, "job-state-reasons", NULL,
			   "job-stopped");
              break;

	  case IPP_JOB_CANCELED :
              ippAddString(temp->attrs, IPP_TAG_EVENT_NOTIFICATION,
		           IPP_TAG_KEYWORD, "job-state-reasons", NULL,
			   "job-canceled-by-user");
              break;

	  case IPP_JOB_ABORTED :
              ippAddString(temp->attrs, IPP_TAG_EVENT_NOTIFICATION,
		           IPP_TAG_KEYWORD, "job-state-reasons", NULL,
			   "aborted-by-system");
              break;

	  case IPP_JOB_COMPLETED :
              ippAddString(temp->attrs, IPP_TAG_EVENT_NOTIFICATION,
		           IPP_TAG_KEYWORD, "job-state-reasons", NULL,
			   "job-completed-successfully");
              break;
	}

	ippAddInteger(temp->attrs, IPP_TAG_EVENT_NOTIFICATION, IPP_TAG_INTEGER,
	              "job-impressions-completed",
		      job->sheets ? job->sheets->values[0].integer : 0);
      }

     /*
      * Send the notification for this subscription...
      */

      cupsd_send_notification(sub, temp);
    }
  }

  if (temp)
    cupsdMarkDirty(CUPSD_DIRTY_SUBSCRIPTIONS);
  else
    cupsdLogMessage(CUPSD_LOG_DEBUG, "Discarding unused %s event...",
                    cupsdEventName(event));
}
Example #2
0
void
cupsdLoadAllClasses(void)
{
  int			i;		/* Looping var */
  cups_file_t		*fp;		/* classes.conf file */
  int			linenum;	/* Current line number */
  char			line[4096],	/* Line from file */
			*value,		/* Pointer to value */
			*valueptr;	/* Pointer into value */
  cupsd_printer_t	*p,		/* Current printer class */
			*temp;		/* Temporary pointer to printer */


 /*
  * Open the classes.conf file...
  */

  snprintf(line, sizeof(line), "%s/classes.conf", ServerRoot);
  if ((fp = cupsFileOpen(line, "r")) == NULL)
  {
    if (errno != ENOENT)
      cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to open %s - %s", line,
		      strerror(errno));
    return;
  }

 /*
  * Read class configurations until we hit EOF...
  */

  linenum = 0;
  p       = NULL;

  while (cupsFileGetConf(fp, line, sizeof(line), &value, &linenum))
  {
   /*
    * Decode the directive...
    */

    if (!strcasecmp(line, "<Class") ||
        !strcasecmp(line, "<DefaultClass"))
    {
     /*
      * <Class name> or <DefaultClass name>
      */

      if (p == NULL && value)
      {
        cupsdLogMessage(CUPSD_LOG_DEBUG, "Loading class %s...", value);

       /*
        * Since prior classes may have implicitly defined this class,
	* see if it already exists...
	*/

        if ((p = cupsdFindDest(value)) != NULL)
	{
	  p->type = CUPS_PRINTER_CLASS;
	  cupsdSetStringf(&p->uri, "ipp://%s:%d/classes/%s", ServerName,
	                  LocalPort, value);
	  cupsdSetString(&p->error_policy, "retry-job");
	}
	else
          p = cupsdAddClass(value);

	p->accepting = 1;
	p->state     = IPP_PRINTER_IDLE;

        if (!strcasecmp(line, "<DefaultClass"))
	  DefaultPrinter = p;
      }
      else
        cupsdLogMessage(CUPSD_LOG_ERROR,
	                "Syntax error on line %d of classes.conf.", linenum);
    }
    else if (!strcasecmp(line, "</Class>"))
    {
      if (p != NULL)
      {
        cupsdSetPrinterAttrs(p);
        p = NULL;
      }
      else
        cupsdLogMessage(CUPSD_LOG_ERROR,
	                "Syntax error on line %d of classes.conf.", linenum);
    }
    else if (!p)
    {
      cupsdLogMessage(CUPSD_LOG_ERROR,
                      "Syntax error on line %d of classes.conf.", linenum);
    }
    else if (!strcasecmp(line, "AuthInfoRequired"))
    {
      if (!cupsdSetAuthInfoRequired(p, value, NULL))
	cupsdLogMessage(CUPSD_LOG_ERROR,
			"Bad AuthInfoRequired on line %d of classes.conf.",
			linenum);
    }
    else if (!strcasecmp(line, "Info"))
    {
      if (value)
        cupsdSetString(&p->info, value);
    }
    else if (!strcasecmp(line, "Location"))
    {
      if (value)
        cupsdSetString(&p->location, value);
    }
    else if (!strcasecmp(line, "Option") && value)
    {
     /*
      * Option name value
      */

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

      if (!*valueptr)
        cupsdLogMessage(CUPSD_LOG_ERROR,
	                "Syntax error on line %d of classes.conf.", linenum);
      else
      {
        for (; *valueptr && isspace(*valueptr & 255); *valueptr++ = '\0');

        p->num_options = cupsAddOption(value, valueptr, p->num_options,
	                               &(p->options));
      }
    }
    else if (!strcasecmp(line, "Printer"))
    {
      if (!value)
      {
	cupsdLogMessage(CUPSD_LOG_ERROR,
	                "Syntax error on line %d of classes.conf.", linenum);
        continue;
      }
      else if ((temp = cupsdFindPrinter(value)) == NULL)
      {
	cupsdLogMessage(CUPSD_LOG_WARN,
	                "Unknown printer %s on line %d of classes.conf.",
	                value, linenum);

       /*
	* Add the missing remote printer...
	*/

	if ((temp = cupsdAddPrinter(value)) != NULL)
	{
	  cupsdSetString(&temp->make_model, "Remote Printer on unknown");

          temp->state       = IPP_PRINTER_STOPPED;
	  temp->type        |= CUPS_PRINTER_REMOTE;
	  temp->browse_time = 2147483647;

	  cupsdSetString(&temp->location, "Location Unknown");
	  cupsdSetString(&temp->info, "No Information Available");
	  temp->hostname[0] = '\0';

	  cupsdSetPrinterAttrs(temp);
	}
      }

      if (temp)
        cupsdAddPrinterToClass(p, temp);
    }
    else if (!strcasecmp(line, "State"))
    {
     /*
      * Set the initial queue state...
      */

      if (!strcasecmp(value, "idle"))
        p->state = IPP_PRINTER_IDLE;
      else if (!strcasecmp(value, "stopped"))
      {
        p->state = IPP_PRINTER_STOPPED;

        for (i = 0 ; i < p->num_reasons; i ++)
	  if (!strcmp("paused", p->reasons[i]))
	    break;

        if (i >= p->num_reasons &&
	    p->num_reasons < (int)(sizeof(p->reasons) / sizeof(p->reasons[0])))
	{
	  p->reasons[p->num_reasons] = _cupsStrAlloc("paused");
	  p->num_reasons ++;
	}
      }
      else
	cupsdLogMessage(CUPSD_LOG_ERROR,
	                "Syntax error on line %d of classes.conf.",
	                linenum);
    }
    else if (!strcasecmp(line, "StateMessage"))
    {
     /*
      * Set the initial queue state message...
      */

      if (value)
	strlcpy(p->state_message, value, sizeof(p->state_message));
    }
    else if (!strcasecmp(line, "StateTime"))
    {
     /*
      * Set the state time...
      */

      if (value)
        p->state_time = atoi(value);
    }
    else if (!strcasecmp(line, "Accepting"))
    {
     /*
      * Set the initial accepting state...
      */

      if (value &&
          (!strcasecmp(value, "yes") ||
           !strcasecmp(value, "on") ||
           !strcasecmp(value, "true")))
        p->accepting = 1;
      else if (value &&
               (!strcasecmp(value, "no") ||
        	!strcasecmp(value, "off") ||
        	!strcasecmp(value, "false")))
        p->accepting = 0;
      else
	cupsdLogMessage(CUPSD_LOG_ERROR,
	                "Syntax error on line %d of classes.conf.",
	                linenum);
    }
    else if (!strcasecmp(line, "Shared"))
    {
     /*
      * Set the initial shared state...
      */

      if (value &&
          (!strcasecmp(value, "yes") ||
           !strcasecmp(value, "on") ||
           !strcasecmp(value, "true")))
        p->shared = 1;
      else if (value &&
               (!strcasecmp(value, "no") ||
        	!strcasecmp(value, "off") ||
        	!strcasecmp(value, "false")))
        p->shared = 0;
      else
	cupsdLogMessage(CUPSD_LOG_ERROR,
	                "Syntax error on line %d of classes.conf.",
	                linenum);
    }
    else if (!strcasecmp(line, "JobSheets"))
    {
     /*
      * Set the initial job sheets...
      */

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

	if (*valueptr)
          *valueptr++ = '\0';

	cupsdSetString(&p->job_sheets[0], value);

	while (isspace(*valueptr & 255))
          valueptr ++;

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

	  if (*valueptr)
            *valueptr = '\0';

	  cupsdSetString(&p->job_sheets[1], value);
	}
      }
      else
	cupsdLogMessage(CUPSD_LOG_ERROR,
	                "Syntax error on line %d of classes.conf.", linenum);
    }
    else if (!strcasecmp(line, "AllowUser"))
    {
      if (value)
      {
        p->deny_users = 0;
        cupsdAddPrinterUser(p, value);
      }
      else
	cupsdLogMessage(CUPSD_LOG_ERROR,
	                "Syntax error on line %d of classes.conf.", linenum);
    }
    else if (!strcasecmp(line, "DenyUser"))
    {
      if (value)
      {
        p->deny_users = 1;
        cupsdAddPrinterUser(p, value);
      }
      else
	cupsdLogMessage(CUPSD_LOG_ERROR,
	                "Syntax error on line %d of classes.conf.", linenum);
    }
    else if (!strcasecmp(line, "QuotaPeriod"))
    {
      if (value)
        p->quota_period = atoi(value);
      else
	cupsdLogMessage(CUPSD_LOG_ERROR,
	                "Syntax error on line %d of classes.conf.", linenum);
    }
    else if (!strcasecmp(line, "PageLimit"))
    {
      if (value)
        p->page_limit = atoi(value);
      else
	cupsdLogMessage(CUPSD_LOG_ERROR,
	                "Syntax error on line %d of classes.conf.", linenum);
    }
    else if (!strcasecmp(line, "KLimit"))
    {
      if (value)
        p->k_limit = atoi(value);
      else
	cupsdLogMessage(CUPSD_LOG_ERROR,
	                "Syntax error on line %d of classes.conf.", linenum);
    }
    else if (!strcasecmp(line, "OpPolicy"))
    {
      if (value)
      {
        cupsd_policy_t *pol;		/* Policy */


        if ((pol = cupsdFindPolicy(value)) != NULL)
	{
          cupsdSetString(&p->op_policy, value);
	  p->op_policy_ptr = pol;
	}
	else
	  cupsdLogMessage(CUPSD_LOG_ERROR,
	                  "Bad policy \"%s\" on line %d of classes.conf",
			  value, linenum);
      }
      else
	cupsdLogMessage(CUPSD_LOG_ERROR,
	                "Syntax error on line %d of classes.conf.", linenum);
    }
    else if (!strcasecmp(line, "ErrorPolicy"))
    {
      if (value)
      {
        if (strcmp(value, "retry-current-job") && strcmp(value, "retry-job"))
	  cupsdLogMessage(CUPSD_LOG_WARN,
	                  "ErrorPolicy %s ignored on line %d of classes.conf",
			  value, linenum);
      }
      else
	cupsdLogMessage(CUPSD_LOG_ERROR,
	                "Syntax error on line %d of classes.conf.", linenum);
    }
    else
    {
     /*
      * Something else we don't understand...
      */

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

  cupsFileClose(fp);
}