Пример #1
0
static char *				/* O - End of string */
cups_scan_strings(char *buffer)		/* I - Start of string */
{
  char	*bufptr;			/* Pointer into string */


  for (bufptr = buffer + 1; *bufptr && *bufptr != '\"'; bufptr ++)
  {
    if (*bufptr == '\\')
    {
      if (bufptr[1] >= '0' && bufptr[1] <= '3' &&
	  bufptr[2] >= '0' && bufptr[2] <= '7' &&
	  bufptr[3] >= '0' && bufptr[3] <= '7')
      {
       /*
	* Decode \nnn octal escape...
	*/

	*bufptr = ((((bufptr[1] - '0') << 3) | (bufptr[2] - '0')) << 3) |
		  (bufptr[3] - '0');
	_cups_strcpy(bufptr + 1, bufptr + 4);
      }
      else
      {
       /*
	* Decode \C escape...
	*/

	_cups_strcpy(bufptr, bufptr + 1);
	if (*bufptr == 'n')
	  *bufptr = '\n';
	else if (*bufptr == 'r')
	  *bufptr = '\r';
	else if (*bufptr == 't')
	  *bufptr = '\t';
      }
    }
  }

  return (bufptr);
}
Пример #2
0
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);
}
Пример #3
0
int					/* O - Number of options found */
cupsParseOptions(
    const char    *arg,			/* I - Argument to parse */
    int           num_options,		/* I - Number of options */
    cups_option_t **options)		/* O - Options found */
{
  char	*copyarg,			/* Copy of input string */
	*ptr,				/* Pointer into string */
	*name,				/* Pointer to name */
	*value,				/* Pointer to value */
	sep,				/* Separator character */
	quote;				/* Quote character */


  DEBUG_printf(("cupsParseOptions(arg=\"%s\", num_options=%d, options=%p)", arg, num_options, (void *)options));

 /*
  * Range check input...
  */

  if (!arg)
  {
    DEBUG_printf(("1cupsParseOptions: Returning %d", num_options));
    return (num_options);
  }

  if (!options || num_options < 0)
  {
    DEBUG_puts("1cupsParseOptions: Returning 0");
    return (0);
  }

 /*
  * Make a copy of the argument string and then divide it up...
  */

  if ((copyarg = strdup(arg)) == NULL)
  {
    DEBUG_puts("1cupsParseOptions: Unable to copy arg string");
    DEBUG_printf(("1cupsParseOptions: Returning %d", num_options));
    return (num_options);
  }

  if (*copyarg == '{')
  {
   /*
    * Remove surrounding {} so we can parse "{name=value ... name=value}"...
    */

    if ((ptr = copyarg + strlen(copyarg) - 1) > copyarg && *ptr == '}')
    {
      *ptr = '\0';
      ptr  = copyarg + 1;
    }
    else
      ptr = copyarg;
  }
  else
    ptr = copyarg;

 /*
  * Skip leading spaces...
  */

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

 /*
  * Loop through the string...
  */

  while (*ptr != '\0')
  {
   /*
    * Get the name up to a SPACE, =, or end-of-string...
    */

    name = ptr;
    while (!strchr("\f\n\r\t\v =", *ptr) && *ptr)
      ptr ++;

   /*
    * Avoid an empty name...
    */

    if (ptr == name)
      break;

   /*
    * Skip trailing spaces...
    */

    while (_cups_isspace(*ptr))
      *ptr++ = '\0';

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

    DEBUG_printf(("2cupsParseOptions: name=\"%s\"", name));

    if (sep != '=')
    {
     /*
      * Boolean option...
      */

      if (!_cups_strncasecmp(name, "no", 2))
        num_options = cupsAddOption(name + 2, "false", num_options,
	                            options);
      else
        num_options = cupsAddOption(name, "true", num_options, options);

      continue;
    }

   /*
    * Remove = and parse the value...
    */

    value = ptr;

    while (*ptr && !_cups_isspace(*ptr))
    {
      if (*ptr == ',')
        ptr ++;
      else if (*ptr == '\'' || *ptr == '\"')
      {
       /*
	* Quoted string constant...
	*/

	quote = *ptr;
	_cups_strcpy(ptr, ptr + 1);

	while (*ptr != quote && *ptr)
	{
	  if (*ptr == '\\' && ptr[1])
	    _cups_strcpy(ptr, ptr + 1);

	  ptr ++;
	}

	if (*ptr)
	  _cups_strcpy(ptr, ptr + 1);
      }
      else if (*ptr == '{')
      {
       /*
	* Collection value...
	*/

	int depth;

	for (depth = 0; *ptr; ptr ++)
	{
	  if (*ptr == '{')
	    depth ++;
	  else if (*ptr == '}')
	  {
	    depth --;
	    if (!depth)
	    {
	      ptr ++;
	      break;
	    }
	  }
	  else if (*ptr == '\\' && ptr[1])
	    _cups_strcpy(ptr, ptr + 1);
	}
      }
      else
      {
       /*
	* Normal space-delimited string...
	*/

	while (*ptr && !_cups_isspace(*ptr))
	{
	  if (*ptr == '\\' && ptr[1])
	    _cups_strcpy(ptr, ptr + 1);

	  ptr ++;
	}
      }
    }

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

    DEBUG_printf(("2cupsParseOptions: value=\"%s\"", value));

   /*
    * Skip trailing whitespace...
    */

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

   /*
    * Add the string value...
    */

    num_options = cupsAddOption(name, value, num_options, options);
  }

 /*
  * Free the copy of the argument we made and return the number of options
  * found.
  */

  free(copyarg);

  DEBUG_printf(("1cupsParseOptions: Returning %d", num_options));

  return (num_options);
}
Пример #4
0
char *					/* O - Line from buffer, "", or NULL */
cupsdStatBufUpdate(cupsd_statbuf_t *sb,	/* I - Status buffer */
                   int             *loglevel,
					/* O - Log level */ 
                   char            *line,
					/* I - Line buffer */
                   int             linelen)
					/* I - Size of line buffer */
{
  int		bytes;			/* Number of bytes read */
  char		*lineptr,		/* Pointer to end of line in buffer */
		*message;		/* Pointer to message text */


 /*
  * Check if the buffer already contains a full line...
  */

  if ((lineptr = strchr(sb->buffer, '\n')) == NULL)
  {
   /*
    * No, read more data...
    */

    if ((bytes = read(sb->fd, sb->buffer + sb->bufused,
                      CUPSD_SB_BUFFER_SIZE - sb->bufused - 1)) > 0)
    {
      sb->bufused += bytes;
      sb->buffer[sb->bufused] = '\0';

     /*
      * Guard against a line longer than the max buffer size...
      */

      if ((lineptr = strchr(sb->buffer, '\n')) == NULL &&
          sb->bufused == (CUPSD_SB_BUFFER_SIZE - 1))
	lineptr = sb->buffer + sb->bufused;
    }
    else if (bytes < 0 && errno == EINTR)
    {
     /*
      * Return an empty line if we are interrupted...
      */

      *loglevel = CUPSD_LOG_NONE;
      line[0]   = '\0';

      return (line);
    }
    else
    {
     /*
      * End-of-file, so use the whole buffer...
      */

      lineptr  = sb->buffer + sb->bufused;
      *lineptr = '\0';
    }

   /*
    * Final check for end-of-file...
    */

    if (sb->bufused == 0 && bytes == 0)
      lineptr = NULL;
  }

  if (!lineptr)
  {
   /*
    * End of file...
    */

    *loglevel = CUPSD_LOG_NONE;
    line[0]   = '\0';

    return (NULL);
  }

 /*
  * Terminate the line and process it...
  */

  *lineptr++ = '\0';

 /*
  * Figure out the logging level...
  */

  if (!strncmp(sb->buffer, "EMERG:", 6))
  {
    *loglevel = CUPSD_LOG_EMERG;
    message   = sb->buffer + 6;
  }
  else if (!strncmp(sb->buffer, "ALERT:", 6))
  {
    *loglevel = CUPSD_LOG_ALERT;
    message   = sb->buffer + 6;
  }
  else if (!strncmp(sb->buffer, "CRIT:", 5))
  {
    *loglevel = CUPSD_LOG_CRIT;
    message   = sb->buffer + 5;
  }
  else if (!strncmp(sb->buffer, "ERROR:", 6))
  {
    *loglevel = CUPSD_LOG_ERROR;
    message   = sb->buffer + 6;
  }
  else if (!strncmp(sb->buffer, "WARNING:", 8))
  {
    *loglevel = CUPSD_LOG_WARN;
    message   = sb->buffer + 8;
  }
  else if (!strncmp(sb->buffer, "NOTICE:", 7))
  {
    *loglevel = CUPSD_LOG_NOTICE;
    message   = sb->buffer + 7;
  }
  else if (!strncmp(sb->buffer, "INFO:", 5))
  {
    *loglevel = CUPSD_LOG_INFO;
    message   = sb->buffer + 5;
  }
  else if (!strncmp(sb->buffer, "DEBUG:", 6))
  {
    *loglevel = CUPSD_LOG_DEBUG;
    message   = sb->buffer + 6;
  }
  else if (!strncmp(sb->buffer, "DEBUG2:", 7))
  {
    *loglevel = CUPSD_LOG_DEBUG2;
    message   = sb->buffer + 7;
  }
  else if (!strncmp(sb->buffer, "PAGE:", 5))
  {
    *loglevel = CUPSD_LOG_PAGE;
    message   = sb->buffer + 5;
  }
  else if (!strncmp(sb->buffer, "STATE:", 6))
  {
    *loglevel = CUPSD_LOG_STATE;
    message   = sb->buffer + 6;
  }
  else if (!strncmp(sb->buffer, "ATTR:", 5))
  {
    *loglevel = CUPSD_LOG_ATTR;
    message   = sb->buffer + 5;
  }
  else
  {
    *loglevel = CUPSD_LOG_DEBUG;
    message   = sb->buffer;
  }

 /*
  * Skip leading whitespace in the message...
  */

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

 /*
  * Send it to the log file as needed...
  */

  if (*loglevel > CUPSD_LOG_NONE &&
      (*loglevel != CUPSD_LOG_INFO || LogLevel == CUPSD_LOG_DEBUG2))
  {
   /*
    * General status message; send it to the error_log file...
    */

    if (message[0] == '[')
      cupsdLogMessage(*loglevel, "%s", message);
    else
      cupsdLogMessage(*loglevel, "%s %s", sb->prefix, message);
  }
  else if (*loglevel < CUPSD_LOG_NONE && LogLevel == CUPSD_LOG_DEBUG2)
    cupsdLogMessage(CUPSD_LOG_DEBUG2, "%s %s", sb->prefix, sb->buffer);

 /*
  * Copy the message to the line buffer...
  */

  strlcpy(line, message, linelen);

 /*
  * Copy over the buffer data we've used up...
  */

  if (lineptr < sb->buffer + sb->bufused)
    _cups_strcpy(sb->buffer, lineptr);

  sb->bufused -= lineptr - sb->buffer;

  if (sb->bufused < 0)
    sb->bufused = 0;

  return (line);
}
Пример #5
0
static int				/* O - Exit status */
auto_configure(ppd_file_t *ppd,		/* I - PPD file */
               const char *user)	/* I - Printing user */
{
  int		status = 0;		/* Exit status */
  ppd_option_t	*option;		/* Current option in PPD */
  ppd_attr_t	*attr;			/* Query command attribute */
  const char	*valptr;		/* Pointer into attribute value */
  char		buffer[1024],		/* String buffer */
		*bufptr;		/* Pointer into buffer */
  ssize_t	bytes;			/* Number of bytes read */
  int		datalen;		/* Side-channel data length */


 /*
  * See if the backend supports bidirectional I/O...
  */

  datalen = 1;
  if (cupsSideChannelDoRequest(CUPS_SC_CMD_GET_BIDI, buffer, &datalen,
                               30.0) != CUPS_SC_STATUS_OK ||
      buffer[0] != CUPS_SC_BIDI_SUPPORTED)
  {
    fputs("DEBUG: Unable to auto-configure PostScript Printer - no "
          "bidirectional I/O available!\n", stderr);
    return (1);
  }

 /*
  * Put the printer in PostScript mode...
  */

  begin_ps(ppd, user);

 /*
  * (STR #4028)
  *
  * As a lot of PPDs contain bad PostScript query code, we need to prevent one
  * bad query sequence from affecting all auto-configuration.  The following
  * error handler allows us to log PostScript errors to cupsd.
  */

  puts("/cups_handleerror {\n"
       "  $error /newerror false put\n"
       "  (:PostScript error in \") print cups_query_keyword print (\": ) "
       "print\n"
       "  $error /errorname get 128 string cvs print\n"
       "  (; offending command:) print $error /command get 128 string cvs "
       "print (\n) print flush\n"
       "} bind def\n"
       "errordict /timeout {} put\n"
       "/cups_query_keyword (?Unknown) def\n");
  fflush(stdout);

 /*
  * Wait for the printer to become connected...
  */

  do
  {
    sleep(1);
    datalen = 1;
  }
  while (cupsSideChannelDoRequest(CUPS_SC_CMD_GET_CONNECTED, buffer, &datalen,
                                  5.0) == CUPS_SC_STATUS_OK && !buffer[0]);

 /*
  * Then loop through every option in the PPD file and ask for the current
  * value...
  */

  fputs("DEBUG: Auto-configuring PostScript printer...\n", stderr);

  for (option = ppdFirstOption(ppd); option; option = ppdNextOption(ppd))
  {
   /*
    * See if we have a query command for this option...
    */

    snprintf(buffer, sizeof(buffer), "?%s", option->keyword);

    if ((attr = ppdFindAttr(ppd, buffer, NULL)) == NULL || !attr->value)
    {
      fprintf(stderr, "DEBUG: Skipping %s option...\n", option->keyword);
      continue;
    }

   /*
    * Send the query code to the printer...
    */

    fprintf(stderr, "DEBUG: Querying %s...\n", option->keyword);

    for (bufptr = buffer, valptr = attr->value; *valptr; valptr ++)
    {
     /*
      * Log the query code, breaking at newlines...
      */

      if (*valptr == '\n')
      {
        *bufptr = '\0';
        fprintf(stderr, "DEBUG: %s\\n\n", buffer);
        bufptr = buffer;
      }
      else if (*valptr < ' ')
      {
        if (bufptr >= (buffer + sizeof(buffer) - 4))
        {
	  *bufptr = '\0';
	  fprintf(stderr, "DEBUG: %s\n", buffer);
	  bufptr = buffer;
        }

        if (*valptr == '\r')
        {
          *bufptr++ = '\\';
          *bufptr++ = 'r';
        }
        else if (*valptr == '\t')
        {
          *bufptr++ = '\\';
          *bufptr++ = 't';
        }
        else
        {
          *bufptr++ = '\\';
          *bufptr++ = '0' + ((*valptr / 64) & 7);
          *bufptr++ = '0' + ((*valptr / 8) & 7);
          *bufptr++ = '0' + (*valptr & 7);
        }
      }
      else
      {
        if (bufptr >= (buffer + sizeof(buffer) - 1))
        {
	  *bufptr = '\0';
	  fprintf(stderr, "DEBUG: %s\n", buffer);
	  bufptr = buffer;
        }

	*bufptr++ = *valptr;
      }
    }

    if (bufptr > buffer)
    {
      *bufptr = '\0';
      fprintf(stderr, "DEBUG: %s\n", buffer);
    }

    printf("/cups_query_keyword (?%s) def\n", option->keyword);
					/* Set keyword for error reporting */
    fputs("{ (", stdout);
    for (valptr = attr->value; *valptr; valptr ++)
    {
      if (*valptr == '(' || *valptr == ')' || *valptr == '\\')
        putchar('\\');
      putchar(*valptr);
    }
    fputs(") cvx exec } stopped { cups_handleerror } if clear\n", stdout);
    					/* Send query code */
    fflush(stdout);

    datalen = 0;
    cupsSideChannelDoRequest(CUPS_SC_CMD_DRAIN_OUTPUT, buffer, &datalen, 5.0);

   /*
    * Read the response data...
    */

    bufptr    = buffer;
    buffer[0] = '\0';
    while ((bytes = cupsBackChannelRead(bufptr, sizeof(buffer) - (size_t)(bufptr - buffer) - 1, 10.0)) > 0)
    {
     /*
      * No newline at the end? Go on reading ...
      */

      bufptr += bytes;
      *bufptr = '\0';

      if (bytes == 0 ||
          (bufptr > buffer && bufptr[-1] != '\r' && bufptr[-1] != '\n'))
	continue;

     /*
      * Trim whitespace and control characters from both ends...
      */

      bytes = bufptr - buffer;

      for (bufptr --; bufptr >= buffer; bufptr --)
        if (isspace(*bufptr & 255) || iscntrl(*bufptr & 255))
	  *bufptr = '\0';
	else
	  break;

      for (bufptr = buffer; isspace(*bufptr & 255) || iscntrl(*bufptr & 255);
	   bufptr ++);

      if (bufptr > buffer)
      {
        _cups_strcpy(buffer, bufptr);
	bufptr = buffer;
      }

      fprintf(stderr, "DEBUG: Got %d bytes.\n", (int)bytes);

     /*
      * Skip blank lines...
      */

      if (!buffer[0])
        continue;

     /*
      * Check the response...
      */

      if ((bufptr = strchr(buffer, ':')) != NULL)
      {
       /*
        * PostScript code for this option in the PPD is broken; show the
        * interpreter's error message that came back...
        */

	fprintf(stderr, "DEBUG%s\n", bufptr);
	break;
      }

     /*
      * Verify the result is a valid option choice...
      */

      if (!ppdFindChoice(option, buffer))
      {
	if (!strcasecmp(buffer, "Unknown"))
	  break;

	bufptr    = buffer;
	buffer[0] = '\0';
        continue;
      }

     /*
      * Write out the result and move on to the next option...
      */

      fprintf(stderr, "PPD: Default%s=%s\n", option->keyword, buffer);
      break;
    }

   /*
    * Printer did not answer this option's query
    */

    if (bytes <= 0)
    {
      fprintf(stderr,
	      "DEBUG: No answer to query for option %s within 10 seconds.\n",
	      option->keyword);
      status = 1;
    }
  }

 /*
  * Finish the job...
  */

  fflush(stdout);
  end_ps(ppd);

 /*
  * Return...
  */

  if (status)
    _cupsLangPrintFilter(stderr, "WARNING",
                         _("Unable to configure printer options."));

  return (0);
}
Пример #6
0
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);
}
int					/* O - 1 on success, 0 on error */
translate_messages(cups_array_t *cat,	/* I - Message catalog */
                   const char *lang)	/* I - Output language... */
{
 /*
  * Google provides a simple translation/language tool for translating
  * from one language to another.  It is far from perfect, however it
  * can be used to get a basic translation done or update an existing
  * translation when no other resources are available.
  *
  * Translation requests are sent as HTTP POSTs to
  * "http://translate.google.com/translate_t" with the following form
  * variables:
  *
  *   Name      Description                         Value
  *   --------  ----------------------------------  ----------------
  *   hl        Help language?                      "en"
  *   ie        Input encoding                      "UTF8"
  *   langpair  Language pair                       "en|" + language
  *   oe        Output encoding                     "UTF8"
  *   text      Text to translate                   translation string
  */

  int		ret;			/* Return value */
  _cups_message_t *m;			/* Current message */
  int		tries;			/* Number of tries... */
  http_t	*http;			/* HTTP connection */
  http_status_t	status;			/* Status of POST request */
  char		*idptr,			/* Pointer into msgid */
		buffer[65536],		/* Input/output buffer */
		*bufptr,		/* Pointer into buffer */
		*bufend,		/* Pointer to end of buffer */
		length[16];		/* Content length */
  int		bytes;			/* Number of bytes read */


 /*
  * Connect to translate.google.com...
  */

  puts("Connecting to translate.google.com...");

  if ((http = httpConnect("translate.google.com", 80)) == NULL)
  {
    perror("Unable to connect to translate.google.com");
    return (0);
  }

 /*
  * Scan the current messages, requesting a translation of any untranslated
  * messages...
  */

  for (m = (_cups_message_t *)cupsArrayFirst(cat), ret = 1;
       m;
       m = (_cups_message_t *)cupsArrayNext(cat))
  {
   /*
    * Skip messages that are already translated...
    */

    if (m->str && m->str[0])
      continue;

   /*
    * Encode the form data into the buffer...
    */

    snprintf(buffer, sizeof(buffer),
             "hl=en&ie=UTF8&langpair=en|%s&oe=UTF8&text=", lang);
    bufptr = buffer + strlen(buffer);
    bufend = buffer + sizeof(buffer) - 5;

    for (idptr = m->id; *idptr && bufptr < bufend; idptr ++)
      if (*idptr == ' ')
        *bufptr++ = '+';
      else if (*idptr < ' ' || *idptr == '%')
      {
        sprintf(bufptr, "%%%02X", *idptr & 255);
	bufptr += 3;
      }
      else if (*idptr != '&')
        *bufptr++ = *idptr;

    *bufptr++ = '&';
    *bufptr = '\0';

    sprintf(length, "%d", (int)(bufptr - buffer));

   /*
    * Send the request...
    */

    printf("\"%s\" = ", m->id);
    fflush(stdout);

    tries = 0;

    do
    {
      httpClearFields(http);
      httpSetField(http, HTTP_FIELD_CONTENT_TYPE,
                   "application/x-www-form-urlencoded");
      httpSetField(http, HTTP_FIELD_CONTENT_LENGTH, length);

      if (httpPost(http, "/translate_t"))
      {
	httpReconnect(http);
	httpPost(http, "/translate_t");
      }

      httpWrite2(http, buffer, bufptr - buffer);

      while ((status = httpUpdate(http)) == HTTP_CONTINUE);

      if (status != HTTP_OK && status != HTTP_ERROR)
        httpFlush(http);

      tries ++;
    }
    while (status == HTTP_ERROR && tries < 10);

    if (status == HTTP_OK)
    {
     /*
      * OK, read the translation back...
      */

      bufptr = buffer;
      bufend = buffer + sizeof(buffer) - 1;

      while ((bytes = httpRead2(http, bufptr, bufend - bufptr)) > 0)
        bufptr += bytes;

      if (bytes < 0)
      {
       /*
        * Read error, abort!
	*/

        puts("READ ERROR!");
	ret = 0;
	break;
      }

      *bufptr = '\0';

     /*
      * Find the div containing translation
      */

      if ((bufptr = strstr(buffer, "<div id=result_box")) == NULL)
      {
       /*
        * No textarea, abort!
	*/

        puts("NO div id=result_box!");
	ret = 0;
	break;
      }

      if ((bufptr = strchr(bufptr, '>')) == NULL)
      {
       /*
        * textarea doesn't end, abort!
	*/

        puts("DIV SHORT DATA!");
	ret = 0;
	break;
      }

      bufptr ++;

      if ((bufend = strstr(bufptr, "</div>")) == NULL)
      {
       /*
        * textarea doesn't close, abort!
	*/

        puts("/DIV SHORT DATA!");
	ret = 0;
	break;
      }

      *bufend = '\0';

     /*
      * Copy the translation...
      */

      m->str = strdup(bufptr);

     /*
      * Convert character entities to regular chars...
      */

      for (bufptr = strchr(m->str, '&');
           bufptr;
	   bufptr = strchr(bufptr + 1, '&'))
      {
        if (!strncmp(bufptr, "&lt;", 4))
	{
	  *bufptr = '<';
	  _cups_strcpy(bufptr + 1, bufptr + 4);
	}
        else if (!strncmp(bufptr, "&gt;", 4))
	{
	  *bufptr = '>';
	  _cups_strcpy(bufptr + 1, bufptr + 4);
	}
        else if (!strncmp(bufptr, "&amp;", 5))
	  _cups_strcpy(bufptr + 1, bufptr + 5);
      }

      printf("\"%s\"\n", m->str);
    }
    else if (status == HTTP_ERROR)
    {
      printf("NETWORK ERROR (%s)!\n", strerror(httpError(http)));
      ret = 0;
      break;
    }
    else
    {
      printf("HTTP ERROR %d!\n", status);
      ret = 0;
      break;
    }
  }

  httpClose(http);

  return (ret);
}
Пример #8
0
ipp_t *					/* O - Attributes */
serverLoadAttributes(
    const char *filename,		/* I - File to load */
    char       **authtype,		/* O - Authentication type, if any */
    char       **command,		/* O - Command to run, if any */
    char       **device_uri,		/* O - Device URI, if any */
    char       **make,			/* O - Manufacturer */
    char       **model,			/* O - Model */
    char       **proxy_user)		/* O - Proxy user, if any */
{
  ipp_t		*attrs;			/* Attributes to return */
  cups_file_t	*fp;			/* File */
  int		linenum = 0;		/* Current line number */
  char		attr[128],		/* Attribute name */
		token[1024],		/* Token from file */
		*tokenptr;		/* Pointer into token */
  ipp_tag_t	value;			/* Current value type */
  ipp_attribute_t *attrptr;		/* Attribute pointer */


  if ((fp = cupsFileOpen(filename, "r")) == NULL)
  {
    serverLog(SERVER_LOGLEVEL_ERROR, "Unable to open \"%s\": %s", filename, strerror(errno));
    return (NULL);
  }

  attrs = ippNew();

  while (get_token(fp, token, sizeof(token), &linenum) != NULL)
  {
    if (!_cups_strcasecmp(token, "ATTR"))
    {
     /*
      * Attribute...
      */

      if (!get_token(fp, token, sizeof(token), &linenum))
      {
	serverLog(SERVER_LOGLEVEL_ERROR, "Missing ATTR value tag on line %d of \"%s\".", linenum, filename);
        goto load_error;
      }

      if ((value = ippTagValue(token)) == IPP_TAG_ZERO)
      {
	serverLog(SERVER_LOGLEVEL_ERROR, "Bad ATTR value tag \"%s\" on line %d of \"%s\".", token, linenum, filename);
        goto load_error;
      }

      if (!get_token(fp, attr, sizeof(attr), &linenum))
      {
	serverLog(SERVER_LOGLEVEL_ERROR, "Missing ATTR name on line %d of \"%s\".", linenum, filename);
        goto load_error;
      }

      if (!get_token(fp, token, sizeof(token), &linenum))
      {
	serverLog(SERVER_LOGLEVEL_ERROR, "Missing ATTR value on line %d of \"%s\".", linenum, filename);
        goto load_error;
      }

      attrptr = NULL;

      switch (value)
      {
	case IPP_TAG_BOOLEAN :
	    if (!_cups_strcasecmp(token, "true"))
	      attrptr = ippAddBoolean(attrs, IPP_TAG_PRINTER, attr, 1);
	    else
	      attrptr = ippAddBoolean(attrs, IPP_TAG_PRINTER, attr, (char)atoi(token));
	    break;

	case IPP_TAG_INTEGER :
	case IPP_TAG_ENUM :
	    if (!strchr(token, ','))
	      attrptr = ippAddInteger(attrs, IPP_TAG_PRINTER, value, attr, (int)strtol(token, &tokenptr, 0));
	    else
	    {
	      int	values[100],	/* Values */
			num_values = 1;	/* Number of values */

	      values[0] = (int)strtol(token, &tokenptr, 10);
	      while (tokenptr && *tokenptr &&
		     num_values < (int)(sizeof(values) / sizeof(values[0])))
	      {
		if (*tokenptr == ',')
		  tokenptr ++;
		else if (!isdigit(*tokenptr & 255) && *tokenptr != '-')
		  break;

		values[num_values] = (int)strtol(tokenptr, &tokenptr, 0);
		num_values ++;
	      }

	      attrptr = ippAddIntegers(attrs, IPP_TAG_PRINTER, value, attr, num_values, values);
	    }

	    if (!tokenptr || *tokenptr)
	    {
	      serverLog(SERVER_LOGLEVEL_ERROR, "Bad %s value \"%s\" on line %d of \"%s\".", ippTagString(value), token, linenum, filename);
              goto load_error;
	    }
	    break;

	case IPP_TAG_RESOLUTION :
	    {
	      int	xres,		/* X resolution */
			yres;		/* Y resolution */
	      ipp_res_t	units;		/* Units */
	      char	*start,		/* Start of value */
			*ptr,		/* Pointer into value */
			*next = NULL;	/* Next value */

	      for (start = token; start; start = next)
	      {
		xres = yres = (int)strtol(start, (char **)&ptr, 10);
		if (ptr > start && xres > 0)
		{
		  if (*ptr == 'x')
		    yres = (int)strtol(ptr + 1, (char **)&ptr, 10);
		}

		if (ptr && (next = strchr(ptr, ',')) != NULL)
		  *next++ = '\0';

		if (ptr <= start || xres <= 0 || yres <= 0 || !ptr ||
		    (_cups_strcasecmp(ptr, "dpi") &&
		     _cups_strcasecmp(ptr, "dpc") &&
		     _cups_strcasecmp(ptr, "dpcm") &&
		     _cups_strcasecmp(ptr, "other")))
		{
		  serverLog(SERVER_LOGLEVEL_ERROR, "Bad resolution value \"%s\" on line %d of \"%s\".", token, linenum, filename);
                  goto load_error;
		}

		if (!_cups_strcasecmp(ptr, "dpc") || !_cups_strcasecmp(ptr, "dpcm"))
		  units = IPP_RES_PER_CM;
		else
		  units = IPP_RES_PER_INCH;

                if (attrptr)
		  ippSetResolution(attrs, &attrptr, ippGetCount(attrptr), units, xres, yres);
		else
		  attrptr = ippAddResolution(attrs, IPP_TAG_PRINTER, attr, units, xres, yres);
	      }
	    }
	    break;

	case IPP_TAG_RANGE :
	    {
	      int	lowers[4],	/* Lower value */
			uppers[4],	/* Upper values */
			num_vals;	/* Number of values */


	      num_vals = sscanf(token, "%d-%d,%d-%d,%d-%d,%d-%d",
				lowers + 0, uppers + 0,
				lowers + 1, uppers + 1,
				lowers + 2, uppers + 2,
				lowers + 3, uppers + 3);

	      if ((num_vals & 1) || num_vals == 0)
	      {
		serverLog(SERVER_LOGLEVEL_ERROR, "Bad rangeOfInteger value \"%s\" on line %d of \"%s\".", token, linenum, filename);
                goto load_error;
	      }

	      attrptr = ippAddRanges(attrs, IPP_TAG_PRINTER, attr, num_vals / 2, lowers,
				     uppers);
	    }
	    break;

	case IPP_TAG_BEGIN_COLLECTION :
	    if (!strcmp(token, "{"))
	    {
	      ipp_t	*col = get_collection(fp, filename, &linenum);
				    /* Collection value */

	      if (col)
	      {
		attrptr = ippAddCollection(attrs, IPP_TAG_PRINTER, attr, col);
		ippDelete(col);
	      }
	      else
		exit(1);
	    }
	    else
	    {
	      serverLog(SERVER_LOGLEVEL_ERROR, "Bad ATTR collection value on line %d of \"%s\".", linenum, filename);
              goto load_error;
	    }

	    do
	    {
	      ipp_t	*col;			/* Collection value */
	      long	pos = cupsFileTell(fp);	/* Save position of file */

	      if (!get_token(fp, token, sizeof(token), &linenum))
		break;

	      if (strcmp(token, ","))
	      {
		cupsFileSeek(fp, pos);
		break;
	      }

	      if (!get_token(fp, token, sizeof(token), &linenum) || strcmp(token, "{"))
	      {
		serverLog(SERVER_LOGLEVEL_ERROR, "Unexpected \"%s\" on line %d of \"%s\".", token, linenum, filename);
                goto load_error;
	      }

	      if ((col = get_collection(fp, filename, &linenum)) == NULL)
		break;

	      ippSetCollection(attrs, &attrptr, ippGetCount(attrptr), col);
	    }
	    while (!strcmp(token, "{"));
	    break;

	case IPP_TAG_STRING :
	    attrptr = ippAddOctetString(attrs, IPP_TAG_PRINTER, attr, token, (int)strlen(token));
	    break;

	default :
	    serverLog(SERVER_LOGLEVEL_ERROR, "Unsupported ATTR value tag %s on line %d of \"%s\".", ippTagString(value), linenum, filename);
            goto load_error;

	case IPP_TAG_TEXTLANG :
	case IPP_TAG_NAMELANG :
	case IPP_TAG_TEXT :
	case IPP_TAG_NAME :
	case IPP_TAG_KEYWORD :
	case IPP_TAG_URI :
	case IPP_TAG_URISCHEME :
	case IPP_TAG_CHARSET :
	case IPP_TAG_LANGUAGE :
	case IPP_TAG_MIMETYPE :
	    if (!strchr(token, ','))
	      attrptr = ippAddString(attrs, IPP_TAG_PRINTER, value, attr, NULL, token);
	    else
	    {
	     /*
	      * Multiple string values...
	      */

	      int	num_values;	/* Number of values */
	      char	*values[100],	/* Values */
			*ptr;		/* Pointer to next value */


	      values[0]  = token;
	      num_values = 1;

	      for (ptr = strchr(token, ','); ptr; ptr = strchr(ptr, ','))
	      {
		if (ptr > token && ptr[-1] == '\\')
		  _cups_strcpy(ptr - 1, ptr);
		else
		{
		  *ptr++ = '\0';
		  values[num_values] = ptr;
		  num_values ++;
		  if (num_values >= (int)(sizeof(values) / sizeof(values[0])))
		    break;
		}
	      }

	      attrptr = ippAddStrings(attrs, IPP_TAG_PRINTER, value, attr, num_values, NULL, (const char **)values);
	    }
	    break;
      }

      if (!attrptr)
      {
        serverLog(SERVER_LOGLEVEL_ERROR, "Unable to add attribute on line %d of \"%s\": %s", linenum, filename, cupsLastErrorString());
        goto load_error;
      }
    }
    else if (!_cups_strcasecmp(token, "AUTHTYPE") && authtype)
    {
      if (!get_token(fp, token, sizeof(token), &linenum))
      {
	serverLog(SERVER_LOGLEVEL_ERROR, "Missing AUTHTYPE value on line %d of \"%s\".", linenum, filename);
        goto load_error;
      }

      *authtype = strdup(token);
    }
    else if (!_cups_strcasecmp(token, "COMMAND") && command)
    {
      if (!get_token(fp, token, sizeof(token), &linenum))
      {
	serverLog(SERVER_LOGLEVEL_ERROR, "Missing COMMAND value on line %d of \"%s\".", linenum, filename);
        goto load_error;
      }

      *command = strdup(token);
    }
    else if (!_cups_strcasecmp(token, "DEVICEURI") && device_uri)
    {
      if (!get_token(fp, token, sizeof(token), &linenum))
      {
	serverLog(SERVER_LOGLEVEL_ERROR, "Missing DEVICE-URI value on line %d of \"%s\".", linenum, filename);
        goto load_error;
      }

      *device_uri = strdup(token);
    }
    else if (!_cups_strcasecmp(token, "MAKE") && make)
    {
      if (!get_token(fp, token, sizeof(token), &linenum))
      {
	serverLog(SERVER_LOGLEVEL_ERROR, "Missing MAKE value on line %d of \"%s\".", linenum, filename);
        goto load_error;
      }

      *make = strdup(token);
    }
    else if (!_cups_strcasecmp(token, "MODEL") && model)
    {
      if (!get_token(fp, token, sizeof(token), &linenum))
      {
	serverLog(SERVER_LOGLEVEL_ERROR, "Missing MODEL value on line %d of \"%s\".", linenum, filename);
        goto load_error;
      }

      *model = strdup(token);
    }
    else if (!_cups_strcasecmp(token, "PROXYUSER") && proxy_user)
    {
      if (!get_token(fp, token, sizeof(token), &linenum))
      {
	serverLog(SERVER_LOGLEVEL_ERROR, "Missing PROXY-USER value on line %d of \"%s\".", linenum, filename);
        goto load_error;
      }

      *proxy_user = strdup(token);
    }
    else
    {
      serverLog(SERVER_LOGLEVEL_ERROR, "Unknown directive \"%s\" on line %d of \"%s\".", token, linenum, filename);
      goto load_error;
    }
  }

  cupsFileClose(fp);

  return (attrs);

 /*
  * If we get here something bad happened...
  */

  load_error:

  cupsFileClose(fp);

  ippDelete(attrs);

  return (NULL);
}
Пример #9
0
char *					/* O  - Line read or @code NULL@ on end of file or error */
cupsFileGetConf(cups_file_t *fp,	/* I  - CUPS file */
                char        *buf,	/* O  - String buffer */
		size_t      buflen,	/* I  - Size of string buffer */
                char        **value,	/* O  - Pointer to value */
		int         *linenum)	/* IO - Current line number */
{
  char	*ptr;				/* Pointer into line */


 /*
  * Range check input...
  */

  DEBUG_printf(("2cupsFileGetConf(fp=%p, buf=%p, buflen=" CUPS_LLFMT
                ", value=%p, linenum=%p)", fp, buf, CUPS_LLCAST buflen,
		value, linenum));

  if (!fp || (fp->mode != 'r' && fp->mode != 's') ||
      !buf || buflen < 2 || !value)
  {
    if (value)
      *value = NULL;

    return (NULL);
  }

 /*
  * Read the next non-comment line...
  */

  *value = NULL;

  while (cupsFileGets(fp, buf, buflen))
  {
    (*linenum) ++;

   /*
    * Strip any comments...
    */

    if ((ptr = strchr(buf, '#')) != NULL)
    {
      if (ptr > buf && ptr[-1] == '\\')
      {
        // Unquote the #...
	_cups_strcpy(ptr - 1, ptr);
      }
      else
      {
        // Strip the comment and any trailing whitespace...
	while (ptr > buf)
	{
	  if (!_cups_isspace(ptr[-1]))
	    break;

	  ptr --;
	}

	*ptr = '\0';
      }
    }

   /*
    * Strip leading whitespace...
    */

    for (ptr = buf; _cups_isspace(*ptr); ptr ++);

    if (ptr > buf)
      _cups_strcpy(buf, ptr);

   /*
    * See if there is anything left...
    */

    if (buf[0])
    {
     /*
      * Yes, grab any value and return...
      */

      for (ptr = buf; *ptr; ptr ++)
        if (_cups_isspace(*ptr))
	  break;

      if (*ptr)
      {
       /*
        * Have a value, skip any other spaces...
	*/

        while (_cups_isspace(*ptr))
	  *ptr++ = '\0';

        if (*ptr)
	  *value = ptr;

       /*
        * Strip trailing whitespace and > for lines that begin with <...
	*/

        ptr += strlen(ptr) - 1;

        if (buf[0] == '<' && *ptr == '>')
	  *ptr-- = '\0';
	else if (buf[0] == '<' && *ptr != '>')
        {
	 /*
	  * Syntax error...
	  */

	  *value = NULL;
	  return (buf);
	}

        while (ptr > *value && _cups_isspace(*ptr))
	  *ptr-- = '\0';
      }

     /*
      * Return the line...
      */

      return (buf);
    }
  }

  return (NULL);
}
Пример #10
0
Файл: attr.c Проект: ezeep/cups
char *					/* O - Normalized make-and-model string or NULL on error */
_ppdNormalizeMakeAndModel(
    const char *make_and_model,		/* I - Original make-and-model string */
    char       *buffer,			/* I - String buffer */
    size_t     bufsize)			/* I - Size of string buffer */
{
  char	*bufptr;			/* Pointer into buffer */


  if (!make_and_model || !buffer || bufsize < 1)
  {
    if (buffer)
      *buffer = '\0';

    return (NULL);
  }

 /*
  * Skip leading whitespace...
  */

  while (_cups_isspace(*make_and_model))
    make_and_model ++;

 /*
  * Remove parenthesis and add manufacturers as needed...
  */

  if (make_and_model[0] == '(')
  {
    strlcpy(buffer, make_and_model + 1, bufsize);

    if ((bufptr = strrchr(buffer, ')')) != NULL)
      *bufptr = '\0';
  }
  else if (!_cups_strncasecmp(make_and_model, "XPrint", 6))
  {
   /*
    * Xerox XPrint...
    */

    snprintf(buffer, bufsize, "Xerox %s", make_and_model);
  }
  else if (!_cups_strncasecmp(make_and_model, "Eastman", 7))
  {
   /*
    * Kodak...
    */

    snprintf(buffer, bufsize, "Kodak %s", make_and_model + 7);
  }
  else if (!_cups_strncasecmp(make_and_model, "laserwriter", 11))
  {
   /*
    * Apple LaserWriter...
    */

    snprintf(buffer, bufsize, "Apple LaserWriter%s", make_and_model + 11);
  }
  else if (!_cups_strncasecmp(make_and_model, "colorpoint", 10))
  {
   /*
    * Seiko...
    */

    snprintf(buffer, bufsize, "Seiko %s", make_and_model);
  }
  else if (!_cups_strncasecmp(make_and_model, "fiery", 5))
  {
   /*
    * EFI...
    */

    snprintf(buffer, bufsize, "EFI %s", make_and_model);
  }
  else if (!_cups_strncasecmp(make_and_model, "ps ", 3) ||
	   !_cups_strncasecmp(make_and_model, "colorpass", 9))
  {
   /*
    * Canon...
    */

    snprintf(buffer, bufsize, "Canon %s", make_and_model);
  }
  else if (!_cups_strncasecmp(make_and_model, "primera", 7))
  {
   /*
    * Fargo...
    */

    snprintf(buffer, bufsize, "Fargo %s", make_and_model);
  }
  else if (!_cups_strncasecmp(make_and_model, "designjet", 9) ||
           !_cups_strncasecmp(make_and_model, "deskjet", 7))
  {
   /*
    * HP...
    */

    snprintf(buffer, bufsize, "HP %s", make_and_model);
  }
  else
    strlcpy(buffer, make_and_model, bufsize);

 /*
  * Clean up the make...
  */

  if (!_cups_strncasecmp(buffer, "agfa", 4))
  {
   /*
    * Replace with AGFA (all uppercase)...
    */

    buffer[0] = 'A';
    buffer[1] = 'G';
    buffer[2] = 'F';
    buffer[3] = 'A';
  }
  else if (!_cups_strncasecmp(buffer, "Hewlett-Packard hp ", 19))
  {
   /*
    * Just put "HP" on the front...
    */

    buffer[0] = 'H';
    buffer[1] = 'P';
    _cups_strcpy(buffer + 2, buffer + 18);
  }
  else if (!_cups_strncasecmp(buffer, "Hewlett-Packard ", 16))
  {
   /*
    * Just put "HP" on the front...
    */

    buffer[0] = 'H';
    buffer[1] = 'P';
    _cups_strcpy(buffer + 2, buffer + 15);
  }
  else if (!_cups_strncasecmp(buffer, "Lexmark International", 21))
  {
   /*
    * Strip "International"...
    */

    _cups_strcpy(buffer + 8, buffer + 21);
  }
  else if (!_cups_strncasecmp(buffer, "herk", 4))
  {
   /*
    * Replace with LHAG...
    */

    buffer[0] = 'L';
    buffer[1] = 'H';
    buffer[2] = 'A';
    buffer[3] = 'G';
  }
  else if (!_cups_strncasecmp(buffer, "linotype", 8))
  {
   /*
    * Replace with LHAG...
    */

    buffer[0] = 'L';
    buffer[1] = 'H';
    buffer[2] = 'A';
    buffer[3] = 'G';
    _cups_strcpy(buffer + 4, buffer + 8);
  }

 /*
  * Remove trailing whitespace and return...
  */

  for (bufptr = buffer + strlen(buffer) - 1;
       bufptr >= buffer && _cups_isspace(*bufptr);
       bufptr --);

  bufptr[1] = '\0';

  return (buffer[0] ? buffer : NULL);
}
Пример #11
0
static int				/* O - 0 on success, -1 on error */
get_device(cupsd_backend_t *backend)	/* I - Backend to read from */
{
  char	line[2048],			/* Line from backend */
	temp[2048],			/* Copy of line */
	*ptr,				/* Pointer into line */
	*dclass,			/* Device class */
	*uri,				/* Device URI */
	*make_model,			/* Make and model */
	*info,				/* Device info */
	*device_id,			/* 1284 device ID */
	*location;			/* Physical location */


  if (cupsFileGets(backend->pipe, line, sizeof(line)))
  {
   /*
    * Each line is of the form:
    *
    *   class URI "make model" "name" ["1284 device ID"] ["location"]
    */

    strlcpy(temp, line, sizeof(temp));

   /*
    * device-class
    */

    dclass = temp;

    for (ptr = temp; *ptr; ptr ++)
      if (isspace(*ptr & 255))
        break;

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

   /*
    * device-uri
    */

    if (!*ptr)
      goto error;

    for (uri = ptr; *ptr; ptr ++)
      if (isspace(*ptr & 255))
        break;

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

   /*
    * device-make-and-model
    */

    if (*ptr != '\"')
      goto error;

    for (ptr ++, make_model = ptr; *ptr && *ptr != '\"'; ptr ++)
    {
      if (*ptr == '\\' && ptr[1])
        _cups_strcpy(ptr, ptr + 1);
    }

    if (*ptr != '\"')
      goto error;

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

   /*
    * device-info
    */

    if (*ptr != '\"')
      goto error;

    for (ptr ++, info = ptr; *ptr && *ptr != '\"'; ptr ++)
    {
      if (*ptr == '\\' && ptr[1])
        _cups_strcpy(ptr, ptr + 1);
    }

    if (*ptr != '\"')
      goto error;

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

   /*
    * device-id
    */

    if (*ptr == '\"')
    {
      for (ptr ++, device_id = ptr; *ptr && *ptr != '\"'; ptr ++)
      {
	if (*ptr == '\\' && ptr[1])
	  _cups_strcpy(ptr, ptr + 1);
      }

      if (*ptr != '\"')
	goto error;

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

     /*
      * device-location
      */

      if (*ptr == '\"')
      {
	for (ptr ++, location = ptr; *ptr && *ptr != '\"'; ptr ++)
	{
	  if (*ptr == '\\' && ptr[1])
	    _cups_strcpy(ptr, ptr + 1);
	}

	if (*ptr != '\"')
	  goto error;

	*ptr = '\0';
      }
      else
        location = NULL;
    }
    else
    {
      device_id = NULL;
      location  = NULL;
    }

   /*
    * Add the device to the array of available devices...
    */

    if (!add_device(dclass, make_model, info, uri, device_id, location))
      fprintf(stderr, "DEBUG: [cups-deviced] Found device \"%s\"...\n", uri);

    return (0);
  }

 /*
  * End of file...
  */

  cupsFileClose(backend->pipe);
  backend->pipe = NULL;

  return (-1);

 /*
  * Bad format; strip trailing newline and write an error message.
  */

  error:

  if (line[strlen(line) - 1] == '\n')
    line[strlen(line) - 1] = '\0';

  fprintf(stderr, "ERROR: [cups-deviced] Bad line from \"%s\": %s\n",
	  backend->name, line);
  return (0);
}
Пример #12
0
static void
add_printer_filter(
    const char  *command,		/* I - Command name */
    mime_t      *mime,			/* I - MIME database */
    mime_type_t *filtertype,		/* I - Printer or prefilter MIME type */
    const char  *filter)		/* I - Filter to add */
{
  char		super[MIME_MAX_SUPER],	/* Super-type for filter */
		type[MIME_MAX_TYPE],	/* Type for filter */
		dsuper[MIME_MAX_SUPER],	/* Destination super-type for filter */
		dtype[MIME_MAX_TYPE],	/* Destination type for filter */
		dest[MIME_MAX_SUPER + MIME_MAX_TYPE + 2],
					/* Destination super/type */
		program[1024];		/* Program/filter name */
  int		cost;			/* Cost of filter */
  size_t	maxsize = 0;		/* Maximum supported file size */
  mime_type_t	*temptype,		/* MIME type looping var */
		*desttype;		/* Destination MIME type */
  mime_filter_t	*filterptr;		/* MIME filter */


 /*
  * Parse the filter string; it should be in one of the following formats:
  *
  *     source/type cost program
  *     source/type cost maxsize(nnnn) program
  *     source/type dest/type cost program
  *     source/type dest/type cost maxsize(nnnn) program
  */

  if (sscanf(filter, "%15[^/]/%255s%*[ \t]%15[^/]/%255s%d%*[ \t]%1023[^\n]",
             super, type, dsuper, dtype, &cost, program) == 6)
  {
    snprintf(dest, sizeof(dest), "%s/%s/%s", filtertype->type, dsuper, dtype);

    if ((desttype = mimeType(mime, "printer", dest)) == NULL)
      desttype = mimeAddType(mime, "printer", dest);
  }
  else
  {
    if (sscanf(filter, "%15[^/]/%255s%d%*[ \t]%1023[^\n]", super, type, &cost,
               program) == 4)
    {
      desttype = filtertype;
    }
    else
    {
      _cupsLangPrintf(stderr, _("%s: Invalid filter string \"%s\"."), command,
		      filter);
      return;
    }
  }

  if (!strncmp(program, "maxsize(", 8))
  {
    char	*ptr;			/* Pointer into maxsize(nnnn) program */

    maxsize = (size_t)strtoll(program + 8, &ptr, 10);

    if (*ptr != ')')
    {
      printf("testmime: Invalid filter string \"%s\".\n", filter);
      return;
    }

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

    _cups_strcpy(program, ptr);
  }

 /*
  * See if the filter program exists; if not, stop the printer and flag
  * the error!
  */

  if (strcmp(program, "-"))
  {
    char filename[1024];		/* Full path to program */

    if (program[0] == '/')
      strlcpy(filename, program, sizeof(filename));
    else
      snprintf(filename, sizeof(filename), "%s/filter/%s", ServerBin, program);

    if (_cupsFileCheck(filename, _CUPS_FILE_CHECK_PROGRAM, !geteuid(), check_cb,
                       (void *)command))
      return;
  }

 /*
  * Add the filter to the MIME database, supporting wildcards as needed...
  */

  for (temptype = mimeFirstType(mime);
       temptype;
       temptype = mimeNextType(mime))
    if (((super[0] == '*' && _cups_strcasecmp(temptype->super, "printer")) ||
         !_cups_strcasecmp(temptype->super, super)) &&
        (type[0] == '*' || !_cups_strcasecmp(temptype->type, type)))
    {
      if (desttype != filtertype)
      {
        filterptr = mimeAddFilter(mime, temptype, desttype, cost, program);

        if (!mimeFilterLookup(mime, desttype, filtertype))
          mimeAddFilter(mime, desttype, filtertype, 0, "-");
      }
      else
        filterptr = mimeAddFilter(mime, temptype, filtertype, cost, program);

      if (filterptr)
	filterptr->maxsize = maxsize;
    }
}
Пример #13
0
Файл: lpc.c Проект: lanceit/cups
int
main(int  argc,				/* I - Number of command-line arguments */
     char *argv[])			/* I - Command-line arguments */
{
  http_t	*http;			/* Connection to server */
  char		line[1024],		/* Input line from user */
		*params;		/* Pointer to parameters */


  _cupsSetLocale(argv);

 /*
  * Connect to the scheduler...
  */

  http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption());

  if (argc > 1)
  {
   /*
    * Process a single command on the command-line...
    */

    do_command(http, argv[1], argv[2]);
  }
  else
  {
   /*
    * Do the command prompt thing...
    */

    _cupsLangPuts(stdout, _("lpc> ")); /* TODO: Need no-newline version */
    while (fgets(line, sizeof(line), stdin) != NULL)
    {
     /*
      * Strip trailing whitespace...
      */

      for (params = line + strlen(line) - 1; params >= line;)
        if (!isspace(*params & 255))
	  break;
	else
	  *params-- = '\0';

     /*
      * Strip leading whitespace...
      */

      for (params = line; isspace(*params & 255); params ++);

      if (params > line)
        _cups_strcpy(line, params);

      if (!line[0])
      {
       /*
        * Nothing left, just show a prompt...
	*/

	_cupsLangPuts(stdout, _("lpc> ")); /* TODO: Need no newline version */
	continue;
      }

     /*
      * Find any options in the string...
      */

      for (params = line; *params != '\0'; params ++)
        if (isspace(*params & 255))
	  break;

     /*
      * Remove whitespace between the command and parameters...
      */

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

     /*
      * The "quit" and "exit" commands exit; otherwise, process as needed...
      */

      if (!compare_strings(line, "quit", 1) ||
          !compare_strings(line, "exit", 2))
        break;

      if (*params == '\0')
        do_command(http, line, NULL);
      else
        do_command(http, line, params);

     /*
      * Put another prompt out to the user...
      */

      _cupsLangPuts(stdout, _("lpc> ")); /* TODO: Need no newline version */
    }
  }

 /*
  * Close the connection to the server and return...
  */

  httpClose(http);

  return (0);
}
Пример #14
0
static void
fix_make_model(
    char       *make_model,		/* I - New make-and-model string */
    const char *old_make_model,		/* I - Old make-and-model string */
    int        make_model_size)		/* I - Size of new string buffer */
{
  char	*mmptr;				/* Pointer into make-and-model string */


 /*
  * Fix some common problems with the make-and-model string so
  * that printer driver detection works better...
  */

  if (!_cups_strncasecmp(old_make_model, "Hewlett-Packard", 15))
  {
   /*
    * Strip leading Hewlett-Packard and hp prefixes and replace
    * with a single HP manufacturer prefix...
    */

    mmptr = (char *)old_make_model + 15;

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

    if (!_cups_strncasecmp(mmptr, "hp", 2))
    {
      mmptr += 2;

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

    make_model[0] = 'H';
    make_model[1] = 'P';
    make_model[2] = ' ';
    strlcpy(make_model + 3, mmptr, (size_t)make_model_size - 3);
  }
  else if (!_cups_strncasecmp(old_make_model, "deskjet", 7))
    snprintf(make_model, (size_t)make_model_size, "HP DeskJet%s", old_make_model + 7);
  else if (!_cups_strncasecmp(old_make_model, "officejet", 9))
    snprintf(make_model, (size_t)make_model_size, "HP OfficeJet%s", old_make_model + 9);
  else if (!_cups_strncasecmp(old_make_model, "stylus_pro_", 11))
    snprintf(make_model, (size_t)make_model_size, "EPSON Stylus Pro %s", old_make_model + 11);
  else
    strlcpy(make_model, old_make_model, (size_t)make_model_size);

  if ((mmptr = strstr(make_model, ", Inc.,")) != NULL)
  {
   /*
    * Strip inc. from name, e.g. "Tektronix, Inc., Phaser 560"
    * becomes "Tektronix Phaser 560"...
    */

    _cups_strcpy(mmptr, mmptr + 7);
  }

  if ((mmptr = strstr(make_model, " Network")) != NULL)
  {
   /*
    * Drop unnecessary informational text, e.g. "Xerox DocuPrint N2025
    * Network LaserJet - 2.12" becomes "Xerox DocuPrint N2025"...
    */

    *mmptr = '\0';
  }

  if ((mmptr = strchr(make_model, ',')) != NULL)
  {
   /*
    * Drop anything after a trailing comma...
    */

    *mmptr = '\0';
  }
}
Пример #15
0
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);
    }
  }
}
Пример #16
0
static void
query_callback(
    DNSServiceRef       sdRef,		/* I - Service reference */
    DNSServiceFlags     flags,		/* I - Data flags */
    uint32_t            interfaceIndex,	/* I - Interface */
    DNSServiceErrorType errorCode,	/* I - Error, if any */
    const char          *fullName,	/* I - Full service name */
    uint16_t            rrtype,		/* I - Record type */
    uint16_t            rrclass,	/* I - Record class */
    uint16_t            rdlen,		/* I - Length of record data */
    const void          *rdata,		/* I - Record data */
    uint32_t            ttl,		/* I - Time-to-live */
    void                *context)	/* I - Device */
{
#  else
/*
 * 'query_callback()' - Process query data.
 */

static void
query_callback(
    AvahiRecordBrowser     *browser,	/* I - Record browser */
    AvahiIfIndex           interfaceIndex,
					/* I - Interface index (unused) */
    AvahiProtocol          protocol,	/* I - Network protocol (unused) */
    AvahiBrowserEvent      event,	/* I - What happened? */
    const char             *fullName,	/* I - Service name */
    uint16_t               rrclass,	/* I - Record class */
    uint16_t               rrtype,	/* I - Record type */
    const void             *rdata,	/* I - TXT record */
    size_t                 rdlen,	/* I - Length of TXT record */
    AvahiLookupResultFlags flags,	/* I - Flags */
    void                   *context)	/* I - Device */
{
  AvahiClient		*client = avahi_record_browser_get_client(browser);
					/* Client information */
#  endif /* HAVE_DNSSD */
  char		*ptr;			/* Pointer into string */
  cups_device_t	*device = (cups_device_t *)context;
					/* Device */
  const uint8_t	*data,			/* Pointer into data */
		*datanext,		/* Next key/value pair */
		*dataend;		/* End of entire TXT record */
  uint8_t	datalen;		/* Length of current key/value pair */
  char		key[256],		/* Key string */
		value[256],		/* Value string */
		make_and_model[512],	/* Manufacturer and model */
		model[256],		/* Model */
		pdl[256],		/* PDL */
		device_id[2048];	/* 1284 device ID */


#  ifdef HAVE_DNSSD
  fprintf(stderr, "DEBUG2: query_callback(sdRef=%p, flags=%x, "
                  "interfaceIndex=%d, errorCode=%d, fullName=\"%s\", "
		  "rrtype=%u, rrclass=%u, rdlen=%u, rdata=%p, ttl=%u, "
		  "context=%p)\n",
          sdRef, flags, interfaceIndex, errorCode, fullName, rrtype, rrclass, rdlen, rdata, ttl, context);

 /*
  * Only process "add" data...
  */

  if (errorCode != kDNSServiceErr_NoError || !(flags & kDNSServiceFlagsAdd))
    return;

#  else
  fprintf(stderr, "DEBUG2: query_callback(browser=%p, interfaceIndex=%d, "
                  "protocol=%d, event=%d, fullName=\"%s\", rrclass=%u, "
		  "rrtype=%u, rdata=%p, rdlen=%u, flags=%x, context=%p)\n",
          browser, interfaceIndex, protocol, event, fullName, rrclass, rrtype, rdata, (unsigned)rdlen, flags, context);

 /*
  * Only process "add" data...
  */

  if (event != AVAHI_BROWSER_NEW)
  {
    if (event == AVAHI_BROWSER_FAILURE)
      fprintf(stderr, "ERROR: %s\n",
	      avahi_strerror(avahi_client_errno(client)));

    return;
  }
#  endif /* HAVE_DNSSD */

 /*
  * Pull out the priority and make and model from the TXT
  * record and save it...
  */

  device_id[0]      = '\0';
  make_and_model[0] = '\0';
  pdl[0]            = '\0';

  strlcpy(model, "Unknown", sizeof(model));

  for (data = rdata, dataend = data + rdlen;
       data < dataend;
       data = datanext)
  {
   /*
    * Read a key/value pair starting with an 8-bit length.  Since the
    * length is 8 bits and the size of the key/value buffers is 256, we
    * don't need to check for overflow...
    */

    datalen = *data++;

    if (!datalen || (data + datalen) > dataend)
      break;

    datanext = data + datalen;

    for (ptr = key; data < datanext && *data != '='; data ++)
      *ptr++ = (char)*data;
    *ptr = '\0';

    if (data < datanext && *data == '=')
    {
      data ++;

      if (data < datanext)
	memcpy(value, data, (size_t)(datanext - data));
      value[datanext - data] = '\0';

      fprintf(stderr, "DEBUG2: query_callback: \"%s=%s\".\n",
	      key, value);
    }
    else
    {
      fprintf(stderr, "DEBUG2: query_callback: \"%s\" with no value.\n",
	      key);
      continue;
    }

    if (!_cups_strncasecmp(key, "usb_", 4))
    {
     /*
      * Add USB device ID information...
      */

      ptr = device_id + strlen(device_id);
      snprintf(ptr, sizeof(device_id) - (size_t)(ptr - device_id), "%s:%s;", key + 4, value);
    }

    if (!_cups_strcasecmp(key, "usb_MFG") || !_cups_strcasecmp(key, "usb_MANU") ||
	!_cups_strcasecmp(key, "usb_MANUFACTURER"))
      strlcpy(make_and_model, value, sizeof(make_and_model));
    else if (!_cups_strcasecmp(key, "usb_MDL") || !_cups_strcasecmp(key, "usb_MODEL"))
      strlcpy(model, value, sizeof(model));
    else if (!_cups_strcasecmp(key, "product") && !strstr(value, "Ghostscript"))
    {
      if (value[0] == '(')
      {
       /*
	* Strip parenthesis...
	*/

	if ((ptr = value + strlen(value) - 1) > value && *ptr == ')')
	  *ptr = '\0';

	strlcpy(model, value + 1, sizeof(model));
      }
      else
	strlcpy(model, value, sizeof(model));
    }
    else if (!_cups_strcasecmp(key, "ty"))
    {
      strlcpy(model, value, sizeof(model));

      if ((ptr = strchr(model, ',')) != NULL)
	*ptr = '\0';
    }
    else if (!_cups_strcasecmp(key, "pdl"))
      strlcpy(pdl, value, sizeof(pdl));
    else if (!_cups_strcasecmp(key, "priority"))
      device->priority = atoi(value);
    else if ((device->type == CUPS_DEVICE_IPP ||
	      device->type == CUPS_DEVICE_IPPS ||
	      device->type == CUPS_DEVICE_PRINTER) &&
	     !_cups_strcasecmp(key, "printer-type"))
    {
     /*
      * This is a CUPS printer!
      */

      device->cups_shared = 1;

      if (device->type == CUPS_DEVICE_PRINTER)
	device->sent = 1;
    }
    else if (!_cups_strcasecmp(key, "UUID"))
      device->uuid = strdup(value);
  }

  if (device->device_id)
    free(device->device_id);

  if (!device_id[0] && strcmp(model, "Unknown"))
  {
    if (make_and_model[0])
      snprintf(device_id, sizeof(device_id), "MFG:%s;MDL:%s;",
	       make_and_model, model);
    else if (!_cups_strncasecmp(model, "designjet ", 10))
      snprintf(device_id, sizeof(device_id), "MFG:HP;MDL:%s;", model + 10);
    else if (!_cups_strncasecmp(model, "stylus ", 7))
      snprintf(device_id, sizeof(device_id), "MFG:EPSON;MDL:%s;", model + 7);
    else if ((ptr = strchr(model, ' ')) != NULL)
    {
     /*
      * Assume the first word is the make...
      */

      memcpy(make_and_model, model, (size_t)(ptr - model));
      make_and_model[ptr - model] = '\0';

      snprintf(device_id, sizeof(device_id), "MFG:%s;MDL:%s;",
	       make_and_model, ptr + 1);
    }
  }

  if (device_id[0] &&
      !strstr(device_id, "CMD:") &&
      !strstr(device_id, "COMMAND SET:") &&
      (strstr(pdl, "application/pdf") ||
       strstr(pdl, "application/postscript") ||
       strstr(pdl, "application/vnd.hp-PCL") ||
       strstr(pdl, "image/")))
  {
    value[0] = '\0';
    if (strstr(pdl, "application/pdf"))
      strlcat(value, ",PDF", sizeof(value));
    if (strstr(pdl, "application/postscript"))
      strlcat(value, ",PS", sizeof(value));
    if (strstr(pdl, "application/vnd.hp-PCL"))
      strlcat(value, ",PCL", sizeof(value));
    for (ptr = strstr(pdl, "image/"); ptr; ptr = strstr(ptr, "image/"))
    {
      char *valptr = value + strlen(value);
      					/* Pointer into value */

      if (valptr < (value + sizeof(value) - 1))
        *valptr++ = ',';

      ptr += 6;
      while (isalnum(*ptr & 255) || *ptr == '-' || *ptr == '.')
      {
        if (isalnum(*ptr & 255) && valptr < (value + sizeof(value) - 1))
          *valptr++ = (char)toupper(*ptr++ & 255);
        else
          break;
      }

      *valptr = '\0';
    }

    ptr = device_id + strlen(device_id);
    snprintf(ptr, sizeof(device_id) - (size_t)(ptr - device_id), "CMD:%s;", value + 1);
  }

  if (device_id[0])
    device->device_id = strdup(device_id);
  else
    device->device_id = NULL;

  if (device->make_and_model)
    free(device->make_and_model);

  if (make_and_model[0])
  {
    strlcat(make_and_model, " ", sizeof(make_and_model));
    strlcat(make_and_model, model, sizeof(make_and_model));

    if (!_cups_strncasecmp(make_and_model, "EPSON EPSON ", 12))
      _cups_strcpy(make_and_model, make_and_model + 6);
    else if (!_cups_strncasecmp(make_and_model, "HP HP ", 6))
      _cups_strcpy(make_and_model, make_and_model + 3);
    else if (!_cups_strncasecmp(make_and_model, "Lexmark International Lexmark ", 30))
      _cups_strcpy(make_and_model, make_and_model + 22);

    device->make_and_model = strdup(make_and_model);
  }
  else
    device->make_and_model = strdup(model);
}
Пример #17
0
static void
add_ppd_filter(mime_t      *mime,	/* I - MIME database */
               mime_type_t *filtertype,	/* I - Filter or prefilter MIME type */
	       const char  *filter)	/* I - Filter to add */
{
  char		super[MIME_MAX_SUPER],	/* Super-type for filter */
		type[MIME_MAX_TYPE],	/* Type for filter */
		dsuper[MIME_MAX_SUPER],	/* Destination super-type for filter */
		dtype[MIME_MAX_TYPE],	/* Destination type for filter */
		dest[MIME_MAX_SUPER + MIME_MAX_TYPE + 2],
					/* Destination super/type */
		program[1024];		/* Program/filter name */
  int		cost;			/* Cost of filter */
  size_t	maxsize = 0;		/* Maximum supported file size */
  mime_type_t	*temptype,		/* MIME type looping var */
		*desttype;		/* Destination MIME type */
  mime_filter_t	*filterptr;		/* MIME filter */


  DEBUG_printf(("add_ppd_filter(mime=%p, filtertype=%p(%s/%s), filter=\"%s\")",
                mime, filtertype, filtertype->super, filtertype->type, filter));

 /*
  * Parse the filter string; it should be in one of the following formats:
  *
  *     source/type cost program
  *     source/type cost maxsize(nnnn) program
  *     source/type dest/type cost program
  *     source/type dest/type cost maxsize(nnnn) program
  */

  if (sscanf(filter, "%15[^/]/%255s%*[ \t]%15[^/]/%255s%d%*[ \t]%1023[^\n]",
             super, type, dsuper, dtype, &cost, program) == 6)
  {
    snprintf(dest, sizeof(dest), "test/%s/%s", dsuper, dtype);

    if ((desttype = mimeType(mime, "printer", dest)) == NULL)
      desttype = mimeAddType(mime, "printer", dest);
  }
  else
  {
    if (sscanf(filter, "%15[^/]/%255s%d%*[ \t]%1023[^\n]", super, type, &cost,
               program) == 4)
    {
      desttype = filtertype;
    }
    else
    {
      printf("testmime: Invalid filter string \"%s\".\n", filter);
      return;
    }
  }

  if (!strncmp(program, "maxsize(", 8))
  {
    char	*ptr;			/* Pointer into maxsize(nnnn) program */

    maxsize = strtoll(program + 8, &ptr, 10);

    if (*ptr != ')')
    {
      printf("testmime: Invalid filter string \"%s\".\n", filter);
      return;
    }

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

    _cups_strcpy(program, ptr);
  }

 /*
  * Add the filter to the MIME database, supporting wildcards as needed...
  */

  for (temptype = mimeFirstType(mime);
       temptype;
       temptype = mimeNextType(mime))
    if (((super[0] == '*' && _cups_strcasecmp(temptype->super, "printer")) ||
         !_cups_strcasecmp(temptype->super, super)) &&
        (type[0] == '*' || !_cups_strcasecmp(temptype->type, type)))
    {
      if (desttype != filtertype)
      {
        DEBUG_printf(("add_ppd_filter: Adding filter %s/%s %s/%s %d %s",
		      temptype->super, temptype->type, desttype->super,
		      desttype->type, cost, program));
        filterptr = mimeAddFilter(mime, temptype, desttype, cost, program);

        if (!mimeFilterLookup(mime, desttype, filtertype))
        {
          DEBUG_printf(("add_printer_filter: Adding filter %s/%s %s/%s 0 -",
	                desttype->super, desttype->type, filtertype->super,
	                filtertype->type));
          mimeAddFilter(mime, desttype, filtertype, 0, "-");
        }
      }
      else
      {
        DEBUG_printf(("add_printer_filter: Adding filter %s/%s %s/%s %d %s",
		      temptype->super, temptype->type, filtertype->super,
		      filtertype->type, cost, program));
        filterptr = mimeAddFilter(mime, temptype, filtertype, cost, program);
      }

      if (filterptr)
	filterptr->maxsize = maxsize;
    }
}