コード例 #1
0
ファイル: help-index.c プロジェクト: josephgbr/cups-pt_BR
static help_word_t *			/* O - New word */
help_add_word(help_node_t *n,		/* I - Node */
              const char  *text)	/* I - Word text */
{
  help_word_t	*w,			/* New word */
		key;			/* Search key */


  DEBUG_printf(("2help_add_word(n=%p, text=\"%s\")", n, text));

 /*
  * Create the words array as needed...
  */

  if (!n->words)
    n->words = cupsArrayNew((cups_array_func_t)help_sort_words, NULL);

 /*
  * See if the word is already added...
  */

  key.text = (char *)text;

  if ((w = (help_word_t *)cupsArrayFind(n->words, &key)) == NULL)
  {
   /*
    * Create a new word...
    */

    if ((w = calloc(1, sizeof(help_word_t))) == NULL)
      return (NULL);

    if ((w->text = strdup(text)) == NULL)
    {
      free(w);
      return (NULL);
    }

    cupsArrayAdd(n->words, w);
  }

 /*
  * Bump the counter for this word and return it...
  */

  w->count ++;

  return (w);
}
コード例 #2
0
_pwg_media_t *				/* O - Matching size or NULL */
_pwgMediaForLegacy(
    const char *legacy)			/* I - Legacy size name */
{
  _pwg_media_t	key;			/* Search key */
  _cups_globals_t *cg = _cupsGlobals();	/* Global data */


 /*
  * Range check input...
  */

  if (!legacy)
    return (NULL);

 /*
  * Build the lookup table for PWG names as needed...
  */

  if (!cg->leg_size_lut)
  {
    int			i;		/* Looping var */
    _pwg_media_t	*size;		/* Current size */

    cg->leg_size_lut = cupsArrayNew((cups_array_func_t)pwg_compare_legacy,
                                    NULL);

    for (i = (int)(sizeof(cups_pwg_media) / sizeof(cups_pwg_media[0])),
             size = (_pwg_media_t *)cups_pwg_media;
	 i > 0;
	 i --, size ++)
      if (size->legacy)
	cupsArrayAdd(cg->leg_size_lut, size);
  }

 /*
  * Lookup the name...
  */

  key.legacy = legacy;
  return ((_pwg_media_t *)cupsArrayFind(cg->leg_size_lut, &key));
}
コード例 #3
0
ファイル: dirsvc.c プロジェクト: AndychenCL/cups
static void
dnssdRegisterCallback(
    DNSServiceRef	sdRef,		/* I - DNS Service reference */
    DNSServiceFlags	flags,		/* I - Reserved for future use */
    DNSServiceErrorType	errorCode,	/* I - Error code */
    const char		*name,     	/* I - Service name */
    const char		*regtype,  	/* I - Service type */
    const char		*domain,   	/* I - Domain. ".local" for now */
    void		*context)	/* I - Printer */
{
  cupsd_printer_t *p = (cupsd_printer_t *)context;
					/* Current printer */


  (void)sdRef;
  (void)flags;
  (void)domain;

  cupsdLogMessage(CUPSD_LOG_DEBUG2, "dnssdRegisterCallback(%s, %s) for %s (%s)",
                  name, regtype, p ? p->name : "Web Interface",
		  p ? (p->reg_name ? p->reg_name : "(null)") : "NA");

  if (errorCode)
  {
    cupsdLogMessage(CUPSD_LOG_ERROR,
		    "DNSServiceRegister failed with error %d", (int)errorCode);
    return;
  }
  else if (p && (!p->reg_name || _cups_strcasecmp(name, p->reg_name)))
  {
    cupsdLogMessage(CUPSD_LOG_INFO, "Using service name \"%s\" for \"%s\"",
                    name, p->name);

    cupsArrayRemove(DNSSDPrinters, p);
    cupsdSetString(&p->reg_name, name);
    cupsArrayAdd(DNSSDPrinters, p);

    LastEvent |= CUPSD_EVENT_PRINTER_MODIFIED;
  }
}
コード例 #4
0
static cups_array_t *			/* O - Array of format strings */
collect_formats(const char *id)		/* I - msgid string */
{
  cups_array_t	*fmts;			/* Array of format strings */
  char		buf[255],		/* Format string buffer */
		*bufptr;		/* Pointer into format string */


  fmts = cupsArrayNew(NULL, NULL);

  while ((id = strchr(id, '%')) != NULL)
  {
    if (id[1] == '%')
    {
     /*
      * Skip %%...
      */

      id += 2;
      continue;
    }

    for (bufptr = buf; *id && bufptr < (buf + sizeof(buf) - 1); id ++)
    {
      *bufptr++ = *id;

      if (strchr("CDEFGIOSUXcdeifgopsux", *id))
      {
        id ++;
        break;
      }
    }

    *bufptr = '\0';
    cupsArrayAdd(fmts, strdup(buf));
  }

  return (fmts);
}
コード例 #5
0
static const char *			/* O - Full path to filter or NULL */
mime_add_fcache(
    cups_array_t *filtercache,		/* I - Filter cache */
    const char   *name,			/* I - Filter name */
    const char   *filterpath)		/* I - Filter path */
{
  _mime_fcache_t	key,		/* Search key */
			*temp;		/* New filter cache */
  char			path[1024];	/* Full path to filter */


  DEBUG_printf(("2mime_add_fcache(filtercache=%p, name=\"%s\", "
                "filterpath=\"%s\")", filtercache, name, filterpath));

  key.name = (char *)name;
  if ((temp = (_mime_fcache_t *)cupsArrayFind(filtercache, &key)) != NULL)
  {
    DEBUG_printf(("3mime_add_fcache: Returning \"%s\".", temp->path));
    return (temp->path);
  }

  if ((temp = calloc(1, sizeof(_mime_fcache_t))) == NULL)
  {
    DEBUG_puts("3mime_add_fcache: Returning NULL.");
    return (NULL);
  }

  temp->name = strdup(name);

  if (cupsFileFind(name, filterpath, 1, path, sizeof(path)))
    temp->path = strdup(path);

  cupsArrayAdd(filtercache, temp);

  DEBUG_printf(("3mime_add_fcache: Returning \"%s\".", temp->path));
  return (temp->path);
}
コード例 #6
0
ファイル: testarray.c プロジェクト: jianglei12138/ghostscript
static int				/* O - 1 on success, 0 on failure */
load_words(const char   *filename,	/* I - File to load */
           cups_array_t *array)		/* I - Array to add to */
{
  FILE		*fp;			/* Test file */
  char		word[256];		/* Word from file */


  if ((fp = fopen(filename, "r")) == NULL)
  {
    perror(filename);
    return (0);
  }

  while (fscanf(fp, "%255s", word) == 1)
  {
    if (!cupsArrayFind(array, word))
      cupsArrayAdd(array, strdup(word));
  }

  fclose(fp);

  return (1);
}
コード例 #7
0
ファイル: ppd-localize.c プロジェクト: CODECOMMUNITY/cups
cups_array_t *				/* O - Languages array */
_ppdGetLanguages(ppd_file_t *ppd)	/* I - PPD file */
{
  cups_array_t	*languages;		/* Languages array */
  ppd_attr_t	*attr;			/* cupsLanguages attribute */
  char		*value,			/* Copy of attribute value */
		*start,			/* Start of current language */
		*ptr;			/* Pointer into languages */


 /*
  * See if we have a cupsLanguages attribute...
  */

  if ((attr = ppdFindAttr(ppd, "cupsLanguages", NULL)) == NULL || !attr->value)
    return (NULL);

 /*
  * Yes, load the list...
  */

  if ((languages = cupsArrayNew((cups_array_func_t)strcmp, NULL)) == NULL)
    return (NULL);

  if ((value = strdup(attr->value)) == NULL)
  {
    cupsArrayDelete(languages);
    return (NULL);
  }

  for (ptr = value; *ptr;)
  {
   /*
    * Skip leading whitespace...
    */

    while (_cups_isspace(*ptr))
      ptr ++;

    if (!*ptr)
      break;

   /*
    * Find the end of this language name...
    */

    for (start = ptr; *ptr && !_cups_isspace(*ptr); ptr ++);

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

    if (!strcmp(start, "en"))
      continue;

    cupsArrayAdd(languages, strdup(start));
  }

 /*
  * Free the temporary string and return either an array with one or more
  * values or a NULL pointer...
  */

  free(value);

  if (cupsArrayCount(languages) == 0)
  {
    cupsArrayDelete(languages);
    return (NULL);
  }
  else
    return (languages);
}
コード例 #8
0
ファイル: language.c プロジェクト: jianglei12138/cups
cups_array_t *				/* O - New message array */
_cupsMessageLoad(const char *filename,	/* I - Message catalog to load */
                 int        unquote)	/* I - Unescape \foo in strings? */
{
  cups_file_t		*fp;		/* Message file */
  cups_array_t		*a;		/* Message array */
  _cups_message_t	*m;		/* Current message */
  char			s[4096],	/* String buffer */
			*ptr,		/* Pointer into buffer */
			*temp;		/* New string */
  size_t		length,		/* Length of combined strings */
			ptrlen;		/* Length of string */


  DEBUG_printf(("4_cupsMessageLoad(filename=\"%s\")", filename));

 /*
  * Create an array to hold the messages...
  */

  if ((a = _cupsMessageNew(NULL)) == NULL)
  {
    DEBUG_puts("5_cupsMessageLoad: Unable to allocate array!");
    return (NULL);
  }

 /*
  * Open the message catalog file...
  */

  if ((fp = cupsFileOpen(filename, "r")) == NULL)
  {
    DEBUG_printf(("5_cupsMessageLoad: Unable to open file: %s",
                  strerror(errno)));
    return (a);
  }

 /*
  * Read messages from the catalog file until EOF...
  *
  * The format is the GNU gettext .po format, which is fairly simple:
  *
  *     msgid "some text"
  *     msgstr "localized text"
  *
  * The ID and localized text can span multiple lines using the form:
  *
  *     msgid ""
  *     "some long text"
  *     msgstr ""
  *     "localized text spanning "
  *     "multiple lines"
  */

  m = NULL;

  while (cupsFileGets(fp, s, sizeof(s)) != NULL)
  {
   /*
    * Skip blank and comment lines...
    */

    if (s[0] == '#' || !s[0])
      continue;

   /*
    * Strip the trailing quote...
    */

    if ((ptr = strrchr(s, '\"')) == NULL)
      continue;

    *ptr = '\0';

   /*
    * Find start of value...
    */

    if ((ptr = strchr(s, '\"')) == NULL)
      continue;

    ptr ++;

   /*
    * Unquote the text...
    */

    if (unquote)
      cups_unquote(ptr, ptr);

   /*
    * Create or add to a message...
    */

    if (!strncmp(s, "msgid", 5))
    {
     /*
      * Add previous message as needed...
      */

      if (m)
      {
        if (m->str && m->str[0])
        {
          cupsArrayAdd(a, m);
        }
        else
        {
         /*
          * Translation is empty, don't add it... (STR #4033)
          */

          free(m->id);
          if (m->str)
            free(m->str);
          free(m);
        }
      }

     /*
      * Create a new message with the given msgid string...
      */

      if ((m = (_cups_message_t *)calloc(1, sizeof(_cups_message_t))) == NULL)
      {
        cupsFileClose(fp);
	return (a);
      }

      if ((m->id = strdup(ptr)) == NULL)
      {
        free(m);
        cupsFileClose(fp);
	return (a);
      }
    }
    else if (s[0] == '\"' && m)
    {
     /*
      * Append to current string...
      */

      length = strlen(m->str ? m->str : m->id);
      ptrlen = strlen(ptr);

      if ((temp = realloc(m->str ? m->str : m->id, length + ptrlen + 1)) == NULL)
      {
        if (m->str)
	  free(m->str);
	free(m->id);
        free(m);

	cupsFileClose(fp);
	return (a);
      }

      if (m->str)
      {
       /*
        * Copy the new portion to the end of the msgstr string - safe
	* to use memcpy because the buffer is allocated to the correct
	* size...
	*/

        m->str = temp;

	memcpy(m->str + length, ptr, ptrlen + 1);
      }
      else
      {
       /*
        * Copy the new portion to the end of the msgid string - safe
	* to use memcpy because the buffer is allocated to the correct
	* size...
	*/

        m->id = temp;

	memcpy(m->id + length, ptr, ptrlen + 1);
      }
    }
    else if (!strncmp(s, "msgstr", 6) && m)
    {
     /*
      * Set the string...
      */

      if ((m->str = strdup(ptr)) == NULL)
      {
	free(m->id);
        free(m);

        cupsFileClose(fp);
	return (a);
      }
    }
  }

 /*
  * Add the last message string to the array as needed...
  */

  if (m)
  {
    if (m->str && m->str[0])
    {
      cupsArrayAdd(a, m);
    }
    else
    {
     /*
      * Translation is empty, don't add it... (STR #4033)
      */

      free(m->id);
      if (m->str)
	free(m->str);
      free(m);
    }
  }

 /*
  * Close the message catalog file and return the new array...
  */

  cupsFileClose(fp);

  DEBUG_printf(("5_cupsMessageLoad: Returning %d messages...",
                cupsArrayCount(a)));

  return (a);
}
コード例 #9
0
ファイル: ppd-conflicts.c プロジェクト: Cacauu/cups
static cups_array_t *			/* O - Array of active constraints */
ppd_test_constraints(
    ppd_file_t    *ppd,			/* I - PPD file */
    const char    *option,		/* I - Current option */
    const char    *choice,		/* I - Current choice */
    int           num_options,		/* I - Number of additional options */
    cups_option_t *options,		/* I - Additional options */
    int           which)		/* I - Which constraints to test */
{
  int			i;		/* Looping var */
  _ppd_cups_uiconsts_t	*consts;	/* Current constraints */
  _ppd_cups_uiconst_t	*constptr;	/* Current constraint */
  ppd_choice_t		key,		/* Search key */
			*marked;	/* Marked choice */
  cups_array_t		*active = NULL;	/* Active constraints */
  const char		*value,		/* Current value */
			*firstvalue;	/* AP_FIRSTPAGE_Keyword value */
  char			firstpage[255];	/* AP_FIRSTPAGE_Keyword string */


  DEBUG_printf(("7ppd_test_constraints(ppd=%p, option=\"%s\", choice=\"%s\", "
                "num_options=%d, options=%p, which=%d)", ppd, option, choice,
		num_options, options, which));

  if (!ppd->cups_uiconstraints)
    ppd_load_constraints(ppd);

  DEBUG_printf(("9ppd_test_constraints: %d constraints!",
	        cupsArrayCount(ppd->cups_uiconstraints)));

  cupsArraySave(ppd->marked);

  for (consts = (_ppd_cups_uiconsts_t *)cupsArrayFirst(ppd->cups_uiconstraints);
       consts;
       consts = (_ppd_cups_uiconsts_t *)cupsArrayNext(ppd->cups_uiconstraints))
  {
    DEBUG_printf(("9ppd_test_constraints: installable=%d, resolver=\"%s\", "
                  "num_constraints=%d option1=\"%s\", choice1=\"%s\", "
		  "option2=\"%s\", choice2=\"%s\", ...",
		  consts->installable, consts->resolver, consts->num_constraints,
		  consts->constraints[0].option->keyword,
		  consts->constraints[0].choice ?
		      consts->constraints[0].choice->choice : "",
		  consts->constraints[1].option->keyword,
		  consts->constraints[1].choice ?
		      consts->constraints[1].choice->choice : ""));

    if (consts->installable && which < _PPD_INSTALLABLE_CONSTRAINTS)
      continue;				/* Skip installable option constraint */

    if (!consts->installable && which == _PPD_INSTALLABLE_CONSTRAINTS)
      continue;				/* Skip non-installable option constraint */

    if (which == _PPD_OPTION_CONSTRAINTS && option)
    {
     /*
      * Skip constraints that do not involve the current option...
      */

      for (i = consts->num_constraints, constptr = consts->constraints;
	   i > 0;
	   i --, constptr ++)
      {
        if (!_cups_strcasecmp(constptr->option->keyword, option))
	  break;

        if (!_cups_strncasecmp(option, "AP_FIRSTPAGE_", 13) &&
	    !_cups_strcasecmp(constptr->option->keyword, option + 13))
	  break;
      }

      if (!i)
        continue;
    }

    DEBUG_puts("9ppd_test_constraints: Testing...");

    for (i = consts->num_constraints, constptr = consts->constraints;
         i > 0;
	 i --, constptr ++)
    {
      DEBUG_printf(("9ppd_test_constraints: %s=%s?", constptr->option->keyword,
		    constptr->choice ? constptr->choice->choice : ""));

      if (constptr->choice &&
          (!_cups_strcasecmp(constptr->option->keyword, "PageSize") ||
           !_cups_strcasecmp(constptr->option->keyword, "PageRegion")))
      {
       /*
        * PageSize and PageRegion are used depending on the selected input slot
	* and manual feed mode.  Validate against the selected page size instead
	* of an individual option...
	*/

        if (option && choice &&
	    (!_cups_strcasecmp(option, "PageSize") ||
	     !_cups_strcasecmp(option, "PageRegion")))
	{
	  value = choice;
        }
	else if ((value = cupsGetOption("PageSize", num_options,
	                                options)) == NULL)
	  if ((value = cupsGetOption("PageRegion", num_options,
	                             options)) == NULL)
	    if ((value = cupsGetOption("media", num_options, options)) == NULL)
	    {
	      ppd_size_t *size = ppdPageSize(ppd, NULL);

              if (size)
	        value = size->name;
	    }

        if (value && !_cups_strncasecmp(value, "Custom.", 7))
	  value = "Custom";

        if (option && choice &&
	    (!_cups_strcasecmp(option, "AP_FIRSTPAGE_PageSize") ||
	     !_cups_strcasecmp(option, "AP_FIRSTPAGE_PageRegion")))
	{
	  firstvalue = choice;
        }
	else if ((firstvalue = cupsGetOption("AP_FIRSTPAGE_PageSize",
	                                     num_options, options)) == NULL)
	  firstvalue = cupsGetOption("AP_FIRSTPAGE_PageRegion", num_options,
	                             options);

        if (firstvalue && !_cups_strncasecmp(firstvalue, "Custom.", 7))
	  firstvalue = "Custom";

        if ((!value || _cups_strcasecmp(value, constptr->choice->choice)) &&
	    (!firstvalue || _cups_strcasecmp(firstvalue, constptr->choice->choice)))
	{
	  DEBUG_puts("9ppd_test_constraints: NO");
	  break;
	}
      }
      else if (constptr->choice)
      {
       /*
        * Compare against the constrained choice...
	*/

        if (option && choice && !_cups_strcasecmp(option, constptr->option->keyword))
	{
	  if (!_cups_strncasecmp(choice, "Custom.", 7))
	    value = "Custom";
	  else
	    value = choice;
	}
        else if ((value = cupsGetOption(constptr->option->keyword, num_options,
	                                options)) != NULL)
        {
	  if (!_cups_strncasecmp(value, "Custom.", 7))
	    value = "Custom";
	}
        else if (constptr->choice->marked)
	  value = constptr->choice->choice;
	else
	  value = NULL;

       /*
        * Now check AP_FIRSTPAGE_option...
	*/

        snprintf(firstpage, sizeof(firstpage), "AP_FIRSTPAGE_%s",
	         constptr->option->keyword);

        if (option && choice && !_cups_strcasecmp(option, firstpage))
	{
	  if (!_cups_strncasecmp(choice, "Custom.", 7))
	    firstvalue = "Custom";
	  else
	    firstvalue = choice;
	}
        else if ((firstvalue = cupsGetOption(firstpage, num_options,
	                                     options)) != NULL)
        {
	  if (!_cups_strncasecmp(firstvalue, "Custom.", 7))
	    firstvalue = "Custom";
	}
	else
	  firstvalue = NULL;

        DEBUG_printf(("9ppd_test_constraints: value=%s, firstvalue=%s", value,
	              firstvalue));

        if ((!value || _cups_strcasecmp(value, constptr->choice->choice)) &&
	    (!firstvalue || _cups_strcasecmp(firstvalue, constptr->choice->choice)))
	{
	  DEBUG_puts("9ppd_test_constraints: NO");
	  break;
	}
      }
      else if (option && choice &&
               !_cups_strcasecmp(option, constptr->option->keyword))
      {
	if (!_cups_strcasecmp(choice, "None") || !_cups_strcasecmp(choice, "Off") ||
	    !_cups_strcasecmp(choice, "False"))
	{
	  DEBUG_puts("9ppd_test_constraints: NO");
	  break;
	}
      }
      else if ((value = cupsGetOption(constptr->option->keyword, num_options,
				      options)) != NULL)
      {
	if (!_cups_strcasecmp(value, "None") || !_cups_strcasecmp(value, "Off") ||
	    !_cups_strcasecmp(value, "False"))
	{
	  DEBUG_puts("9ppd_test_constraints: NO");
	  break;
	}
      }
      else
      {
	key.option = constptr->option;

	if ((marked = (ppd_choice_t *)cupsArrayFind(ppd->marked, &key))
		== NULL ||
	    (!_cups_strcasecmp(marked->choice, "None") ||
	     !_cups_strcasecmp(marked->choice, "Off") ||
	     !_cups_strcasecmp(marked->choice, "False")))
	{
	  DEBUG_puts("9ppd_test_constraints: NO");
	  break;
	}
      }
    }

    if (i <= 0)
    {
      if (!active)
        active = cupsArrayNew(NULL, NULL);

      cupsArrayAdd(active, consts);
      DEBUG_puts("9ppd_test_constraints: Added...");
    }
  }

  cupsArrayRestore(ppd->marked);

  DEBUG_printf(("8ppd_test_constraints: Found %d active constraints!",
                cupsArrayCount(active)));

  return (active);
}
コード例 #10
0
ファイル: dnssd.c プロジェクト: zdohnal/cups
static cups_device_t *			/* O - Device */
get_device(cups_array_t *devices,	/* I - Device array */
           const char   *serviceName,	/* I - Name of service/device */
           const char   *regtype,	/* I - Type of service */
           const char   *replyDomain)	/* I - Service domain */
{
  cups_device_t	key,			/* Search key */
		*device;		/* Device */
  char		fullName[kDNSServiceMaxDomainName];
					/* Full name for query */


 /*
  * See if this is a new device...
  */

  key.name = (char *)serviceName;
  key.type = device_type(regtype);

  for (device = cupsArrayFind(devices, &key);
       device;
       device = cupsArrayNext(devices))
    if (_cups_strcasecmp(device->name, key.name))
      break;
    else if (device->type == key.type)
    {
      if (!_cups_strcasecmp(device->domain, "local.") &&
          _cups_strcasecmp(device->domain, replyDomain))
      {
       /*
        * Update the .local listing to use the "global" domain name instead.
	* The backend will try local lookups first, then the global domain name.
	*/

        free(device->domain);
	device->domain = strdup(replyDomain);

#ifdef HAVE_DNSSD
	DNSServiceConstructFullName(fullName, device->name, regtype,
	                            replyDomain);
#else /* HAVE_AVAHI */
	avahi_service_name_join(fullName, kDNSServiceMaxDomainName,
				serviceName, regtype, replyDomain);
#endif /* HAVE_DNSSD */

	free(device->fullName);
	device->fullName = strdup(fullName);
      }

      return (device);
    }

 /*
  * Yes, add the device...
  */

  device           = calloc(sizeof(cups_device_t), 1);
  device->name     = strdup(serviceName);
  device->domain   = strdup(replyDomain);
  device->type     = key.type;
  device->priority = 50;

  cupsArrayAdd(devices, device);

 /*
  * Set the "full name" of this service, which is used for queries...
  */

#ifdef HAVE_DNSSD
  DNSServiceConstructFullName(fullName, serviceName, regtype, replyDomain);
#else /* HAVE_AVAHI */
  avahi_service_name_join(fullName, kDNSServiceMaxDomainName, serviceName, regtype, replyDomain);
#endif /* HAVE_DNSSD */

  device->fullName = strdup(fullName);

  return (device);
}
コード例 #11
0
static void
cups_create_localizations(
    http_t       *http,			/* I - Connection to destination */
    cups_dinfo_t *dinfo)		/* I - Destination informations */
{
  http_t		*http2;		/* Connection for strings file */
  http_status_t		status;		/* Request status */
  ipp_attribute_t	*attr;		/* "printer-strings-uri" attribute */
  char			scheme[32],	/* URI scheme */
  			userpass[256],	/* Username/password info */
  			hostname[256],	/* Hostname */
  			resource[1024],	/* Resource */
  			http_hostname[256],
  					/* Hostname of connection */
			tempfile[1024];	/* Temporary filename */
  int			port;		/* Port number */
  http_encryption_t	encryption;	/* Encryption to use */
  cups_file_t		*temp;		/* Temporary file */


 /*
  * Create an empty message catalog...
  */

  dinfo->localizations = _cupsMessageNew(NULL);

 /*
  * See if there are any localizations...
  */

  if ((attr = ippFindAttribute(dinfo->attrs, "printer-strings-uri",
                               IPP_TAG_URI)) == NULL)
  {
   /*
    * Nope...
    */

    DEBUG_puts("4cups_create_localizations: No printer-strings-uri (uri) "
               "value.");
    return;				/* Nope */
  }

 /*
  * Pull apart the URI and determine whether we need to try a different
  * server...
  */

  if (httpSeparateURI(HTTP_URI_CODING_ALL, attr->values[0].string.text,
                      scheme, sizeof(scheme), userpass, sizeof(userpass),
                      hostname, sizeof(hostname), &port, resource,
                      sizeof(resource)) < HTTP_URI_OK)
  {
    DEBUG_printf(("4cups_create_localizations: Bad printer-strings-uri value "
                  "\"%s\".", attr->values[0].string.text));
    return;
  }

  httpGetHostname(http, http_hostname, sizeof(http_hostname));

  if (!_cups_strcasecmp(http_hostname, hostname) &&
      port == _httpAddrPort(http->hostaddr))
  {
   /*
    * Use the same connection...
    */

    http2 = http;
  }
  else
  {
   /*
    * Connect to the alternate host...
    */

    if (!strcmp(scheme, "https"))
      encryption = HTTP_ENCRYPT_ALWAYS;
    else
      encryption = HTTP_ENCRYPT_IF_REQUESTED;

    if ((http2 = httpConnectEncrypt(hostname, port, encryption)) == NULL)
    {
      DEBUG_printf(("4cups_create_localizations: Unable to connect to "
                    "%s:%d: %s", hostname, port, cupsLastErrorString()));
      return;
    }
  }

 /*
  * Get a temporary file...
  */

  if ((temp = cupsTempFile2(tempfile, sizeof(tempfile))) == NULL)
  {
    DEBUG_printf(("4cups_create_localizations: Unable to create temporary "
                  "file: %s", cupsLastErrorString()));
    if (http2 != http)
      httpClose(http2);
    return;
  }

  status = cupsGetFd(http2, resource, cupsFileNumber(temp));

  DEBUG_printf(("4cups_create_localizations: GET %s = %s", resource,
                httpStatus(status)));

  if (status == HTTP_OK)
  {
   /*
    * Got the file, read it...
    */

    char		buffer[8192],	/* Message buffer */
    			*id,		/* ID string */
    			*str;		/* Translated message */
    _cups_message_t	*m;		/* Current message */

    lseek(cupsFileNumber(temp), 0, SEEK_SET);

    while (cups_read_strings(temp, buffer, sizeof(buffer), &id, &str))
    {
      if ((m = malloc(sizeof(_cups_message_t))) == NULL)
        break;

      m->id  = strdup(id);
      m->str = strdup(str);

      if (m->id && m->str)
        cupsArrayAdd(dinfo->localizations, m);
      else
      {
        if (m->id)
          free(m->id);

        if (m->str)
          free(m->str);

        free(m);
        break;
      }
    }
  }

  DEBUG_printf(("4cups_create_localizations: %d messages loaded.",
                cupsArrayCount(dinfo->localizations)));

 /*
  * Cleanup...
  */

  unlink(tempfile);
  cupsFileClose(temp);

  if (http2 != http)
    httpClose(http2);
}
コード例 #12
0
ファイル: help-index.c プロジェクト: josephgbr/cups-pt_BR
help_index_t *				/* O - Index pointer or NULL */
helpLoadIndex(const char *hifile,	/* I - Index filename */
              const char *directory)	/* I - Directory that is indexed */
{
  help_index_t	*hi;			/* Help index */
  cups_file_t	*fp;			/* Current file */
  char		line[2048],		/* Line from file */
		*ptr,			/* Pointer into line */
		*filename,		/* Filename in line */
		*anchor,		/* Anchor in line */
		*sectptr,		/* Section pointer in line */
		section[1024],		/* Section name */
		*text;			/* Text in line */
  time_t	mtime;			/* Modification time */
  off_t		offset;			/* Offset into file */
  size_t	length;			/* Length in bytes */
  int		update;			/* Update? */
  help_node_t	*node;			/* Current node */
  help_word_t	*word;			/* Current word */


  DEBUG_printf(("helpLoadIndex(hifile=\"%s\", directory=\"%s\")",
                hifile, directory));

 /*
  * Create a new, empty index.
  */

  if ((hi = (help_index_t *)calloc(1, sizeof(help_index_t))) == NULL)
    return (NULL);

  hi->nodes  = cupsArrayNew((cups_array_func_t)help_sort_by_name, NULL);
  hi->sorted = cupsArrayNew((cups_array_func_t)help_sort_by_score, NULL);

  if (!hi->nodes || !hi->sorted)
  {
    cupsArrayDelete(hi->nodes);
    cupsArrayDelete(hi->sorted);
    free(hi);
    return (NULL);
  }

 /*
  * Try loading the existing index file...
  */

  if ((fp = cupsFileOpen(hifile, "r")) != NULL)
  {
   /*
    * Lock the file and then read the first line...
    */

    cupsFileLock(fp, 1);

    if (cupsFileGets(fp, line, sizeof(line)) && !strcmp(line, "HELPV2"))
    {
     /*
      * Got a valid header line, now read the data lines...
      */

      node = NULL;

      while (cupsFileGets(fp, line, sizeof(line)))
      {
       /*
	* Each line looks like one of the following:
	*
	*     filename mtime offset length "section" "text"
	*     filename#anchor offset length "text"
	*     SP count word
	*/

        if (line[0] == ' ')
	{
	 /*
	  * Read a word in the current node...
	  */

          if (!node || (ptr = strrchr(line, ' ')) == NULL)
	    continue;

          if ((word = help_add_word(node, ptr + 1)) != NULL)
	    word->count = atoi(line + 1);
        }
	else
	{
	 /*
	  * Add a node...
	  */

	  filename = line;

	  if ((ptr = strchr(line, ' ')) == NULL)
            break;

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

	  if ((anchor = strrchr(filename, '#')) != NULL)
	  {
            *anchor++ = '\0';
	    mtime = 0;
	  }
	  else
	    mtime = strtol(ptr, &ptr, 10);

	  offset = strtoll(ptr, &ptr, 10);
	  length = strtoll(ptr, &ptr, 10);

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

          if (!anchor)
	  {
	   /*
	    * Get section...
	    */

            if (*ptr != '\"')
	      break;

            ptr ++;
	    sectptr = ptr;

            while (*ptr && *ptr != '\"')
	      ptr ++;

            if (*ptr != '\"')
	      break;

            *ptr++ = '\0';

            strlcpy(section, sectptr, sizeof(section));

	    while (isspace(*ptr & 255))
              ptr ++;
          }

          if (*ptr != '\"')
	    break;

          ptr ++;
	  text = ptr;

          while (*ptr && *ptr != '\"')
	    ptr ++;

          if (*ptr != '\"')
	    break;

          *ptr++ = '\0';

	  if ((node = help_new_node(filename, anchor, section, text,
				    mtime, offset, length)) == NULL)
            break;

	  node->score = -1;

	  cupsArrayAdd(hi->nodes, node);
        }
      }
    }

    cupsFileClose(fp);
  }

 /*
  * Scan for new/updated files...
  */

  update = help_load_directory(hi, directory, NULL);

 /*
  * Remove any files that are no longer installed...
  */

  for (node = (help_node_t *)cupsArrayFirst(hi->nodes);
       node;
       node = (help_node_t *)cupsArrayNext(hi->nodes))
    if (node->score < 0)
    {
     /*
      * Delete this node...
      */

      cupsArrayRemove(hi->nodes, node);
      help_delete_node(node);
    }

 /*
  * Add nodes to the sorted array...
  */

  for (node = (help_node_t *)cupsArrayFirst(hi->nodes);
       node;
       node = (help_node_t *)cupsArrayNext(hi->nodes))
    cupsArrayAdd(hi->sorted, node);

 /*
  * Save the index if we updated it...
  */

  if (update)
    helpSaveIndex(hi, hifile);

 /*
  * Return the index...
  */

  return (hi);
}
コード例 #13
0
ファイル: testarray.c プロジェクト: jianglei12138/ghostscript
int					/* O - Exit status */
main(int  argc,				/* I - Number of command-line arguments */
     char *argv[])			/* I - Command-line arguments */
{
  int		i;			/* Looping var */
  cups_array_t	*array,			/* Test array */
		*dup_array;		/* Duplicate array */
  int		status;			/* Exit status */
  char		*text;			/* Text from array */
  char		word[256];		/* Word from file */
  double	start,			/* Start time */
		end;			/* End time */
  cups_dir_t	*dir;			/* Current directory */
  cups_dentry_t	*dent;			/* Directory entry */
  char		*saved[32];		/* Saved entries */
  void		*data;			/* User data for arrays */


 /*
  * No errors so far...
  */

  status = 0;

 /*
  * cupsArrayNew()
  */

  fputs("cupsArrayNew: ", stdout);

  data  = (void *)"testarray";
  array = cupsArrayNew((cups_array_func_t)strcmp, data);

  if (array)
    puts("PASS");
  else
  {
    puts("FAIL (returned NULL, expected pointer)");
    status ++;
  }

 /*
  * cupsArrayUserData()
  */

  fputs("cupsArrayUserData: ", stdout);
  if (cupsArrayUserData(array) == data)
    puts("PASS");
  else
  {
    printf("FAIL (returned %p instead of %p!)\n", cupsArrayUserData(array),
           data);
    status ++;
  }

 /*
  * cupsArrayAdd()
  */

  fputs("cupsArrayAdd: ", stdout);

  if (!cupsArrayAdd(array, strdup("One Fish")))
  {
    puts("FAIL (\"One Fish\")");
    status ++;
  }
  else
  {
    if (!cupsArrayAdd(array, strdup("Two Fish")))
    {
      puts("FAIL (\"Two Fish\")");
      status ++;
    }
    else
    {
      if (!cupsArrayAdd(array, strdup("Red Fish")))
      {
	puts("FAIL (\"Red Fish\")");
	status ++;
      }
      else
      {
        if (!cupsArrayAdd(array, strdup("Blue Fish")))
	{
	  puts("FAIL (\"Blue Fish\")");
	  status ++;
	}
	else
	  puts("PASS");
      }
    }
  }

 /*
  * cupsArrayCount()
  */

  fputs("cupsArrayCount: ", stdout);
  if (cupsArrayCount(array) == 4)
    puts("PASS");
  else
  {
    printf("FAIL (returned %d, expected 4)\n", cupsArrayCount(array));
    status ++;
  }

 /*
  * cupsArrayFirst()
  */

  fputs("cupsArrayFirst: ", stdout);
  if ((text = (char *)cupsArrayFirst(array)) != NULL &&
      !strcmp(text, "Blue Fish"))
    puts("PASS");
  else
  {
    printf("FAIL (returned \"%s\", expected \"Blue Fish\")\n", text);
    status ++;
  }

 /*
  * cupsArrayNext()
  */

  fputs("cupsArrayNext: ", stdout);
  if ((text = (char *)cupsArrayNext(array)) != NULL &&
      !strcmp(text, "One Fish"))
    puts("PASS");
  else
  {
    printf("FAIL (returned \"%s\", expected \"One Fish\")\n", text);
    status ++;
  }

 /*
  * cupsArrayLast()
  */

  fputs("cupsArrayLast: ", stdout);
  if ((text = (char *)cupsArrayLast(array)) != NULL &&
      !strcmp(text, "Two Fish"))
    puts("PASS");
  else
  {
    printf("FAIL (returned \"%s\", expected \"Two Fish\")\n", text);
    status ++;
  }

 /*
  * cupsArrayPrev()
  */

  fputs("cupsArrayPrev: ", stdout);
  if ((text = (char *)cupsArrayPrev(array)) != NULL &&
      !strcmp(text, "Red Fish"))
    puts("PASS");
  else
  {
    printf("FAIL (returned \"%s\", expected \"Red Fish\")\n", text);
    status ++;
  }

 /*
  * cupsArrayFind()
  */

  fputs("cupsArrayFind: ", stdout);
  if ((text = (char *)cupsArrayFind(array, (void *)"One Fish")) != NULL &&
      !strcmp(text, "One Fish"))
    puts("PASS");
  else
  {
    printf("FAIL (returned \"%s\", expected \"One Fish\")\n", text);
    status ++;
  }

 /*
  * cupsArrayCurrent()
  */

  fputs("cupsArrayCurrent: ", stdout);
  if ((text = (char *)cupsArrayCurrent(array)) != NULL &&
      !strcmp(text, "One Fish"))
    puts("PASS");
  else
  {
    printf("FAIL (returned \"%s\", expected \"One Fish\")\n", text);
    status ++;
  }

 /*
  * cupsArrayDup()
  */

  fputs("cupsArrayDup: ", stdout);
  if ((dup_array = cupsArrayDup(array)) != NULL &&
      cupsArrayCount(dup_array) == 4)
    puts("PASS");
  else
  {
    printf("FAIL (returned %p with %d elements, expected pointer with 4 elements)\n",
           dup_array, cupsArrayCount(dup_array));
    status ++;
  }

 /*
  * cupsArrayRemove()
  */

  fputs("cupsArrayRemove: ", stdout);
  if (cupsArrayRemove(array, (void *)"One Fish") &&
      cupsArrayCount(array) == 3)
    puts("PASS");
  else
  {
    printf("FAIL (returned 0 with %d elements, expected 1 with 4 elements)\n",
           cupsArrayCount(array));
    status ++;
  }

 /*
  * cupsArrayClear()
  */

  fputs("cupsArrayClear: ", stdout);
  cupsArrayClear(array);
  if (cupsArrayCount(array) == 0)
    puts("PASS");
  else
  {
    printf("FAIL (%d elements, expected 0 elements)\n",
           cupsArrayCount(array));
    status ++;
  }

 /*
  * Now load this source file and grab all of the unique words...
  */

  fputs("Load unique words: ", stdout);
  fflush(stdout);

  start = get_seconds();

  if ((dir = cupsDirOpen(".")) == NULL)
  {
    puts("FAIL (cupsDirOpen failed)");
    status ++;
  }
  else
  {
    while ((dent = cupsDirRead(dir)) != NULL)
    {
      i = strlen(dent->filename) - 2;

      if (i > 0 && dent->filename[i] == '.' &&
          (dent->filename[i + 1] == 'c' ||
	   dent->filename[i + 1] == 'h'))
	load_words(dent->filename, array);
    }

    cupsDirClose(dir);

    end = get_seconds();

    printf("%d words in %.3f seconds (%.0f words/sec), ", cupsArrayCount(array),
           end - start, cupsArrayCount(array) / (end - start));
    fflush(stdout);

    for (text = (char *)cupsArrayFirst(array); text;)
    {
     /*
      * Copy this word to the word buffer (safe because we strdup'd from
      * the same buffer in the first place... :)
      */

      strlcpy(word, text, sizeof(word));

     /*
      * Grab the next word and compare...
      */

      if ((text = (char *)cupsArrayNext(array)) == NULL)
	break;

      if (strcmp(word, text) >= 0)
	break;
    }

    if (text)
    {
      printf("FAIL (\"%s\" >= \"%s\"!)\n", word, text);
      status ++;
    }
    else
      puts("PASS");
  }

 /*
  * Test deleting with iteration...
  */

  fputs("Delete While Iterating: ", stdout);

  text = (char *)cupsArrayFirst(array);
  cupsArrayRemove(array, text);
  free(text);

  text = (char *)cupsArrayNext(array);
  if (!text)
  {
    puts("FAIL (cupsArrayNext returned NULL!)");
    status ++;
  }
  else
    puts("PASS");

 /*
  * Test save/restore...
  */

  fputs("cupsArraySave: ", stdout);

  for (i = 0, text = (char *)cupsArrayFirst(array);
       i < 32;
       i ++, text = (char *)cupsArrayNext(array))
  {
    saved[i] = text;

    if (!cupsArraySave(array))
      break;
  }

  if (i < 32)
    printf("FAIL (depth = %d)\n", i);
  else
    puts("PASS");

  fputs("cupsArrayRestore: ", stdout);

  while (i > 0)
  {
    i --;

    text = cupsArrayRestore(array);
    if (text != saved[i])
      break;
  }

  if (i)
    printf("FAIL (depth = %d)\n", i);
  else
    puts("PASS");

 /*
  * Delete the arrays...
  */

  cupsArrayDelete(array);
  cupsArrayDelete(dup_array);

 /*
  * Test the array with string functions...
  */

  fputs("_cupsArrayNewStrings(\" \\t\\nfoo bar\\tboo\\nfar\", ' '): ", stdout);
  array = _cupsArrayNewStrings(" \t\nfoo bar\tboo\nfar", ' ');
  if (!array)
  {
    status = 1;
    puts("FAIL (unable to create array)");
  }
  else if (cupsArrayCount(array) != 4)
  {
    status = 1;
    printf("FAIL (got %d elements, expected 4)\n", cupsArrayCount(array));
  }
  else if (strcmp(text = (char *)cupsArrayFirst(array), "bar"))
  {
    status = 1;
    printf("FAIL (first element \"%s\", expected \"bar\")\n", text);
  }
  else if (strcmp(text = (char *)cupsArrayNext(array), "boo"))
  {
    status = 1;
    printf("FAIL (first element \"%s\", expected \"boo\")\n", text);
  }
  else if (strcmp(text = (char *)cupsArrayNext(array), "far"))
  {
    status = 1;
    printf("FAIL (first element \"%s\", expected \"far\")\n", text);
  }
  else if (strcmp(text = (char *)cupsArrayNext(array), "foo"))
  {
    status = 1;
    printf("FAIL (first element \"%s\", expected \"foo\")\n", text);
  }
  else
    puts("PASS");

  fputs("_cupsArrayAddStrings(array, \"foo2,bar2\", ','): ", stdout);
  _cupsArrayAddStrings(array, "foo2,bar2", ',');

  if (cupsArrayCount(array) != 6)
  {
    status = 1;
    printf("FAIL (got %d elements, expected 6)\n", cupsArrayCount(array));
  }
  else if (strcmp(text = (char *)cupsArrayFirst(array), "bar"))
  {
    status = 1;
    printf("FAIL (first element \"%s\", expected \"bar\")\n", text);
  }
  else if (strcmp(text = (char *)cupsArrayNext(array), "bar2"))
  {
    status = 1;
    printf("FAIL (first element \"%s\", expected \"bar2\")\n", text);
  }
  else if (strcmp(text = (char *)cupsArrayNext(array), "boo"))
  {
    status = 1;
    printf("FAIL (first element \"%s\", expected \"boo\")\n", text);
  }
  else if (strcmp(text = (char *)cupsArrayNext(array), "far"))
  {
    status = 1;
    printf("FAIL (first element \"%s\", expected \"far\")\n", text);
  }
  else if (strcmp(text = (char *)cupsArrayNext(array), "foo"))
  {
    status = 1;
    printf("FAIL (first element \"%s\", expected \"foo\")\n", text);
  }
  else if (strcmp(text = (char *)cupsArrayNext(array), "foo2"))
  {
    status = 1;
    printf("FAIL (first element \"%s\", expected \"foo2\")\n", text);
  }
  else
    puts("PASS");

  cupsArrayDelete(array);

 /*
  * Summarize the results and return...
  */

  if (!status)
    puts("\nALL TESTS PASSED!");
  else
    printf("\n%d TEST(S) FAILED!\n", status);

  return (status);
}
コード例 #14
0
ファイル: subscriptions.c プロジェクト: aosm/cups
cupsd_subscription_t *			/* O - New subscription object */
cupsdAddSubscription(
    unsigned        mask,		/* I - Event mask */
    cupsd_printer_t *dest,		/* I - Printer, if any */
    cupsd_job_t     *job,		/* I - Job, if any */
    const char      *uri,		/* I - notify-recipient-uri, if any */
    int             sub_id)		/* I - notify-subscription-id or 0 */
{
  cupsd_subscription_t	*temp;		/* New subscription object */


  cupsdLogMessage(CUPSD_LOG_DEBUG,
                  "cupsdAddSubscription(mask=%x, dest=%p(%s), job=%p(%d), "
		  "uri=\"%s\")",
                  mask, dest, dest ? dest->name : "", job, job ? job->id : 0,
		  uri ? uri : "(null)");

  if (!Subscriptions)
    Subscriptions = cupsArrayNew((cups_array_func_t)cupsd_compare_subscriptions,
                                 NULL);

  if (!Subscriptions)
  {
    cupsdLogMessage(CUPSD_LOG_CRIT,
                    "Unable to allocate memory for subscriptions - %s",
        	    strerror(errno));
    return (NULL);
  }

 /*
  * Limit the number of subscriptions...
  */

  if (MaxSubscriptions > 0 && cupsArrayCount(Subscriptions) >= MaxSubscriptions)
  {
    cupsdLogMessage(CUPSD_LOG_DEBUG,
                    "cupsdAddSubscription: Reached MaxSubscriptions %d "
		    "(count=%d)", MaxSubscriptions,
		    cupsArrayCount(Subscriptions));
    return (NULL);
  }

  if (MaxSubscriptionsPerJob > 0 && job)
  {
    int	count;				/* Number of job subscriptions */

    for (temp = (cupsd_subscription_t *)cupsArrayFirst(Subscriptions),
             count = 0;
         temp;
	 temp = (cupsd_subscription_t *)cupsArrayNext(Subscriptions))
      if (temp->job == job)
        count ++;

    if (count >= MaxSubscriptionsPerJob)
    {
      cupsdLogMessage(CUPSD_LOG_DEBUG,
		      "cupsdAddSubscription: Reached MaxSubscriptionsPerJob %d "
		      "for job #%d (count=%d)", MaxSubscriptionsPerJob,
		      job->id, count);
      return (NULL);
    }
  }

  if (MaxSubscriptionsPerPrinter > 0 && dest)
  {
    int	count;				/* Number of printer subscriptions */

    for (temp = (cupsd_subscription_t *)cupsArrayFirst(Subscriptions),
             count = 0;
         temp;
	 temp = (cupsd_subscription_t *)cupsArrayNext(Subscriptions))
      if (temp->dest == dest)
        count ++;

    if (count >= MaxSubscriptionsPerPrinter)
    {
      cupsdLogMessage(CUPSD_LOG_DEBUG,
		      "cupsdAddSubscription: Reached "
		      "MaxSubscriptionsPerPrinter %d for %s (count=%d)",
		      MaxSubscriptionsPerPrinter, dest->name, count);
      return (NULL);
    }
  }

 /*
  * Allocate memory for this subscription...
  */

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

 /*
  * Fill in common data...
  */

  if (sub_id)
  {
    temp->id = sub_id;

    if (sub_id >= NextSubscriptionId)
      NextSubscriptionId = sub_id + 1;
  }
  else
  {
    temp->id = NextSubscriptionId;

    NextSubscriptionId ++;
  }

  temp->mask           = mask;
  temp->dest           = dest;
  temp->job            = job;
  temp->pipe           = -1;
  temp->first_event_id = 1;
  temp->next_event_id  = 1;

  cupsdSetString(&(temp->recipient), uri);

 /*
  * Add the subscription to the array...
  */

  cupsArrayAdd(Subscriptions, temp);

 /*
  * For RSS subscriptions, run the notifier immediately...
  */

  if (uri && !strncmp(uri, "rss:", 4))
    cupsd_start_notifier(temp);

  return (temp);
}
コード例 #15
0
ファイル: subscriptions.c プロジェクト: aosm/cups
static void
cupsd_send_notification(
    cupsd_subscription_t *sub,		/* I - Subscription object */
    cupsd_event_t        *event)	/* I - Event to send */
{
  ipp_state_t	state;			/* IPP event state */


  cupsdLogMessage(CUPSD_LOG_DEBUG2,
                  "cupsd_send_notification(sub=%p(%d), event=%p(%s))",
                  sub, sub->id, event, cupsdEventName(event->event));

 /*
  * Allocate the events array as needed...
  */

  if (!sub->events)
  {
    sub->events = cupsArrayNew3((cups_array_func_t)NULL, NULL,
                                (cups_ahash_func_t)NULL, 0,
				(cups_acopy_func_t)NULL,
				(cups_afree_func_t)cupsd_delete_event);

    if (!sub->events)
    {
      cupsdLogMessage(CUPSD_LOG_CRIT,
                      "Unable to allocate memory for subscription #%d!",
                      sub->id);
      return;
    }
  }

 /*
  * Purge an old event as needed...
  */

  if (cupsArrayCount(sub->events) >= MaxEvents)
  {
   /*
    * Purge the oldest event in the cache...
    */

    cupsArrayRemove(sub->events, cupsArrayFirst(sub->events));

    sub->first_event_id ++;
  }

 /*
  * Add the event to the subscription.  Since the events array is
  * always MaxEvents in length, and since we will have already
  * removed an event from the subscription cache if we hit the
  * event cache limit, we don't need to check for overflow here...
  */

  cupsArrayAdd(sub->events, event);

 /*
  * Deliver the event...
  */

  if (sub->recipient)
  {
    for (;;)
    {
      if (sub->pipe < 0)
	cupsd_start_notifier(sub);

      cupsdLogMessage(CUPSD_LOG_DEBUG2, "sub->pipe=%d", sub->pipe);

      if (sub->pipe < 0)
	break;

      event->attrs->state = IPP_IDLE;

      while ((state = ippWriteFile(sub->pipe, event->attrs)) != IPP_DATA)
        if (state == IPP_ERROR)
	  break;

      if (state == IPP_ERROR)
      {
        if (errno == EPIPE)
	{
	 /*
	  * Notifier died, try restarting it...
	  */

          cupsdLogMessage(CUPSD_LOG_WARN,
	                  "Notifier for subscription %d (%s) went away, "
			  "retrying!",
			  sub->id, sub->recipient);
	  cupsdEndProcess(sub->pid, 0);

	  close(sub->pipe);
	  sub->pipe = -1;
          continue;
	}

        cupsdLogMessage(CUPSD_LOG_ERROR,
	                "Unable to send event for subscription %d (%s)!",
			sub->id, sub->recipient);
      }

     /*
      * If we get this far, break out of the loop...
      */

      break;
    }
  }

 /*
  * Bump the event sequence number...
  */

  sub->next_event_id ++;
}
コード例 #16
0
ファイル: string.c プロジェクト: AndychenCL/cups
char *					/* O - String pointer */
_cupsStrAlloc(const char *s)		/* I - String */
{
  size_t		slen;		/* Length of string */
  _cups_sp_item_t	*item,		/* String pool item */
			*key;		/* Search key */


 /*
  * Range check input...
  */

  if (!s)
    return (NULL);

 /*
  * Get the string pool...
  */

  _cupsMutexLock(&sp_mutex);

  if (!stringpool)
    stringpool = cupsArrayNew((cups_array_func_t)compare_sp_items, NULL);

  if (!stringpool)
  {
    _cupsMutexUnlock(&sp_mutex);

    return (NULL);
  }

 /*
  * See if the string is already in the pool...
  */

  key = (_cups_sp_item_t *)(s - offsetof(_cups_sp_item_t, str));

  if ((item = (_cups_sp_item_t *)cupsArrayFind(stringpool, key)) != NULL)
  {
   /*
    * Found it, return the cached string...
    */

    item->ref_count ++;

#ifdef DEBUG_GUARDS
    DEBUG_printf(("5_cupsStrAlloc: Using string %p(%s) for \"%s\", guard=%08x, "
                  "ref_count=%d", item, item->str, s, item->guard,
		  item->ref_count));

    if (item->guard != _CUPS_STR_GUARD)
      abort();
#endif /* DEBUG_GUARDS */

    _cupsMutexUnlock(&sp_mutex);

    return (item->str);
  }

 /*
  * Not found, so allocate a new one...
  */

  slen = strlen(s);
  item = (_cups_sp_item_t *)calloc(1, sizeof(_cups_sp_item_t) + slen);
  if (!item)
  {
    _cupsMutexUnlock(&sp_mutex);

    return (NULL);
  }

  item->ref_count = 1;
  memcpy(item->str, s, slen + 1);

#ifdef DEBUG_GUARDS
  item->guard = _CUPS_STR_GUARD;

  DEBUG_printf(("5_cupsStrAlloc: Created string %p(%s) for \"%s\", guard=%08x, "
		"ref_count=%d", item, item->str, s, item->guard,
		item->ref_count));
#endif /* DEBUG_GUARDS */

 /*
  * Add the string to the pool and return it...
  */

  cupsArrayAdd(stringpool, item);

  _cupsMutexUnlock(&sp_mutex);

  return (item->str);
}
コード例 #17
0
ファイル: colorman.c プロジェクト: Cacauu/cups
static void
colord_create_profile(
    cups_array_t *profiles,		/* I - Profiles array */
    const char   *printer_name,		/* I - Printer name */
    const char   *qualifier,		/* I - Profile qualifier */
    const char   *colorspace,		/* I - Profile colorspace */
    char         **format,		/* I - Profile qualifier format */
    const char   *iccfile,		/* I - ICC filename */
    const char   *scope)		/* I - The scope of the profile, e.g.
				               'normal', 'temp' or 'disk' */
{
  DBusMessage	*message = NULL;        /* D-Bus request */
  DBusMessage	*reply = NULL;          /* D-Bus reply */
  DBusMessageIter args;			/* D-Bus method arguments */
  DBusMessageIter dict;			/* D-Bus method arguments */
  DBusError	error;			/* D-Bus error */
  char		*idstr;			/* Profile ID string */
  size_t	idstrlen;		/* Profile ID allocated length */
  const char	*profile_path;		/* Device object path */
  char		format_str[1024];	/* Qualifier format as a string */


 /*
  * Create the profile...
  */

  message = dbus_message_new_method_call(COLORD_DBUS_SERVICE,
                                         COLORD_DBUS_PATH,
                                         COLORD_DBUS_INTERFACE,
                                         "CreateProfile");

  idstrlen = strlen(printer_name) + 1 + strlen(qualifier) + 1;
  if ((idstr = malloc(idstrlen)) == NULL)
    goto out;
  snprintf(idstr, idstrlen, "%s-%s", printer_name, qualifier);
  cupsdLogMessage(CUPSD_LOG_DEBUG, "Using profile ID \"%s\".", idstr);

  dbus_message_iter_init_append(message, &args);
  dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &idstr);
  dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &scope);

  snprintf(format_str, sizeof(format_str), "%s.%s.%s", format[0], format[1],
           format[2]);

  dbus_message_iter_open_container(&args, DBUS_TYPE_ARRAY, "{ss}", &dict);
  colord_dict_add_strings(&dict, "Qualifier", qualifier);
  colord_dict_add_strings(&dict, "Format", format_str);
  colord_dict_add_strings(&dict, "Colorspace", colorspace);
  if (iccfile)
    colord_dict_add_strings(&dict, "Filename", iccfile);
  dbus_message_iter_close_container(&args, &dict);

 /*
  * Send the CreateProfile request synchronously...
  */

  dbus_error_init(&error);
  cupsdLogMessage(CUPSD_LOG_DEBUG, "Calling CreateProfile(%s,%s)", idstr,
                  scope);
  reply = dbus_connection_send_with_reply_and_block(colord_con, message,
                                                    COLORD_DBUS_TIMEOUT,
                                                    &error);
  if (!reply)
  {
    cupsdLogMessage(CUPSD_LOG_WARN, "CreateProfile failed: %s:%s", error.name,
                    error.message);
    dbus_error_free(&error);
    goto out;
  }

 /*
  * Get reply data...
  */

  dbus_message_iter_init(reply, &args);
  if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_OBJECT_PATH)
  {
    cupsdLogMessage(CUPSD_LOG_WARN,
                    "CreateProfile failed: Incorrect reply type.");
    goto out;
  }

  dbus_message_iter_get_basic(&args, &profile_path);
  cupsdLogMessage(CUPSD_LOG_DEBUG, "Created profile \"%s\".", profile_path);
  cupsArrayAdd(profiles, strdup(profile_path));

out:

  if (message)
    dbus_message_unref(message);

  if (reply)
    dbus_message_unref(reply);

  if (idstr)
    free(idstr);
}
コード例 #18
0
ファイル: array.c プロジェクト: Cacauu/cups
int					/* O - 1 on success, 0 on failure */
_cupsArrayAddStrings(cups_array_t *a,	/* I - Array */
                     const char   *s,	/* I - Delimited strings or NULL */
                     char         delim)/* I - Delimiter character */
{
  char		*buffer,		/* Copy of string */
		*start,			/* Start of string */
		*end;			/* End of string */
  int		status = 1;		/* Status of add */


  DEBUG_printf(("_cupsArrayAddStrings(a=%p, s=\"%s\", delim='%c')", a, s,
                delim));

  if (!a || !s || !*s)
  {
    DEBUG_puts("1_cupsArrayAddStrings: Returning 0");
    return (0);
  }

  if (delim == ' ')
  {
   /*
    * Skip leading whitespace...
    */

    DEBUG_puts("1_cupsArrayAddStrings: Skipping leading whitespace.");

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

    DEBUG_printf(("1_cupsArrayAddStrings: Remaining string \"%s\".", s));
  }

  if (!strchr(s, delim) &&
      (delim != ' ' || (!strchr(s, '\t') && !strchr(s, '\n'))))
  {
   /*
    * String doesn't contain a delimiter, so add it as a single value...
    */

    DEBUG_puts("1_cupsArrayAddStrings: No delimiter seen, adding a single "
               "value.");

    if (!cupsArrayFind(a, (void *)s))
      status = cupsArrayAdd(a, (void *)s);
  }
  else if ((buffer = strdup(s)) == NULL)
  {
    DEBUG_puts("1_cupsArrayAddStrings: Unable to duplicate string.");
    status = 0;
  }
  else
  {
    for (start = end = buffer; *end; start = end)
    {
     /*
      * Find the end of the current delimited string and see if we need to add
      * it...
      */

      if (delim == ' ')
      {
        while (*end && !isspace(*end & 255))
          end ++;
        while (*end && isspace(*end & 255))
          *end++ = '\0';
      }
      else if ((end = strchr(start, delim)) != NULL)
        *end++ = '\0';
      else
        end = start + strlen(start);

      DEBUG_printf(("1_cupsArrayAddStrings: Adding \"%s\", end=\"%s\"", start,
                    end));

      if (!cupsArrayFind(a, start))
        status &= cupsArrayAdd(a, start);
    }

    free(buffer);
  }

  DEBUG_printf(("1_cupsArrayAddStrings: Returning %d.", status));

  return (status);
}
コード例 #19
0
ファイル: process.c プロジェクト: Cacauu/cups
int					/* O - Process ID or 0 */
cupsdStartProcess(
    const char  *command,		/* I - Full path to command */
    char        *argv[],		/* I - Command-line arguments */
    char        *envp[],		/* I - Environment */
    int         infd,			/* I - Standard input file descriptor */
    int         outfd,			/* I - Standard output file descriptor */
    int         errfd,			/* I - Standard error file descriptor */
    int         backfd,			/* I - Backchannel file descriptor */
    int         sidefd,			/* I - Sidechannel file descriptor */
    int         root,			/* I - Run as root? */
    void        *profile,		/* I - Security profile to use */
    cupsd_job_t *job,			/* I - Job associated with process */
    int         *pid)			/* O - Process ID */
{
  int		i;			/* Looping var */
  const char	*exec_path = command;	/* Command to be exec'd */
  char		*real_argv[110],	/* Real command-line arguments */
		cups_exec[1024],	/* Path to "cups-exec" program */
		user_str[16],		/* User string */
		group_str[16],		/* Group string */
		nice_str[16];		/* FilterNice string */
  uid_t		user;			/* Command UID */
  cupsd_proc_t	*proc;			/* New process record */
#if USE_POSIX_SPAWN
  posix_spawn_file_actions_t actions;	/* Spawn file actions */
  posix_spawnattr_t attrs;		/* Spawn attributes */
  sigset_t	defsignals;		/* Default signals */
#elif defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
  struct sigaction action;		/* POSIX signal handler */
#endif /* USE_POSIX_SPAWN */
#if defined(__APPLE__)
  char		processPath[1024],	/* CFProcessPath environment variable */
		linkpath[1024];		/* Link path for symlinks... */
  int		linkbytes;		/* Bytes for link path */
#endif /* __APPLE__ */


  *pid = 0;

 /*
  * Figure out the UID for the child process...
  */

  if (RunUser)
    user = RunUser;
  else if (root)
    user = 0;
  else
    user = User;

 /*
  * Check the permissions of the command we are running...
  */

  if (_cupsFileCheck(command, _CUPS_FILE_CHECK_PROGRAM, !RunUser,
                     cupsdLogFCMessage, job ? job->printer : NULL))
    return (0);

#if defined(__APPLE__)
  if (envp)
  {
   /*
    * Add special voodoo magic for OS X - this allows OS X programs to access
    * their bundle resources properly...
    */

    if ((linkbytes = readlink(command, linkpath, sizeof(linkpath) - 1)) > 0)
    {
     /*
      * Yes, this is a symlink to the actual program, nul-terminate and
      * use it...
      */

      linkpath[linkbytes] = '\0';

      if (linkpath[0] == '/')
	snprintf(processPath, sizeof(processPath), "CFProcessPath=%s",
		 linkpath);
      else
	snprintf(processPath, sizeof(processPath), "CFProcessPath=%s/%s",
		 dirname((char *)command), linkpath);
    }
    else
      snprintf(processPath, sizeof(processPath), "CFProcessPath=%s", command);

    envp[0] = processPath;		/* Replace <CFProcessPath> string */
  }
#endif	/* __APPLE__ */

 /*
  * Use helper program when we have a sandbox profile...
  */

#if !USE_POSIX_SPAWN
  if (profile)
#endif /* !USE_POSIX_SPAWN */
  {
    snprintf(cups_exec, sizeof(cups_exec), "%s/daemon/cups-exec", ServerBin);
    snprintf(user_str, sizeof(user_str), "%d", user);
    snprintf(group_str, sizeof(group_str), "%d", Group);
    snprintf(nice_str, sizeof(nice_str), "%d", FilterNice);

    real_argv[0] = cups_exec;
    real_argv[1] = (char *)"-g";
    real_argv[2] = group_str;
    real_argv[3] = (char *)"-n";
    real_argv[4] = nice_str;
    real_argv[5] = (char *)"-u";
    real_argv[6] = user_str;
    real_argv[7] = profile ? profile : "none";
    real_argv[8] = (char *)command;

    for (i = 0;
         i < (int)(sizeof(real_argv) / sizeof(real_argv[0]) - 10) && argv[i];
	 i ++)
      real_argv[i + 9] = argv[i];

    real_argv[i + 9] = NULL;

    argv      = real_argv;
    exec_path = cups_exec;
  }

  if (LogLevel == CUPSD_LOG_DEBUG2)
  {
    cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdStartProcess: Preparing to start \"%s\", arguments:", command);

    for (i = 0; argv[i]; i ++)
      cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdStartProcess: argv[%d] = \"%s\"", i, argv[i]);
  }

#if USE_POSIX_SPAWN
 /*
  * Setup attributes and file actions for the spawn...
  */

  cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdStartProcess: Setting spawn attributes.");
  sigemptyset(&defsignals);
  sigaddset(&defsignals, SIGTERM);
  sigaddset(&defsignals, SIGCHLD);
  sigaddset(&defsignals, SIGPIPE);

  posix_spawnattr_init(&attrs);
  posix_spawnattr_setflags(&attrs, POSIX_SPAWN_SETPGROUP | POSIX_SPAWN_SETSIGDEF);
  posix_spawnattr_setpgroup(&attrs, 0);
  posix_spawnattr_setsigdefault(&attrs, &defsignals);

  cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdStartProcess: Setting file actions.");
  posix_spawn_file_actions_init(&actions);
  if (infd != 0)
  {
    if (infd < 0)
      posix_spawn_file_actions_addopen(&actions, 0, "/dev/null", O_RDONLY, 0);
    else
      posix_spawn_file_actions_adddup2(&actions, infd, 0);
  }

  if (outfd != 1)
  {
    if (outfd < 0)
      posix_spawn_file_actions_addopen(&actions, 1, "/dev/null", O_WRONLY, 0);
    else
      posix_spawn_file_actions_adddup2(&actions, outfd, 1);
  }

  if (errfd != 2)
  {
    if (errfd < 0)
      posix_spawn_file_actions_addopen(&actions, 2, "/dev/null", O_WRONLY, 0);
    else
      posix_spawn_file_actions_adddup2(&actions, errfd, 2);
  }

  if (backfd != 3 && backfd >= 0)
    posix_spawn_file_actions_adddup2(&actions, backfd, 3);

  if (sidefd != 4 && sidefd >= 0)
    posix_spawn_file_actions_adddup2(&actions, sidefd, 4);

  cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdStartProcess: Calling posix_spawn.");

  if (posix_spawn(pid, exec_path, &actions, &attrs, argv, envp ? envp : environ))
  {
    cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to fork %s - %s.", command, strerror(errno));

    *pid = 0;
  }
  else
    cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdStartProcess: pid=%d", (int)*pid);

  posix_spawn_file_actions_destroy(&actions);
  posix_spawnattr_destroy(&attrs);

#else
 /*
  * Block signals before forking...
  */

  cupsdHoldSignals();

  if ((*pid = fork()) == 0)
  {
   /*
    * Child process goes here; update stderr as needed...
    */

    if (errfd != 2)
    {
      if (errfd < 0)
        errfd = open("/dev/null", O_WRONLY);

      if (errfd != 2)
      {
        dup2(errfd, 2);
	close(errfd);
      }
    }

   /*
    * Put this process in its own process group so that we can kill any child
    * processes it creates.
    */

#  ifdef HAVE_SETPGID
    if (!RunUser && setpgid(0, 0))
      exit(errno + 100);
#  else
    if (!RunUser && setpgrp())
      exit(errno + 100);
#  endif /* HAVE_SETPGID */

   /*
    * Update the remaining file descriptors as needed...
    */

    if (infd != 0)
    {
      if (infd < 0)
        infd = open("/dev/null", O_RDONLY);

      if (infd != 0)
      {
        dup2(infd, 0);
	close(infd);
      }
    }

    if (outfd != 1)
    {
      if (outfd < 0)
        outfd = open("/dev/null", O_WRONLY);

      if (outfd != 1)
      {
        dup2(outfd, 1);
	close(outfd);
      }
    }

    if (backfd != 3 && backfd >= 0)
    {
      dup2(backfd, 3);
      close(backfd);
      fcntl(3, F_SETFL, O_NDELAY);
    }

    if (sidefd != 4 && sidefd >= 0)
    {
      dup2(sidefd, 4);
      close(sidefd);
      fcntl(4, F_SETFL, O_NDELAY);
    }

   /*
    * Change the priority of the process based on the FilterNice setting.
    * (this is not done for root processes...)
    */

    if (!root)
      nice(FilterNice);

   /*
    * Reset group membership to just the main one we belong to.
    */

    if (!RunUser && setgid(Group))
      exit(errno + 100);

    if (!RunUser && setgroups(1, &Group))
      exit(errno + 100);

   /*
    * Change user to something "safe"...
    */

    if (!RunUser && user && setuid(user))
      exit(errno + 100);

   /*
    * Change umask to restrict permissions on created files...
    */

    umask(077);

   /*
    * Unblock signals before doing the exec...
    */

#  ifdef HAVE_SIGSET
    sigset(SIGTERM, SIG_DFL);
    sigset(SIGCHLD, SIG_DFL);
    sigset(SIGPIPE, SIG_DFL);
#  elif defined(HAVE_SIGACTION)
    memset(&action, 0, sizeof(action));

    sigemptyset(&action.sa_mask);
    action.sa_handler = SIG_DFL;

    sigaction(SIGTERM, &action, NULL);
    sigaction(SIGCHLD, &action, NULL);
    sigaction(SIGPIPE, &action, NULL);
#  else
    signal(SIGTERM, SIG_DFL);
    signal(SIGCHLD, SIG_DFL);
    signal(SIGPIPE, SIG_DFL);
#  endif /* HAVE_SIGSET */

    cupsdReleaseSignals();

   /*
    * Execute the command; if for some reason this doesn't work, log an error
    * exit with a non-zero value...
    */

    if (envp)
      execve(exec_path, argv, envp);
    else
      execv(exec_path, argv);

    exit(errno + 100);
  }
  else if (*pid < 0)
  {
   /*
    * Error - couldn't fork a new process!
    */

    cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to fork %s - %s.", command,
                    strerror(errno));

    *pid = 0;
  }

  cupsdReleaseSignals();
#endif /* USE_POSIX_SPAWN */

  if (*pid)
  {
    if (!process_array)
      process_array = cupsArrayNew((cups_array_func_t)compare_procs, NULL);

    if (process_array)
    {
      if ((proc = calloc(1, sizeof(cupsd_proc_t) + strlen(command))) != NULL)
      {
        proc->pid    = *pid;
	proc->job_id = job ? job->id : 0;
	_cups_strcpy(proc->name, command);

	cupsArrayAdd(process_array, proc);
      }
    }
  }

  cupsdLogMessage(CUPSD_LOG_DEBUG2,
		  "cupsdStartProcess(command=\"%s\", argv=%p, envp=%p, "
		  "infd=%d, outfd=%d, errfd=%d, backfd=%d, sidefd=%d, root=%d, "
		  "profile=%p, job=%p(%d), pid=%p) = %d",
		  command, argv, envp, infd, outfd, errfd, backfd, sidefd,
		  root, profile, job, job ? job->id : 0, pid, *pid);

  return (*pid);
}
コード例 #20
0
ファイル: main.c プロジェクト: ChErePOdaViLka/cups
static void
launchd_checkin(void)
{
  size_t		i,		/* Looping var */
			count;		/* Number of listeners */
  launch_data_t		ld_msg,		/* Launch data message */
			ld_resp,	/* Launch data response */
			ld_array,	/* Launch data array */
			ld_sockets,	/* Launch data sockets dictionary */
			tmp;		/* Launch data */
  cupsd_listener_t	*lis;		/* Listeners array */
  http_addr_t		addr;		/* Address variable */
  socklen_t		addrlen;	/* Length of address */
  int			fd;		/* File descriptor */
  char			s[256];		/* String addresss */


  cupsdLogMessage(CUPSD_LOG_DEBUG, "launchd_checkin: pid=%d", (int)getpid());

 /*
  * Check-in with launchd...
  */

  ld_msg = launch_data_new_string(LAUNCH_KEY_CHECKIN);
  if ((ld_resp = launch_msg(ld_msg)) == NULL)
  {
    cupsdLogMessage(CUPSD_LOG_ERROR,
		    "launchd_checkin: launch_msg(\"" LAUNCH_KEY_CHECKIN
		    "\") IPC failure");
    exit(EXIT_FAILURE);
    return; /* anti-compiler-warning */
  }

  if (launch_data_get_type(ld_resp) == LAUNCH_DATA_ERRNO)
  {
    errno = launch_data_get_errno(ld_resp);
    cupsdLogMessage(CUPSD_LOG_ERROR, "launchd_checkin: Check-in failed: %s",
                    strerror(errno));
    exit(EXIT_FAILURE);
    return; /* anti-compiler-warning */
  }

 /*
  * Get the sockets dictionary...
  */

  if ((ld_sockets = launch_data_dict_lookup(ld_resp, LAUNCH_JOBKEY_SOCKETS))
          == NULL)
  {
    cupsdLogMessage(CUPSD_LOG_ERROR,
                    "launchd_checkin: No sockets found to answer requests on!");
    exit(EXIT_FAILURE);
    return; /* anti-compiler-warning */
  }

 /*
  * Get the array of listener sockets...
  */

  if ((ld_array = launch_data_dict_lookup(ld_sockets, "Listeners")) == NULL)
  {
    cupsdLogMessage(CUPSD_LOG_ERROR,
                    "launchd_checkin: No sockets found to answer requests on!");
    exit(EXIT_FAILURE);
    return; /* anti-compiler-warning */
  }

 /*
  * Add listening fd(s) to the Listener array...
  */

  if (launch_data_get_type(ld_array) == LAUNCH_DATA_ARRAY)
  {
    count = launch_data_array_get_count(ld_array);

    for (i = 0; i < count; i ++)
    {
     /*
      * Get the launchd file descriptor and address...
      */

      if ((tmp = launch_data_array_get_index(ld_array, i)) != NULL)
      {
	fd      = launch_data_get_fd(tmp);
	addrlen = sizeof(addr);

	if (getsockname(fd, (struct sockaddr *)&addr, &addrlen))
	{
	  cupsdLogMessage(CUPSD_LOG_ERROR,
			  "launchd_checkin: Unable to get local address - %s",
			  strerror(errno));
	  continue;
	}

       /*
	* Try to match the launchd socket address to one of the listeners...
	*/

	for (lis = (cupsd_listener_t *)cupsArrayFirst(Listeners);
	     lis;
	     lis = (cupsd_listener_t *)cupsArrayNext(Listeners))
	  if (httpAddrEqual(&lis->address, &addr))
	    break;

       /*
	* Add a new listener If there's no match...
	*/

	if (lis)
	{
	  cupsdLogMessage(CUPSD_LOG_DEBUG,
		  "launchd_checkin: Matched existing listener %s with fd %d...",
		  httpAddrString(&(lis->address), s, sizeof(s)), fd);
	}
	else
	{
	  cupsdLogMessage(CUPSD_LOG_DEBUG,
		  "launchd_checkin: Adding new listener %s with fd %d...",
		  httpAddrString(&addr, s, sizeof(s)), fd);

	  if ((lis = calloc(1, sizeof(cupsd_listener_t))) == NULL)
	  {
	    cupsdLogMessage(CUPSD_LOG_ERROR,
			    "launchd_checkin: Unable to allocate listener - "
			    "%s.", strerror(errno));
	    exit(EXIT_FAILURE);
	  }

	  cupsArrayAdd(Listeners, lis);

	  memcpy(&lis->address, &addr, sizeof(lis->address));
	}

	lis->fd = fd;

#  ifdef HAVE_SSL
	if (_httpAddrPort(&(lis->address)) == 443)
	  lis->encryption = HTTP_ENCRYPT_ALWAYS;
#  endif /* HAVE_SSL */
      }
    }
  }

  launch_data_free(ld_msg);
  launch_data_free(ld_resp);
}
コード例 #21
0
ファイル: mark.c プロジェクト: AnotherView/cups
static void
ppd_mark_option(ppd_file_t *ppd,	/* I - PPD file */
                const char *option,	/* I - Option name */
                const char *choice)	/* I - Choice name */
{
  int		i, j;			/* Looping vars */
  ppd_option_t	*o;			/* Option pointer */
  ppd_choice_t	*c,			/* Choice pointer */
		*oldc,			/* Old choice pointer */
		key;			/* Search key for choice */
  struct lconv	*loc;			/* Locale data */


  DEBUG_printf(("7ppd_mark_option(ppd=%p, option=\"%s\", choice=\"%s\")",
        	ppd, option, choice));

 /*
  * AP_D_InputSlot is the "default input slot" on MacOS X, and setting
  * it clears the regular InputSlot choices...
  */

  if (!_cups_strcasecmp(option, "AP_D_InputSlot"))
  {
    cupsArraySave(ppd->options);

    if ((o = ppdFindOption(ppd, "InputSlot")) != NULL)
    {
      key.option = o;
      if ((oldc = (ppd_choice_t *)cupsArrayFind(ppd->marked, &key)) != NULL)
      {
        oldc->marked = 0;
        cupsArrayRemove(ppd->marked, oldc);
      }
    }

    cupsArrayRestore(ppd->options);
  }

 /*
  * Check for custom options...
  */

  cupsArraySave(ppd->options);

  o = ppdFindOption(ppd, option);

  cupsArrayRestore(ppd->options);

  if (!o)
    return;

  loc = localeconv();

  if (!_cups_strncasecmp(choice, "Custom.", 7))
  {
   /*
    * Handle a custom option...
    */

    if ((c = ppdFindChoice(o, "Custom")) == NULL)
      return;

    if (!_cups_strcasecmp(option, "PageSize"))
    {
     /*
      * Handle custom page sizes...
      */

      ppdPageSize(ppd, choice);
    }
    else
    {
     /*
      * Handle other custom options...
      */

      ppd_coption_t	*coption;	/* Custom option */
      ppd_cparam_t	*cparam;	/* Custom parameter */
      char		*units;		/* Custom points units */


      if ((coption = ppdFindCustomOption(ppd, option)) != NULL)
      {
        if ((cparam = (ppd_cparam_t *)cupsArrayFirst(coption->params)) == NULL)
	  return;

        switch (cparam->type)
	{
	  case PPD_CUSTOM_CURVE :
	  case PPD_CUSTOM_INVCURVE :
	  case PPD_CUSTOM_REAL :
	      cparam->current.custom_real = (float)_cupsStrScand(choice + 7,
	                                                         NULL, loc);
	      break;

	  case PPD_CUSTOM_POINTS :
	      cparam->current.custom_points = (float)_cupsStrScand(choice + 7,
	                                                           &units,
	                                                           loc);

              if (units)
	      {
        	if (!_cups_strcasecmp(units, "cm"))
	          cparam->current.custom_points *= 72.0f / 2.54f;
        	else if (!_cups_strcasecmp(units, "mm"))
	          cparam->current.custom_points *= 72.0f / 25.4f;
        	else if (!_cups_strcasecmp(units, "m"))
	          cparam->current.custom_points *= 72.0f / 0.0254f;
        	else if (!_cups_strcasecmp(units, "in"))
	          cparam->current.custom_points *= 72.0f;
        	else if (!_cups_strcasecmp(units, "ft"))
	          cparam->current.custom_points *= 12.0f * 72.0f;
              }
	      break;

	  case PPD_CUSTOM_INT :
	      cparam->current.custom_int = atoi(choice + 7);
	      break;

	  case PPD_CUSTOM_PASSCODE :
	  case PPD_CUSTOM_PASSWORD :
	  case PPD_CUSTOM_STRING :
	      if (cparam->current.custom_string)
	        _cupsStrFree(cparam->current.custom_string);

	      cparam->current.custom_string = _cupsStrAlloc(choice + 7);
	      break;
	}
      }
    }

   /*
    * Make sure that we keep the option marked below...
    */

    choice = "Custom";
  }
  else if (choice[0] == '{')
  {
   /*
    * Handle multi-value custom options...
    */

    ppd_coption_t	*coption;	/* Custom option */
    ppd_cparam_t	*cparam;	/* Custom parameter */
    char		*units;		/* Custom points units */
    int			num_vals;	/* Number of values */
    cups_option_t	*vals,		/* Values */
			*val;		/* Value */


    if ((c = ppdFindChoice(o, "Custom")) == NULL)
      return;

    if ((coption = ppdFindCustomOption(ppd, option)) != NULL)
    {
      num_vals = cupsParseOptions(choice, 0, &vals);

      for (i = 0, val = vals; i < num_vals; i ++, val ++)
      {
        if ((cparam = ppdFindCustomParam(coption, val->name)) == NULL)
	  continue;

	switch (cparam->type)
	{
	  case PPD_CUSTOM_CURVE :
	  case PPD_CUSTOM_INVCURVE :
	  case PPD_CUSTOM_REAL :
	      cparam->current.custom_real = (float)_cupsStrScand(val->value,
	                                                         NULL, loc);
	      break;

	  case PPD_CUSTOM_POINTS :
	      cparam->current.custom_points = (float)_cupsStrScand(val->value,
	                                                           &units,
	                                                           loc);

	      if (units)
	      {
        	if (!_cups_strcasecmp(units, "cm"))
		  cparam->current.custom_points *= 72.0f / 2.54f;
        	else if (!_cups_strcasecmp(units, "mm"))
		  cparam->current.custom_points *= 72.0f / 25.4f;
        	else if (!_cups_strcasecmp(units, "m"))
		  cparam->current.custom_points *= 72.0f / 0.0254f;
        	else if (!_cups_strcasecmp(units, "in"))
		  cparam->current.custom_points *= 72.0f;
        	else if (!_cups_strcasecmp(units, "ft"))
		  cparam->current.custom_points *= 12.0f * 72.0f;
	      }
	      break;

	  case PPD_CUSTOM_INT :
	      cparam->current.custom_int = atoi(val->value);
	      break;

	  case PPD_CUSTOM_PASSCODE :
	  case PPD_CUSTOM_PASSWORD :
	  case PPD_CUSTOM_STRING :
	      if (cparam->current.custom_string)
		_cupsStrFree(cparam->current.custom_string);

	      cparam->current.custom_string = _cupsStrRetain(val->value);
	      break;
	}
      }

      cupsFreeOptions(num_vals, vals);
    }
  }
  else
  {
    for (i = o->num_choices, c = o->choices; i > 0; i --, c ++)
      if (!_cups_strcasecmp(c->choice, choice))
        break;

    if (!i)
      return;
  }

 /*
  * Option found; mark it and then handle unmarking any other options.
  */

  if (o->ui != PPD_UI_PICKMANY)
  {
   /*
    * Unmark all other choices...
    */

    if ((oldc = (ppd_choice_t *)cupsArrayFind(ppd->marked, c)) != NULL)
    {
      oldc->marked = 0;
      cupsArrayRemove(ppd->marked, oldc);
    }

    if (!_cups_strcasecmp(option, "PageSize") || !_cups_strcasecmp(option, "PageRegion"))
    {
     /*
      * Mark current page size...
      */

      for (j = 0; j < ppd->num_sizes; j ++)
	ppd->sizes[j].marked = !_cups_strcasecmp(ppd->sizes[j].name,
		                           choice);

     /*
      * Unmark the current PageSize or PageRegion setting, as
      * appropriate...
      */

      cupsArraySave(ppd->options);

      if (!_cups_strcasecmp(option, "PageSize"))
      {
	if ((o = ppdFindOption(ppd, "PageRegion")) != NULL)
        {
          key.option = o;
          if ((oldc = (ppd_choice_t *)cupsArrayFind(ppd->marked, &key)) != NULL)
          {
            oldc->marked = 0;
            cupsArrayRemove(ppd->marked, oldc);
          }
        }
      }
      else
      {
	if ((o = ppdFindOption(ppd, "PageSize")) != NULL)
        {
          key.option = o;
          if ((oldc = (ppd_choice_t *)cupsArrayFind(ppd->marked, &key)) != NULL)
          {
            oldc->marked = 0;
            cupsArrayRemove(ppd->marked, oldc);
          }
        }
      }

      cupsArrayRestore(ppd->options);
    }
    else if (!_cups_strcasecmp(option, "InputSlot"))
    {
     /*
      * Unmark ManualFeed option...
      */

      cupsArraySave(ppd->options);

      if ((o = ppdFindOption(ppd, "ManualFeed")) != NULL)
      {
        key.option = o;
        if ((oldc = (ppd_choice_t *)cupsArrayFind(ppd->marked, &key)) != NULL)
        {
          oldc->marked = 0;
          cupsArrayRemove(ppd->marked, oldc);
        }
      }

      cupsArrayRestore(ppd->options);
    }
    else if (!_cups_strcasecmp(option, "ManualFeed") &&
	     !_cups_strcasecmp(choice, "True"))
    {
     /*
      * Unmark InputSlot option...
      */

      cupsArraySave(ppd->options);

      if ((o = ppdFindOption(ppd, "InputSlot")) != NULL)
      {
        key.option = o;
        if ((oldc = (ppd_choice_t *)cupsArrayFind(ppd->marked, &key)) != NULL)
        {
          oldc->marked = 0;
          cupsArrayRemove(ppd->marked, oldc);
        }
      }

      cupsArrayRestore(ppd->options);
    }
  }

  c->marked = 1;

  cupsArrayAdd(ppd->marked, c);
}
コード例 #22
0
static cups_device_t *			/* O - Device */
get_device(cups_array_t *devices,	/* I - Device array */
           const char   *serviceName,	/* I - Name of service/device */
           const char   *regtype,	/* I - Type of service */
           const char   *replyDomain)	/* I - Service domain */
{
  cups_device_t	key,			/* Search key */
		*device;		/* Device */
  char		fullName[kDNSServiceMaxDomainName];
					/* Full name for query */


 /*
  * See if this is a new device...
  */

  key.name    = (char *)serviceName;
  key.regtype = (char *)regtype;

  for (device = cupsArrayFind(devices, &key);
       device;
       device = cupsArrayNext(devices))
    if (strcasecmp(device->name, key.name))
      break;
    else
    {
      if (!strcasecmp(device->domain, "local.") &&
          strcasecmp(device->domain, replyDomain))
      {
       /*
        * Update the .local listing to use the "global" domain name instead.
	* The backend will try local lookups first, then the global domain name.
	*/

        free(device->domain);
	device->domain = strdup(replyDomain);

	DNSServiceConstructFullName(fullName, device->name, regtype,
	                            replyDomain);
	free(device->fullName);
	device->fullName = strdup(fullName);
      }

      return (device);
    }

 /*
  * Yes, add the device...
  */

  device          = calloc(sizeof(cups_device_t), 1);
  device->name    = strdup(serviceName);
  device->domain  = strdup(replyDomain);
  device->regtype = strdup(regtype);

  cupsArrayAdd(devices, device);

 /*
  * Set the "full name" of this service, which is used for queries...
  */

  DNSServiceConstructFullName(fullName, serviceName, regtype, replyDomain);
  device->fullName = strdup(fullName);

#ifdef DEBUG
  fprintf(stderr, "get_device: fullName=\"%s\"...\n", fullName);
#endif /* DEBUG */

  return (device);
}
コード例 #23
0
ファイル: snmp.c プロジェクト: jianglei12138/cups
static device_uri_t *			/* O - Device URI */
add_device_uri(char *value)		/* I - Value from snmp.conf */
{
  device_uri_t	*device_uri;		/* Device URI */
  char		*start;			/* Start of value */


 /*
  * Allocate memory as needed...
  */

  if (!DeviceURIs)
    DeviceURIs = cupsArrayNew(NULL, NULL);

  if (!DeviceURIs)
    return (NULL);

  if ((device_uri = calloc(1, sizeof(device_uri_t))) == NULL)
    return (NULL);

  if ((device_uri->uris = cupsArrayNew(NULL, NULL)) == NULL)
  {
    free(device_uri);
    return (NULL);
  }

 /*
  * Scan the value string for the regular expression and URI(s)...
  */

  value ++; /* Skip leading " */

  for (start = value; *value && *value != '\"'; value ++)
    if (*value == '\\' && value[1])
      _cups_strcpy(value, value + 1);

  if (!*value)
  {
    fputs("ERROR: Missing end quote for DeviceURI!\n", stderr);

    cupsArrayDelete(device_uri->uris);
    free(device_uri);

    return (NULL);
  }

  *value++ = '\0';

  if (regcomp(&(device_uri->re), start, REG_EXTENDED | REG_ICASE))
  {
    fputs("ERROR: Bad regular expression for DeviceURI!\n", stderr);

    cupsArrayDelete(device_uri->uris);
    free(device_uri);

    return (NULL);
  }

  while (*value)
  {
    while (isspace(*value & 255))
      value ++;

    if (!*value)
      break;

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

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

    cupsArrayAdd(device_uri->uris, strdup(start));
  }

 /*
  * Add the device URI to the list and return it...
  */

  cupsArrayAdd(DeviceURIs, device_uri);

  return (device_uri);
}
コード例 #24
0
ファイル: ppd-conflicts.c プロジェクト: Cacauu/cups
int					/* O  - 1 on success, 0 on failure */
cupsResolveConflicts(
    ppd_file_t    *ppd,			/* I  - PPD file */
    const char    *option,		/* I  - Newly selected option or @code NULL@ for none */
    const char    *choice,		/* I  - Newly selected choice or @code NULL@ for none */
    int           *num_options,		/* IO - Number of additional selected options */
    cups_option_t **options)		/* IO - Additional selected options */
{
  int			i,		/* Looping var */
			tries,		/* Number of tries */
			num_newopts;	/* Number of new options */
  cups_option_t		*newopts;	/* New options */
  cups_array_t		*active = NULL,	/* Active constraints */
			*pass,		/* Resolvers for this pass */
			*resolvers,	/* Resolvers we have used */
			*test;		/* Test array for conflicts */
  _ppd_cups_uiconsts_t	*consts;	/* Current constraints */
  _ppd_cups_uiconst_t	*constptr;	/* Current constraint */
  ppd_attr_t		*resolver;	/* Current resolver */
  const char		*resval;	/* Pointer into resolver value */
  char			resoption[PPD_MAX_NAME],
					/* Current resolver option */
			reschoice[PPD_MAX_NAME],
					/* Current resolver choice */
			*resptr,	/* Pointer into option/choice */
			firstpage[255];	/* AP_FIRSTPAGE_Keyword string */
  const char		*value;		/* Selected option value */
  int			changed;	/* Did we change anything? */
  ppd_choice_t		*marked;	/* Marked choice */


 /*
  * Range check input...
  */

  if (!ppd || !num_options || !options || (option == NULL) != (choice == NULL))
    return (0);

 /*
  * Build a shadow option array...
  */

  num_newopts = 0;
  newopts     = NULL;

  for (i = 0; i < *num_options; i ++)
    num_newopts = cupsAddOption((*options)[i].name, (*options)[i].value,
                                num_newopts, &newopts);
  if (option && _cups_strcasecmp(option, "Collate"))
    num_newopts = cupsAddOption(option, choice, num_newopts, &newopts);

 /*
  * Loop until we have no conflicts...
  */

  cupsArraySave(ppd->sorted_attrs);

  resolvers = NULL;
  pass      = cupsArrayNew((cups_array_func_t)_cups_strcasecmp, NULL);
  tries     = 0;

  while (tries < 100 &&
         (active = ppd_test_constraints(ppd, NULL, NULL, num_newopts, newopts,
                                        _PPD_ALL_CONSTRAINTS)) != NULL)
  {
    tries ++;

    if (!resolvers)
      resolvers = cupsArrayNew((cups_array_func_t)_cups_strcasecmp, NULL);

    for (consts = (_ppd_cups_uiconsts_t *)cupsArrayFirst(active), changed = 0;
         consts;
	 consts = (_ppd_cups_uiconsts_t *)cupsArrayNext(active))
    {
      if (consts->resolver[0])
      {
       /*
        * Look up the resolver...
	*/

        if (cupsArrayFind(pass, consts->resolver))
	  continue;			/* Already applied this resolver... */

        if (cupsArrayFind(resolvers, consts->resolver))
	{
	 /*
	  * Resolver loop!
	  */

	  DEBUG_printf(("1cupsResolveConflicts: Resolver loop with %s!",
	                consts->resolver));
          goto error;
	}

        if ((resolver = ppdFindAttr(ppd, "cupsUIResolver",
	                            consts->resolver)) == NULL)
        {
	  DEBUG_printf(("1cupsResolveConflicts: Resolver %s not found!",
	                consts->resolver));
	  goto error;
	}

        if (!resolver->value)
	{
	  DEBUG_printf(("1cupsResolveConflicts: Resolver %s has no value!",
	                consts->resolver));
	  goto error;
	}

       /*
        * Add the options from the resolver...
	*/

        cupsArrayAdd(pass, consts->resolver);
	cupsArrayAdd(resolvers, consts->resolver);

        for (resval = resolver->value; *resval && !changed;)
	{
	  while (_cups_isspace(*resval))
	    resval ++;

	  if (*resval != '*')
	    break;

	  for (resval ++, resptr = resoption;
	       *resval && !_cups_isspace(*resval);
	       resval ++)
            if (resptr < (resoption + sizeof(resoption) - 1))
	      *resptr++ = *resval;

          *resptr = '\0';

	  while (_cups_isspace(*resval))
	    resval ++;

	  for (resptr = reschoice;
	       *resval && !_cups_isspace(*resval);
	       resval ++)
            if (resptr < (reschoice + sizeof(reschoice) - 1))
	      *resptr++ = *resval;

          *resptr = '\0';

          if (!resoption[0] || !reschoice[0])
	    break;

         /*
	  * Is this the option we are changing?
	  */

          snprintf(firstpage, sizeof(firstpage), "AP_FIRSTPAGE_%s", resoption);

	  if (option &&
	      (!_cups_strcasecmp(resoption, option) ||
	       !_cups_strcasecmp(firstpage, option) ||
	       (!_cups_strcasecmp(option, "PageSize") &&
		!_cups_strcasecmp(resoption, "PageRegion")) ||
	       (!_cups_strcasecmp(option, "AP_FIRSTPAGE_PageSize") &&
		!_cups_strcasecmp(resoption, "PageSize")) ||
	       (!_cups_strcasecmp(option, "AP_FIRSTPAGE_PageSize") &&
		!_cups_strcasecmp(resoption, "PageRegion")) ||
	       (!_cups_strcasecmp(option, "PageRegion") &&
	        !_cups_strcasecmp(resoption, "PageSize")) ||
	       (!_cups_strcasecmp(option, "AP_FIRSTPAGE_PageRegion") &&
	        !_cups_strcasecmp(resoption, "PageSize")) ||
	       (!_cups_strcasecmp(option, "AP_FIRSTPAGE_PageRegion") &&
	        !_cups_strcasecmp(resoption, "PageRegion"))))
	    continue;

	 /*
	  * Try this choice...
	  */

          if ((test = ppd_test_constraints(ppd, resoption, reschoice,
					   num_newopts, newopts,
					   _PPD_ALL_CONSTRAINTS)) == NULL)
	  {
	   /*
	    * That worked...
	    */

            changed = 1;
	  }
	  else
            cupsArrayDelete(test);

	 /*
	  * Add the option/choice from the resolver regardless of whether it
	  * worked; this makes sure that we can cascade several changes to
	  * make things resolve...
	  */

	  num_newopts = cupsAddOption(resoption, reschoice, num_newopts,
				      &newopts);
        }
      }
      else
      {
       /*
        * Try resolving by choosing the default values for non-installable
	* options, then by iterating through the possible choices...
	*/

        int		j;		/* Looping var */
	ppd_choice_t	*cptr;		/* Current choice */
        ppd_size_t	*size;		/* Current page size */


        for (i = consts->num_constraints, constptr = consts->constraints;
	     i > 0 && !changed;
	     i --, constptr ++)
	{
	 /*
	  * Can't resolve by changing an installable option...
	  */

	  if (constptr->installable)
	    continue;

         /*
	  * Is this the option we are changing?
	  */

	  if (option &&
	      (!_cups_strcasecmp(constptr->option->keyword, option) ||
	       (!_cups_strcasecmp(option, "PageSize") &&
		!_cups_strcasecmp(constptr->option->keyword, "PageRegion")) ||
	       (!_cups_strcasecmp(option, "PageRegion") &&
		!_cups_strcasecmp(constptr->option->keyword, "PageSize"))))
	    continue;

         /*
	  * Get the current option choice...
	  */

          if ((value = cupsGetOption(constptr->option->keyword, num_newopts,
	                             newopts)) == NULL)
          {
	    if (!_cups_strcasecmp(constptr->option->keyword, "PageSize") ||
	        !_cups_strcasecmp(constptr->option->keyword, "PageRegion"))
	    {
	      if ((value = cupsGetOption("PageSize", num_newopts,
	                                 newopts)) == NULL)
                value = cupsGetOption("PageRegion", num_newopts, newopts);

              if (!value)
	      {
	        if ((size = ppdPageSize(ppd, NULL)) != NULL)
		  value = size->name;
		else
		  value = "";
	      }
	    }
	    else
	    {
	      marked = ppdFindMarkedChoice(ppd, constptr->option->keyword);
	      value  = marked ? marked->choice : "";
	    }
	  }

	  if (!_cups_strncasecmp(value, "Custom.", 7))
	    value = "Custom";

         /*
	  * Try the default choice...
	  */

          test = NULL;

          if (_cups_strcasecmp(value, constptr->option->defchoice) &&
	      (test = ppd_test_constraints(ppd, constptr->option->keyword,
	                                   constptr->option->defchoice,
					   num_newopts, newopts,
					   _PPD_OPTION_CONSTRAINTS)) == NULL)
	  {
	   /*
	    * That worked...
	    */

	    num_newopts = cupsAddOption(constptr->option->keyword,
	                                constptr->option->defchoice,
					num_newopts, &newopts);
            changed     = 1;
	  }
	  else
	  {
	   /*
	    * Try each choice instead...
	    */

            for (j = constptr->option->num_choices,
	             cptr = constptr->option->choices;
		 j > 0;
		 j --, cptr ++)
            {
	      cupsArrayDelete(test);
	      test = NULL;

	      if (_cups_strcasecmp(value, cptr->choice) &&
	          _cups_strcasecmp(constptr->option->defchoice, cptr->choice) &&
		  _cups_strcasecmp("Custom", cptr->choice) &&
	          (test = ppd_test_constraints(ppd, constptr->option->keyword,
	                                       cptr->choice, num_newopts,
					       newopts,
					       _PPD_OPTION_CONSTRAINTS)) == NULL)
	      {
	       /*
		* This choice works...
		*/

		num_newopts = cupsAddOption(constptr->option->keyword,
					    cptr->choice, num_newopts,
					    &newopts);
		changed     = 1;
		break;
	      }
	    }

	    cupsArrayDelete(test);
          }
        }
      }
    }

    if (!changed)
    {
      DEBUG_puts("1cupsResolveConflicts: Unable to automatically resolve "
		 "constraint!");
      goto error;
    }

    cupsArrayClear(pass);
    cupsArrayDelete(active);
    active = NULL;
  }

  if (tries >= 100)
    goto error;

 /*
  * Free the caller's option array...
  */

  cupsFreeOptions(*num_options, *options);

 /*
  * If Collate is the option we are testing, add it here.  Otherwise, remove
  * any Collate option from the resolve list since the filters automatically
  * handle manual collation...
  */

  if (option && !_cups_strcasecmp(option, "Collate"))
    num_newopts = cupsAddOption(option, choice, num_newopts, &newopts);
  else
    num_newopts = cupsRemoveOption("Collate", num_newopts, &newopts);

 /*
  * Return the new list of options to the caller...
  */

  *num_options = num_newopts;
  *options     = newopts;

  cupsArrayDelete(pass);
  cupsArrayDelete(resolvers);

  cupsArrayRestore(ppd->sorted_attrs);

  DEBUG_printf(("1cupsResolveConflicts: Returning %d options:", num_newopts));
#ifdef DEBUG
  for (i = 0; i < num_newopts; i ++)
    DEBUG_printf(("1cupsResolveConflicts: options[%d]: %s=%s", i,
                  newopts[i].name, newopts[i].value));
#endif /* DEBUG */

  return (1);

 /*
  * If we get here, we failed to resolve...
  */

  error:

  cupsFreeOptions(num_newopts, newopts);

  cupsArrayDelete(active);
  cupsArrayDelete(pass);
  cupsArrayDelete(resolvers);

  cupsArrayRestore(ppd->sorted_attrs);

  DEBUG_puts("1cupsResolveConflicts: Unable to resolve conflicts!");

  return (0);
}
コード例 #25
0
ファイル: help-index.c プロジェクト: josephgbr/cups-pt_BR
help_index_t *				/* O - Search index */
helpSearchIndex(help_index_t *hi,	/* I - Index */
                const char   *query,	/* I - Query string */
		const char   *section,	/* I - Limit search to this section */
		const char   *filename)	/* I - Limit search to this file */
{
  help_index_t	*search;		/* Search index */
  help_node_t	*node;			/* Current node */
  help_word_t	*word;			/* Current word */
  void		*sc;			/* Search context */
  int		matches;		/* Number of matches */


  DEBUG_printf(("helpSearchIndex(hi=%p, query=\"%s\", filename=\"%s\")",
                hi, query, filename));

 /*
  * Range check...
  */

  if (!hi || !query)
    return (NULL);

 /*
  * Reset the scores of all nodes to 0...
  */

  for (node = (help_node_t *)cupsArrayFirst(hi->nodes);
       node;
       node = (help_node_t *)cupsArrayNext(hi->nodes))
    node->score = 0;

 /*
  * Find the first node to search in...
  */

  if (filename)
  {
    node = helpFindNode(hi, filename, NULL);
    if (!node)
      return (NULL);
  }
  else
    node = (help_node_t *)cupsArrayFirst(hi->nodes);

 /*
  * Convert the query into a regular expression...
  */

  sc = cgiCompileSearch(query);
  if (!sc)
    return (NULL);

 /*
  * Allocate a search index...
  */

  search = calloc(1, sizeof(help_index_t));
  if (!search)
  {
    cgiFreeSearch(sc);
    return (NULL);
  }

  search->nodes  = cupsArrayNew((cups_array_func_t)help_sort_by_name, NULL);
  search->sorted = cupsArrayNew((cups_array_func_t)help_sort_by_score, NULL);

  if (!search->nodes || !search->sorted)
  {
    cupsArrayDelete(search->nodes);
    cupsArrayDelete(search->sorted);
    free(search);
    cgiFreeSearch(sc);
    return (NULL);
  }

  search->search = 1;

 /*
  * Check each node in the index, adding matching nodes to the
  * search index...
  */

  for (; node; node = (help_node_t *)cupsArrayNext(hi->nodes))
    if (section && strcmp(node->section, section))
      continue;
    else if (filename && strcmp(node->filename, filename))
      continue;
    else
    {
      matches = cgiDoSearch(sc, node->text);

      for (word = (help_word_t *)cupsArrayFirst(node->words);
           word;
	   word = (help_word_t *)cupsArrayNext(node->words))
        if (cgiDoSearch(sc, word->text) > 0)
          matches += word->count;

      if (matches > 0)
      {
       /*
	* Found a match, add the node to the search index...
	*/

	node->score = matches;

	cupsArrayAdd(search->nodes, node);
	cupsArrayAdd(search->sorted, node);
      }
    }

 /*
  * Free the search context...
  */

  cgiFreeSearch(sc);

 /*
  * Return the results...
  */

  return (search);
}
コード例 #26
0
ファイル: network.c プロジェクト: josephgbr/cups-pt_BR
void
cupsdNetIFUpdate(void)
{
  int			match;		/* Matching address? */
  cupsd_listener_t	*lis;		/* Listen address */
  cupsd_netif_t		*temp;		/* New interface */
  struct ifaddrs	*addrs,		/* Interface address list */
			*addr;		/* Current interface address */
  char			hostname[1024];	/* Hostname for address */
  size_t		hostlen;	/* Length of hostname */


 /*
  * Only update the list if we need to...
  */

  if (!NetIFUpdate)
    return;

  NetIFUpdate = 0;

 /*
  * Free the old interfaces...
  */

  cupsdNetIFFree();

 /*
  * Make sure we have an array...
  */

  if (!NetIFList)
    NetIFList = cupsArrayNew((cups_array_func_t)compare_netif, NULL);

  if (!NetIFList)
    return;

 /*
  * Grab a new list of interfaces...
  */

  if (getifaddrs(&addrs) < 0)
  {
    cupsdLogMessage(CUPSD_LOG_DEBUG, "cupsdNetIFUpdate: Unable to get interface list - %s", strerror(errno));
    return;
  }

  for (addr = addrs; addr != NULL; addr = addr->ifa_next)
  {
   /*
    * See if this interface address is IPv4 or IPv6...
    */

    if (addr->ifa_addr == NULL ||
        (addr->ifa_addr->sa_family != AF_INET
#ifdef AF_INET6
	 && addr->ifa_addr->sa_family != AF_INET6
#endif
	) ||
        addr->ifa_netmask == NULL || addr->ifa_name == NULL)
    {
      cupsdLogMessage(CUPSD_LOG_DEBUG, "cupsdNetIFUpdate: Ignoring \"%s\".", addr->ifa_name);
      continue;
    }

   /*
    * Try looking up the hostname for the address as needed...
    */

    if (HostNameLookups)
      httpAddrLookup((http_addr_t *)(addr->ifa_addr), hostname,
                     sizeof(hostname));
    else
    {
     /*
      * Map the default server address and localhost to the server name
      * and localhost, respectively; for all other addresses, use the
      * numeric address...
      */

      if (httpAddrLocalhost((http_addr_t *)(addr->ifa_addr)))
        strlcpy(hostname, "localhost", sizeof(hostname));
      else
	httpAddrString((http_addr_t *)(addr->ifa_addr), hostname,
		       sizeof(hostname));
    }

   /*
    * Create a new address element...
    */

    hostlen = strlen(hostname);
    if ((temp = calloc(1, sizeof(cupsd_netif_t) + hostlen)) == NULL)
    {
      cupsdLogMessage(CUPSD_LOG_DEBUG, "cupsdNetIFUpdate: Unable to allocate memory for interface.");
      break;
    }

   /*
    * Copy all of the information...
    */

    strlcpy(temp->name, addr->ifa_name, sizeof(temp->name));
    temp->hostlen = hostlen;
    memcpy(temp->hostname, hostname, hostlen + 1);

    if (addr->ifa_addr->sa_family == AF_INET)
    {
     /*
      * Copy IPv4 addresses...
      */

      memcpy(&(temp->address), addr->ifa_addr, sizeof(struct sockaddr_in));
      memcpy(&(temp->mask), addr->ifa_netmask, sizeof(struct sockaddr_in));

      if (addr->ifa_dstaddr)
	memcpy(&(temp->broadcast), addr->ifa_dstaddr,
	       sizeof(struct sockaddr_in));
    }
#ifdef AF_INET6
    else
    {
     /*
      * Copy IPv6 addresses...
      */

      memcpy(&(temp->address), addr->ifa_addr, sizeof(struct sockaddr_in6));
      memcpy(&(temp->mask), addr->ifa_netmask, sizeof(struct sockaddr_in6));

      if (addr->ifa_dstaddr)
	memcpy(&(temp->broadcast), addr->ifa_dstaddr,
	       sizeof(struct sockaddr_in6));
    }
#endif /* AF_INET6 */

    if (!(addr->ifa_flags & IFF_POINTOPOINT) &&
        !httpAddrLocalhost(&(temp->address)))
      temp->is_local = 1;

   /*
    * Determine which port to use when advertising printers...
    */

    for (lis = (cupsd_listener_t *)cupsArrayFirst(Listeners);
         lis;
	 lis = (cupsd_listener_t *)cupsArrayNext(Listeners))
    {
      match = 0;

      if (httpAddrAny(&(lis->address)))
        match = 1;
      else if (addr->ifa_addr->sa_family == AF_INET &&
               lis->address.addr.sa_family == AF_INET &&
               (lis->address.ipv4.sin_addr.s_addr &
	        temp->mask.ipv4.sin_addr.s_addr) ==
	           (temp->address.ipv4.sin_addr.s_addr &
		    temp->mask.ipv4.sin_addr.s_addr))
        match = 1;
#ifdef AF_INET6
      else if (addr->ifa_addr->sa_family == AF_INET6 &&
               lis->address.addr.sa_family == AF_INET6 &&
               (lis->address.ipv6.sin6_addr.s6_addr[0] &
	        temp->mask.ipv6.sin6_addr.s6_addr[0]) ==
		   (temp->address.ipv6.sin6_addr.s6_addr[0] &
		    temp->mask.ipv6.sin6_addr.s6_addr[0]) &&
               (lis->address.ipv6.sin6_addr.s6_addr[1] &
	        temp->mask.ipv6.sin6_addr.s6_addr[1]) ==
		   (temp->address.ipv6.sin6_addr.s6_addr[1] &
		    temp->mask.ipv6.sin6_addr.s6_addr[1]) &&
               (lis->address.ipv6.sin6_addr.s6_addr[2] &
	        temp->mask.ipv6.sin6_addr.s6_addr[2]) ==
		   (temp->address.ipv6.sin6_addr.s6_addr[2] &
		    temp->mask.ipv6.sin6_addr.s6_addr[2]) &&
               (lis->address.ipv6.sin6_addr.s6_addr[3] &
	        temp->mask.ipv6.sin6_addr.s6_addr[3]) ==
		   (temp->address.ipv6.sin6_addr.s6_addr[3] &
		    temp->mask.ipv6.sin6_addr.s6_addr[3]))
        match = 1;
#endif /* AF_INET6 */

      if (match)
      {
        temp->port = httpAddrPort(&(lis->address));
	break;
      }
    }

   /*
    * Add it to the array...
    */

    cupsArrayAdd(NetIFList, temp);

    cupsdLogMessage(CUPSD_LOG_DEBUG, "cupsdNetIFUpdate: \"%s\" = %s:%d",
                    temp->name, temp->hostname, temp->port);
  }

  freeifaddrs(addrs);
}
コード例 #27
0
ファイル: help-index.c プロジェクト: josephgbr/cups-pt_BR
static int				/* O - 0 = success, -1 = error */
help_load_file(
    help_index_t *hi,			/* I - Index */
    const char   *filename,		/* I - Filename */
    const char   *relative,		/* I - Relative path */
    time_t       mtime)			/* I - Modification time */
{
  cups_file_t	*fp;			/* HTML file */
  help_node_t	*node;			/* Current node */
  char		line[1024],		/* Line from file */
		temp[1024],		/* Temporary word */
                section[1024],		/* Section */
		*ptr,			/* Pointer into line */
		*anchor,		/* Anchor name */
		*text;			/* Text for anchor */
  off_t		offset;			/* File offset */
  char		quote;			/* Quote character */
  help_word_t	*word;			/* Current word */
  int		wordlen;		/* Length of word */


  DEBUG_printf(("2help_load_file(hi=%p, filename=\"%s\", relative=\"%s\", "
                "mtime=%ld)", hi, filename, relative, mtime));

  if ((fp = cupsFileOpen(filename, "r")) == NULL)
    return (-1);

  node   = NULL;
  offset = 0;

  strlcpy(section, "Other", sizeof(section));

  while (cupsFileGets(fp, line, sizeof(line)))
  {
   /*
    * Look for "<TITLE>", "<A NAME", or "<!-- SECTION:" prefix...
    */

    if (!_cups_strncasecmp(line, "<!-- SECTION:", 13))
    {
     /*
      * Got section line, copy it!
      */

      for (ptr = line + 13; isspace(*ptr & 255); ptr ++);

      strlcpy(section, ptr, sizeof(section));
      if ((ptr = strstr(section, "-->")) != NULL)
      {
       /*
        * Strip comment stuff from end of line...
	*/

        for (*ptr-- = '\0'; ptr > line && isspace(*ptr & 255); *ptr-- = '\0');

	if (isspace(*ptr & 255))
	  *ptr = '\0';
      }
      continue;
    }

    for (ptr = line; (ptr = strchr(ptr, '<')) != NULL;)
    {
      ptr ++;

      if (!_cups_strncasecmp(ptr, "TITLE>", 6))
      {
       /*
        * Found the title...
	*/

	anchor = NULL;
	ptr += 6;
      }
      else if (!_cups_strncasecmp(ptr, "A NAME=", 7))
      {
       /*
        * Found an anchor...
	*/

        ptr += 7;

	if (*ptr == '\"' || *ptr == '\'')
	{
	 /*
	  * Get quoted anchor...
	  */

	  quote  = *ptr;
          anchor = ptr + 1;
	  if ((ptr = strchr(anchor, quote)) != NULL)
	    *ptr++ = '\0';
	  else
	    break;
	}
	else
	{
	 /*
	  * Get unquoted anchor...
	  */

          anchor = ptr + 1;

	  for (ptr = anchor; *ptr && *ptr != '>' && !isspace(*ptr & 255); ptr ++);

	  if (*ptr)
	    *ptr++ = '\0';
	  else
	    break;
	}

       /*
        * Got the anchor, now lets find the end...
	*/

        while (*ptr && *ptr != '>')
	  ptr ++;

        if (*ptr != '>')
	  break;

        ptr ++;
      }
      else
        continue;

     /*
      * Now collect text for the link...
      */

      text = ptr;
      while ((ptr = strchr(text, '<')) == NULL)
      {
	ptr = text + strlen(text);
	if (ptr >= (line + sizeof(line) - 2))
	  break;

        *ptr++ = ' ';

        if (!cupsFileGets(fp, ptr, sizeof(line) - (ptr - line) - 1))
	  break;
      }

      *ptr = '\0';

      if (node)
	node->length = offset - node->offset;

      if (!*text)
      {
        node = NULL;
        break;
      }

      if ((node = helpFindNode(hi, relative, anchor)) != NULL)
      {
       /*
	* Node already in the index, so replace the text and other
	* data...
	*/

        cupsArrayRemove(hi->nodes, node);

        if (node->section)
	  free(node->section);

	if (node->text)
	  free(node->text);

        if (node->words)
	{
	  for (word = (help_word_t *)cupsArrayFirst(node->words);
	       word;
	       word = (help_word_t *)cupsArrayNext(node->words))
	    help_delete_word(word);

	  cupsArrayDelete(node->words);
	  node->words = NULL;
	}

	node->section = section[0] ? strdup(section) : NULL;
	node->text    = strdup(text);
	node->mtime   = mtime;
	node->offset  = offset;
	node->score   = 0;
      }
      else
      {
       /*
	* New node...
	*/

        node = help_new_node(relative, anchor, section, text, mtime, offset, 0);
      }

     /*
      * Go through the text value and replace tabs and newlines with
      * whitespace and eliminate extra whitespace...
      */

      for (ptr = node->text, text = node->text; *ptr;)
	if (isspace(*ptr & 255))
	{
	  while (isspace(*ptr & 255))
	    ptr ++;

	  *text++ = ' ';
        }
	else if (text != ptr)
	  *text++ = *ptr++;
	else
	{
	  text ++;
	  ptr ++;
	}

      *text = '\0';

     /*
      * (Re)add the node to the array...
      */

      cupsArrayAdd(hi->nodes, node);

      if (!anchor)
        node = NULL;
      break;
    }

    if (node)
    {
     /*
      * Scan this line for words...
      */

      for (ptr = line; *ptr; ptr ++)
      {
       /*
	* Skip HTML stuff...
	*/

	if (*ptr == '<')
	{
          if (!strncmp(ptr, "<!--", 4))
	  {
	   /*
	    * Skip HTML comment...
	    */

            if ((text = strstr(ptr + 4, "-->")) == NULL)
	      ptr += strlen(ptr) - 1;
	    else
	      ptr = text + 2;
	  }
	  else
	  {
	   /*
            * Skip HTML element...
	    */

            for (ptr ++; *ptr && *ptr != '>'; ptr ++)
	    {
	      if (*ptr == '\"' || *ptr == '\'')
	      {
		for (quote = *ptr++; *ptr && *ptr != quote; ptr ++);

		if (!*ptr)
		  ptr --;
	      }
	    }

	    if (!*ptr)
	      ptr --;
          }

          continue;
	}
	else if (*ptr == '&')
	{
	 /*
	  * Skip HTML entity...
	  */

	  for (ptr ++; *ptr && *ptr != ';'; ptr ++);

	  if (!*ptr)
	    ptr --;

	  continue;
	}
	else if (!isalnum(*ptr & 255))
          continue;

       /*
	* Found the start of a word, search until we find the end...
	*/

	for (text = ptr, ptr ++; *ptr && isalnum(*ptr & 255); ptr ++);

	wordlen = ptr - text;

        memcpy(temp, text, wordlen);
	temp[wordlen] = '\0';

        ptr --;

	if (wordlen > 1 && !bsearch(temp, help_common_words,
	                            (sizeof(help_common_words) /
				     sizeof(help_common_words[0])),
				    sizeof(help_common_words[0]),
				    (int (*)(const void *, const void *))
				        _cups_strcasecmp))
          help_add_word(node, temp);
      }
    }

   /*
    * Get the offset of the next line...
    */

    offset = cupsFileTell(fp);
  }

  cupsFileClose(fp);

  if (node)
    node->length = offset - node->offset;

  return (0);
}
コード例 #28
0
ファイル: language.c プロジェクト: jianglei12138/cups
const char *				/* O - Localized message */
_cupsMessageLookup(cups_array_t *a,	/* I - Message array */
                   const char   *m)	/* I - Message */
{
  _cups_message_t	key,		/* Search key */
			*match;		/* Matching message */


 /*
  * Lookup the message string; if it doesn't exist in the catalog,
  * then return the message that was passed to us...
  */

  key.id = (char *)m;
  match  = (_cups_message_t *)cupsArrayFind(a, &key);

#if defined(__APPLE__) && defined(CUPS_BUNDLEDIR)
  if (!match && cupsArrayUserData(a))
  {
   /*
    * Try looking the string up in the cups.strings dictionary...
    */

    CFDictionaryRef	dict;		/* cups.strings dictionary */
    CFStringRef		cfm,		/* Message as a CF string */
			cfstr;		/* Localized text as a CF string */

    dict      = (CFDictionaryRef)cupsArrayUserData(a);
    cfm       = CFStringCreateWithCString(kCFAllocatorDefault, m,
                                          kCFStringEncodingUTF8);
    match     = calloc(1, sizeof(_cups_message_t));
    match->id = strdup(m);
    cfstr     = cfm ? CFDictionaryGetValue(dict, cfm) : NULL;

    if (cfstr)
    {
      char	buffer[1024];		/* Message buffer */

      CFStringGetCString(cfstr, buffer, sizeof(buffer), kCFStringEncodingUTF8);
      match->str = strdup(buffer);

      DEBUG_printf(("1_cupsMessageLookup: Found \"%s\" as \"%s\"...",
                    m, buffer));
    }
    else
    {
      match->str = strdup(m);

      DEBUG_printf(("1_cupsMessageLookup: Did not find \"%s\"...", m));
    }

    cupsArrayAdd(a, match);

    if (cfm)
      CFRelease(cfm);
  }
#endif /* __APPLE__ && CUPS_BUNDLEDIR */

  if (match && match->str)
    return (match->str);
  else
    return (m);
}
コード例 #29
0
ファイル: dirsvc.c プロジェクト: AndychenCL/cups
static void
dnssdRegisterPrinter(
    cupsd_printer_t *p,			/* I - Printer */
    int             from_callback)	/* I - Called from callback? */
{
  char		name[256];		/* Service name */
  int		printer_port;		/* LPD port number */
  int		status;			/* Registration status */
  cupsd_txt_t	ipp_txt,		/* IPP(S) TXT record */
 		printer_txt;		/* LPD TXT record */


  cupsdLogMessage(CUPSD_LOG_DEBUG2, "dnssdRegisterPrinter(%s) %s", p->name,
                  !p->ipp_srv ? "new" : "update");

#  ifdef HAVE_AVAHI
  if (!avahi_running)
    return;
#  endif /* HAVE_AVAHI */

 /*
  * Remove the current registrations if we have them and then return if
  * per-printer sharing was just disabled...
  */

  dnssdDeregisterPrinter(p, 0, from_callback);

  if (!p->shared)
    return;

 /*
  * Set the registered name as needed; the registered name takes the form of
  * "<printer-info> @ <computer name>"...
  */

  if (!p->reg_name)
  {
    if (p->info && strlen(p->info) > 0)
    {
      if (DNSSDComputerName)
	snprintf(name, sizeof(name), "%s @ %s", p->info, DNSSDComputerName);
      else
	strlcpy(name, p->info, sizeof(name));
    }
    else if (DNSSDComputerName)
      snprintf(name, sizeof(name), "%s @ %s", p->name, DNSSDComputerName);
    else
      strlcpy(name, p->name, sizeof(name));
  }
  else
    strlcpy(name, p->reg_name, sizeof(name));

 /*
  * Register IPP and LPD...
  *
  * We always must register the "_printer" service type in order to reserve
  * our name, but use port number 0 if we haven't actually configured cups-lpd
  * to share via LPD...
  */

  ipp_txt     = dnssdBuildTxtRecord(p, 0);
  printer_txt = dnssdBuildTxtRecord(p, 1);

  if (BrowseLocalProtocols & BROWSE_LPD)
    printer_port = 515;
  else
    printer_port = 0;

  status = dnssdRegisterInstance(NULL, p, name, "_printer._tcp", NULL, printer_port, &printer_txt, 0, from_callback);

#  ifdef HAVE_SSL
  if (status)
    dnssdRegisterInstance(NULL, p, name, "_ipps._tcp", DNSSDSubTypes, DNSSDPort, &ipp_txt, 0, from_callback);
#  endif /* HAVE_SSL */

  if (status)
  {
   /*
    * Use the "_fax-ipp" service type for fax queues, otherwise use "_ipp"...
    */

    if (p->type & CUPS_PRINTER_FAX)
      status = dnssdRegisterInstance(NULL, p, name, "_fax-ipp._tcp", DNSSDSubTypes, DNSSDPort, &ipp_txt, 1, from_callback);
    else
      status = dnssdRegisterInstance(NULL, p, name, "_ipp._tcp", DNSSDSubTypes, DNSSDPort, &ipp_txt, 1, from_callback);
  }

  dnssdFreeTxtRecord(&ipp_txt);
  dnssdFreeTxtRecord(&printer_txt);

  if (status)
  {
   /*
    * Save the registered name and add the printer to the array of DNS-SD
    * printers...
    */

    cupsdSetString(&p->reg_name, name);
    cupsArrayAdd(DNSSDPrinters, p);
  }
  else
  {
   /*
    * Registration failed for this printer...
    */

    dnssdDeregisterInstance(&p->ipp_srv, from_callback);

#  ifdef HAVE_DNSSD
#    ifdef HAVE_SSL
    dnssdDeregisterInstance(&p->ipps_srv, from_callback);
#    endif /* HAVE_SSL */
    dnssdDeregisterInstance(&p->printer_srv, from_callback);
#  endif /* HAVE_DNSSD */
  }
}
コード例 #30
0
ファイル: ppd-conflicts.c プロジェクト: Cacauu/cups
static void
ppd_load_constraints(ppd_file_t *ppd)	/* I - PPD file */
{
  int		i;			/* Looping var */
  ppd_const_t	*oldconst;		/* Current UIConstraints data */
  ppd_attr_t	*constattr;		/* Current cupsUIConstraints attribute */
  _ppd_cups_uiconsts_t	*consts;	/* Current cupsUIConstraints data */
  _ppd_cups_uiconst_t	*constptr;	/* Current constraint */
  ppd_group_t	*installable;		/* Installable options group */
  const char	*vptr;			/* Pointer into constraint value */
  char		option[PPD_MAX_NAME],	/* Option name/MainKeyword */
		choice[PPD_MAX_NAME],	/* Choice/OptionKeyword */
		*ptr;			/* Pointer into option or choice */


  DEBUG_printf(("7ppd_load_constraints(ppd=%p)", ppd));

 /*
  * Create an array to hold the constraint data...
  */

  ppd->cups_uiconstraints = cupsArrayNew(NULL, NULL);

 /*
  * Find the installable options group if it exists...
  */

  for (i = ppd->num_groups, installable = ppd->groups;
       i > 0;
       i --, installable ++)
    if (!_cups_strcasecmp(installable->name, "InstallableOptions"))
      break;

  if (i <= 0)
    installable = NULL;

 /*
  * Load old-style [Non]UIConstraints data...
  */

  for (i = ppd->num_consts, oldconst = ppd->consts; i > 0; i --, oldconst ++)
  {
   /*
    * Weed out nearby duplicates, since the PPD spec requires that you
    * define both "*Foo foo *Bar bar" and "*Bar bar *Foo foo"...
    */

    if (i > 1 &&
	!_cups_strcasecmp(oldconst[0].option1, oldconst[1].option2) &&
	!_cups_strcasecmp(oldconst[0].choice1, oldconst[1].choice2) &&
	!_cups_strcasecmp(oldconst[0].option2, oldconst[1].option1) &&
	!_cups_strcasecmp(oldconst[0].choice2, oldconst[1].choice1))
      continue;

   /*
    * Allocate memory...
    */

    if ((consts = calloc(1, sizeof(_ppd_cups_uiconsts_t))) == NULL)
    {
      DEBUG_puts("8ppd_load_constraints: Unable to allocate memory for "
		 "UIConstraints!");
      return;
    }

    if ((constptr = calloc(2, sizeof(_ppd_cups_uiconst_t))) == NULL)
    {
      free(consts);
      DEBUG_puts("8ppd_load_constraints: Unable to allocate memory for "
		 "UIConstraints!");
      return;
    }

   /*
    * Fill in the information...
    */

    consts->num_constraints = 2;
    consts->constraints     = constptr;

    if (!_cups_strncasecmp(oldconst->option1, "Custom", 6) &&
	!_cups_strcasecmp(oldconst->choice1, "True"))
    {
      constptr[0].option      = ppdFindOption(ppd, oldconst->option1 + 6);
      constptr[0].choice      = ppdFindChoice(constptr[0].option, "Custom");
      constptr[0].installable = 0;
    }
    else
    {
      constptr[0].option      = ppdFindOption(ppd, oldconst->option1);
      constptr[0].choice      = ppdFindChoice(constptr[0].option,
					      oldconst->choice1);
      constptr[0].installable = ppd_is_installable(installable,
						   oldconst->option1);
    }

    if (!constptr[0].option || (!constptr[0].choice && oldconst->choice1[0]))
    {
      DEBUG_printf(("8ppd_load_constraints: Unknown option *%s %s!",
		    oldconst->option1, oldconst->choice1));
      free(consts->constraints);
      free(consts);
      continue;
    }

    if (!_cups_strncasecmp(oldconst->option2, "Custom", 6) &&
	!_cups_strcasecmp(oldconst->choice2, "True"))
    {
      constptr[1].option      = ppdFindOption(ppd, oldconst->option2 + 6);
      constptr[1].choice      = ppdFindChoice(constptr[1].option, "Custom");
      constptr[1].installable = 0;
    }
    else
    {
      constptr[1].option      = ppdFindOption(ppd, oldconst->option2);
      constptr[1].choice      = ppdFindChoice(constptr[1].option,
					      oldconst->choice2);
      constptr[1].installable = ppd_is_installable(installable,
						   oldconst->option2);
    }

    if (!constptr[1].option || (!constptr[1].choice && oldconst->choice2[0]))
    {
      DEBUG_printf(("8ppd_load_constraints: Unknown option *%s %s!",
		    oldconst->option2, oldconst->choice2));
      free(consts->constraints);
      free(consts);
      continue;
    }

    consts->installable = constptr[0].installable || constptr[1].installable;

   /*
    * Add it to the constraints array...
    */

    cupsArrayAdd(ppd->cups_uiconstraints, consts);
  }

 /*
  * Then load new-style constraints...
  */

  for (constattr = ppdFindAttr(ppd, "cupsUIConstraints", NULL);
       constattr;
       constattr = ppdFindNextAttr(ppd, "cupsUIConstraints", NULL))
  {
    if (!constattr->value)
    {
      DEBUG_puts("8ppd_load_constraints: Bad cupsUIConstraints value!");
      continue;
    }

    for (i = 0, vptr = strchr(constattr->value, '*');
	 vptr;
	 i ++, vptr = strchr(vptr + 1, '*'));

    if (i == 0)
    {
      DEBUG_puts("8ppd_load_constraints: Bad cupsUIConstraints value!");
      continue;
    }

    if ((consts = calloc(1, sizeof(_ppd_cups_uiconsts_t))) == NULL)
    {
      DEBUG_puts("8ppd_load_constraints: Unable to allocate memory for "
		 "cupsUIConstraints!");
      return;
    }

    if ((constptr = calloc((size_t)i, sizeof(_ppd_cups_uiconst_t))) == NULL)
    {
      free(consts);
      DEBUG_puts("8ppd_load_constraints: Unable to allocate memory for "
		 "cupsUIConstraints!");
      return;
    }

    consts->num_constraints = i;
    consts->constraints     = constptr;

    strlcpy(consts->resolver, constattr->spec, sizeof(consts->resolver));

    for (i = 0, vptr = strchr(constattr->value, '*');
	 vptr;
	 i ++, vptr = strchr(vptr, '*'), constptr ++)
    {
     /*
      * Extract "*Option Choice" or just "*Option"...
      */

      for (vptr ++, ptr = option; *vptr && !_cups_isspace(*vptr); vptr ++)
	if (ptr < (option + sizeof(option) - 1))
	  *ptr++ = *vptr;

      *ptr = '\0';

      while (_cups_isspace(*vptr))
	vptr ++;

      if (*vptr == '*')
	choice[0] = '\0';
      else
      {
	for (ptr = choice; *vptr && !_cups_isspace(*vptr); vptr ++)
	  if (ptr < (choice + sizeof(choice) - 1))
	    *ptr++ = *vptr;

	*ptr = '\0';
      }

      if (!_cups_strncasecmp(option, "Custom", 6) && !_cups_strcasecmp(choice, "True"))
      {
	_cups_strcpy(option, option + 6);
	strlcpy(choice, "Custom", sizeof(choice));
      }

      constptr->option      = ppdFindOption(ppd, option);
      constptr->choice      = ppdFindChoice(constptr->option, choice);
      constptr->installable = ppd_is_installable(installable, option);
      consts->installable   |= constptr->installable;

      if (!constptr->option || (!constptr->choice && choice[0]))
      {
	DEBUG_printf(("8ppd_load_constraints: Unknown option *%s %s!",
		      option, choice));
	break;
      }
    }

    if (!vptr)
      cupsArrayAdd(ppd->cups_uiconstraints, consts);
    else
    {
      free(consts->constraints);
      free(consts);
    }
  }
}