Ejemplo n.º 1
0
int					/* O - 0 on success, -1 on error */
httpLoadCredentials(
    const char   *path,			/* I  - Keychain/PKCS#12 path */
    cups_array_t **credentials,		/* IO - Credentials */
    const char   *common_name)		/* I  - Common name for credentials */
{
  cups_file_t		*fp;		/* Certificate file */
  char			filename[1024],	/* filename.crt */
			temp[1024],	/* Temporary string */
			line[256];	/* Base64-encoded line */
  unsigned char		*data = NULL;	/* Buffer for cert data */
  size_t		alloc_data = 0,	/* Bytes allocated */
			num_data = 0;	/* Bytes used */
  int			decoded;	/* Bytes decoded */


  if (!credentials || !common_name)
    return (-1);

  if (!path)
    path = http_gnutls_default_path(temp, sizeof(temp));
  if (!path)
    return (-1);

  http_gnutls_make_path(filename, sizeof(filename), path, common_name, "crt");

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

  while (cupsFileGets(fp, line, sizeof(line)))
  {
    if (!strcmp(line, "-----BEGIN CERTIFICATE-----"))
    {
      if (num_data)
      {
       /*
	* Missing END CERTIFICATE...
	*/

        httpFreeCredentials(*credentials);
	*credentials = NULL;
        break;
      }
    }
    else if (!strcmp(line, "-----END CERTIFICATE-----"))
    {
      if (!num_data)
      {
       /*
	* Missing data...
	*/

        httpFreeCredentials(*credentials);
	*credentials = NULL;
        break;
      }

      if (!*credentials)
        *credentials = cupsArrayNew(NULL, NULL);

      if (httpAddCredential(*credentials, data, num_data))
      {
        httpFreeCredentials(*credentials);
	*credentials = NULL;
        break;
      }

      num_data = 0;
    }
    else
    {
      if (alloc_data == 0)
      {
        data       = malloc(2048);
	alloc_data = 2048;

        if (!data)
	  break;
      }
      else if ((num_data + strlen(line)) >= alloc_data)
      {
        unsigned char *tdata = realloc(data, alloc_data + 1024);
					/* Expanded buffer */

	if (!tdata)
	{
	  httpFreeCredentials(*credentials);
	  *credentials = NULL;
	  break;
	}

	data       = tdata;
        alloc_data += 1024;
      }

      decoded = alloc_data - num_data;
      httpDecode64_2((char *)data + num_data, &decoded, line);
      num_data += (size_t)decoded;
    }
  }

  cupsFileClose(fp);

  if (num_data)
  {
   /*
    * Missing END CERTIFICATE...
    */

    httpFreeCredentials(*credentials);
    *credentials = NULL;
  }

  if (data)
    free(data);

  return (*credentials ? 0 : -1);
}
Ejemplo n.º 2
0
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);
}
Ejemplo n.º 3
0
pwg_media_t *				/* O - Matching size or NULL */
pwgMediaForPPD(const char *ppd)		/* I - PPD size name */
{
  pwg_media_t	key,			/* Search key */
		*size;			/* Matching size */
  _cups_globals_t *cg = _cupsGlobals();	/* Global data */


 /*
  * Range check input...
  */

  if (!ppd)
    return (NULL);

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

  if (!cg->ppd_size_lut)
  {
    int	i;				/* Looping var */

    cg->ppd_size_lut = cupsArrayNew((cups_array_func_t)pwg_compare_ppd, 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->ppd)
        cupsArrayAdd(cg->ppd_size_lut, size);
  }

 /*
  * Lookup the name...
  */

  key.ppd = ppd;
  if ((size = (pwg_media_t *)cupsArrayFind(cg->ppd_size_lut, &key)) == NULL)
  {
   /*
    * See if the name is of the form:
    *
    *   [Custom.]WIDTHxLENGTH[.FullBleed]    - Size in points/inches [borderless]
    *   [Custom.]WIDTHxLENGTHcm[.FullBleed]  - Size in centimeters [borderless]
    *   [Custom.]WIDTHxLENGTHft[.FullBleed]  - Size in feet [borderless]
    *   [Custom.]WIDTHxLENGTHin[.FullBleed]  - Size in inches [borderless]
    *   [Custom.]WIDTHxLENGTHm[.FullBleed]   - Size in meters [borderless]
    *   [Custom.]WIDTHxLENGTHmm[.FullBleed]  - Size in millimeters [borderless]
    *   [Custom.]WIDTHxLENGTHpt[.FullBleed]  - Size in points [borderless]
    */

    int			w, l,		/* Width and length of page */
			numer,		/* Unit scaling factor */
			denom;		/* ... */
    char		*ptr;		/* Pointer into name */
    const char		*units;		/* Pointer to units */
    int			custom;		/* Custom page size? */


    if (!_cups_strncasecmp(ppd, "Custom.", 7))
    {
      custom = 1;
      numer  = 2540;
      denom  = 72;
      ptr    = (char *)ppd + 7;
    }
    else
    {
      custom = 0;
      numer  = 2540;
      denom  = 1;
      ptr    = (char *)ppd;
    }

   /*
    * Find any units in the size...
    */

    units = strchr(ptr, '.');
    while (units && isdigit(units[1] & 255))
      units = strchr(units + 1, '.');

    if (units)
      units -= 2;
    else
      units = ptr + strlen(ptr) - 2;

    if (units > ptr)
    {
      if (isdigit(*units & 255) || *units == '.')
        units ++;

      if (!_cups_strncasecmp(units, "cm", 2))
      {
        numer = 1000;
        denom = 1;
      }
      else if (!_cups_strncasecmp(units, "ft", 2))
      {
        numer = 2540 * 12;
        denom = 1;
      }
      else if (!_cups_strncasecmp(units, "in", 2))
      {
	numer = 2540;
        denom = 1;
      }
      else if (!_cups_strncasecmp(units, "mm", 2))
      {
        numer = 100;
        denom = 1;
      }
      else if (*units == 'm' || *units == 'M')
      {
	numer = 100000;
        denom = 1;
      }
      else if (!_cups_strncasecmp(units, "pt", 2))
      {
	numer = 2540;
	denom = 72;
      }
    }

    w = pwg_scan_measurement(ptr, &ptr, numer, denom);

    if (ptr && ptr > ppd && *ptr == 'x')
    {
      l = pwg_scan_measurement(ptr + 1, &ptr, numer, denom);

      if (ptr)
      {
       /*
	* Not a standard size; convert it to a PWG custom name of the form:
	*
	*     [oe|om]_WIDTHxHEIGHTuu_WIDTHxHEIGHTuu
	*/

        char	wstr[32], lstr[32];	/* Width and length as strings */

	size         = &(cg->pwg_media);
	size->width  = w;
	size->length = l;
	size->pwg    = cg->pwg_name;

	pwgFormatSizeName(cg->pwg_name, sizeof(cg->pwg_name),
	                  custom ? "custom" : NULL, custom ? ppd + 7 : NULL,
	                  size->width, size->length, NULL);

        if ((w % 635) == 0 && (l % 635) == 0)
          snprintf(cg->ppd_name, sizeof(cg->ppd_name), "%sx%s", pwg_format_inches(wstr, sizeof(wstr), w), pwg_format_inches(lstr, sizeof(lstr), l));
        else
          snprintf(cg->ppd_name, sizeof(cg->ppd_name), "%sx%smm", pwg_format_millimeters(wstr, sizeof(wstr), w), pwg_format_millimeters(lstr, sizeof(lstr), l));
        size->ppd = cg->ppd_name;
      }
    }
  }

  return (size);
}
Ejemplo n.º 4
0
int					/* O - Exit code */
main(int  argc,				/* I - Number of command-line args */
     char *argv[])			/* I - Command-line arguments */
{
  int		i;			/* Looping var */
  int		request_id;		/* Request ID */
  int		timeout;		/* Timeout in seconds */
  const char	*server_bin;		/* CUPS_SERVERBIN environment variable */
  char		filename[1024];		/* Backend directory filename */
  cups_dir_t	*dir;			/* Directory pointer */
  cups_dentry_t *dent;			/* Directory entry */
  double	current_time,		/* Current time */
		end_time;		/* Ending time */
  int		num_options;		/* Number of options */
  cups_option_t	*options;		/* Options */
  cups_array_t	*requested,		/* requested-attributes values */
		*exclude,		/* exclude-schemes values */
		*include;		/* include-schemes values */
#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
  struct sigaction action;		/* Actions for POSIX signals */
#endif /* HAVE_SIGACTION && !HAVE_SIGSET */


  setbuf(stderr, NULL);

 /*
  * Check the command-line...
  */

  if (argc != 6)
  {
    fputs("Usage: cups-deviced request-id limit timeout user-id options\n", stderr);

    return (1);
  }

  request_id = atoi(argv[1]);
  if (request_id < 1)
  {
    fprintf(stderr, "ERROR: [cups-deviced] Bad request ID %d!\n", request_id);

    return (1);
  }

  device_limit = atoi(argv[2]);
  if (device_limit < 0)
  {
    fprintf(stderr, "ERROR: [cups-deviced] Bad limit %d!\n", device_limit);

    return (1);
  }

  timeout = atoi(argv[3]);
  if (timeout < 1)
  {
    fprintf(stderr, "ERROR: [cups-deviced] Bad timeout %d!\n", timeout);

    return (1);
  }

  normal_user = atoi(argv[4]);
  if (normal_user <= 0)
  {
    fprintf(stderr, "ERROR: [cups-deviced] Bad user %d!\n", normal_user);

    return (1);
  }

  num_options = cupsParseOptions(argv[5], 0, &options);
  requested   = cupsdCreateStringsArray(cupsGetOption("requested-attributes",
                                                      num_options, options));
  exclude     = cupsdCreateStringsArray(cupsGetOption("exclude-schemes",
                                                      num_options, options));
  include     = cupsdCreateStringsArray(cupsGetOption("include-schemes",
                                                      num_options, options));

  if (!requested || cupsArrayFind(requested, "all") != NULL)
  {
    send_class = send_info = send_make_and_model = send_uri = send_id =
        send_location = 1;
  }
  else
  {
    send_class          = cupsArrayFind(requested, "device-class") != NULL;
    send_info           = cupsArrayFind(requested, "device-info") != NULL;
    send_make_and_model = cupsArrayFind(requested, "device-make-and-model") != NULL;
    send_uri            = cupsArrayFind(requested, "device-uri") != NULL;
    send_id             = cupsArrayFind(requested, "device-id") != NULL;
    send_location       = cupsArrayFind(requested, "device-location") != NULL;
  }

 /*
  * Listen to child signals...
  */

#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
  sigset(SIGCHLD, sigchld_handler);
#elif defined(HAVE_SIGACTION)
  memset(&action, 0, sizeof(action));

  sigemptyset(&action.sa_mask);
  sigaddset(&action.sa_mask, SIGCHLD);
  action.sa_handler = sigchld_handler;
  sigaction(SIGCHLD, &action, NULL);
#else
  signal(SIGCLD, sigchld_handler);	/* No, SIGCLD isn't a typo... */
#endif /* HAVE_SIGSET */

 /*
  * Try opening the backend directory...
  */

  if ((server_bin = getenv("CUPS_SERVERBIN")) == NULL)
    server_bin = CUPS_SERVERBIN;

  snprintf(filename, sizeof(filename), "%s/backend", server_bin);

  if ((dir = cupsDirOpen(filename)) == NULL)
  {
    fprintf(stderr, "ERROR: [cups-deviced] Unable to open backend directory "
                    "\"%s\": %s", filename, strerror(errno));

    return (1);
  }

 /*
  * Setup the devices array...
  */

  devices = cupsArrayNew((cups_array_func_t)compare_devices, NULL);

 /*
  * Loop through all of the device backends...
  */

  while ((dent = cupsDirRead(dir)) != NULL)
  {
   /*
    * Skip entries that are not executable files...
    */

    if (!S_ISREG(dent->fileinfo.st_mode) ||
        !isalnum(dent->filename[0] & 255) ||
        (dent->fileinfo.st_mode & (S_IRUSR | S_IXUSR)) != (S_IRUSR | S_IXUSR))
      continue;

   /*
    * Skip excluded or not included backends...
    */

    if (cupsArrayFind(exclude, dent->filename) ||
        (include && !cupsArrayFind(include, dent->filename)))
      continue;

   /*
    * Backends without permissions for normal users run as root,
    * all others run as the unprivileged user...
    */

    start_backend(dent->filename,
                  !(dent->fileinfo.st_mode & (S_IRWXG | S_IRWXO)));
  }

  cupsDirClose(dir);

 /*
  * Collect devices...
  */

  if (getenv("SOFTWARE"))
    puts("Content-Type: application/ipp\n");

  cupsdSendIPPHeader(IPP_OK, request_id);
  cupsdSendIPPGroup(IPP_TAG_OPERATION);
  cupsdSendIPPString(IPP_TAG_CHARSET, "attributes-charset", "utf-8");
  cupsdSendIPPString(IPP_TAG_LANGUAGE, "attributes-natural-language", "en-US");

  end_time = get_current_time() + timeout;

  while (active_backends > 0 && (current_time = get_current_time()) < end_time)
  {
   /*
    * Collect the output from the backends...
    */

    timeout = (int)(1000 * (end_time - current_time));

    if (poll(backend_fds, num_backends, timeout) > 0)
    {
      for (i = 0; i < num_backends; i ++)
        if (backend_fds[i].revents && backends[i].pipe)
	{
	  cups_file_t *bpipe = backends[i].pipe;
					/* Copy of pipe for backend... */

	  do
	  {
	    if (get_device(backends + i))
	    {
	      backend_fds[i].fd     = 0;
	      backend_fds[i].events = 0;
	      break;
	    }
	  }
	  while (bpipe->ptr &&
	         memchr(bpipe->ptr, '\n', bpipe->end - bpipe->ptr));
        }
    }

   /*
    * Get exit status from children...
    */

    if (dead_children)
      process_children();
  }

  cupsdSendIPPTrailer();

 /*
  * Terminate any remaining backends and exit...
  */

  if (active_backends > 0)
  {
    for (i = 0; i < num_backends; i ++)
      if (backends[i].pid)
	kill(backends[i].pid, SIGTERM);
  }

  return (0);
}
Ejemplo n.º 5
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);
}
Ejemplo n.º 6
0
static cups_array_t *			/* O - Array of filters to run */
mime_find_filters(
    mime_t           *mime,		/* I - MIME database */
    mime_type_t      *src,		/* I - Source file type */
    size_t           srcsize,		/* I - Size of source file */
    mime_type_t      *dst,		/* I - Destination file type */
    int              *cost,		/* O - Cost of filters */
    _mime_typelist_t *list)		/* I - Source types we've used */
{
  int			tempcost,	/* Temporary cost */
			mincost;	/* Current minimum */
  cups_array_t		*temp,		/* Temporary filter */
			*mintemp;	/* Current minimum */
  mime_filter_t		*current,	/* Current filter */
			srckey;		/* Source type key */
  _mime_typelist_t	listnode,	/* New list node */
			*listptr;	/* Pointer in list */


  DEBUG_printf(("2mime_find_filters(mime=%p, src=%p(%s/%s), srcsize=" CUPS_LLFMT
                ", dst=%p(%s/%s), cost=%p, list=%p)", mime, src, src->super,
		src->type, CUPS_LLCAST srcsize, dst, dst->super, dst->type,
		cost, list));

 /*
  * See if there is a filter that can convert the files directly...
  */

  if ((current = mimeFilterLookup(mime, src, dst)) != NULL &&
      (current->maxsize == 0 || srcsize <= current->maxsize))
  {
   /*
    * Got a direct filter!
    */

    DEBUG_puts("3mime_find_filters: Direct filter found.");

    if ((mintemp = cupsArrayNew(NULL, NULL)) == NULL)
    {
      DEBUG_puts("3mime_find_filters: Returning NULL (out of memory).");
      return (NULL);
    }

    cupsArrayAdd(mintemp, current);

    mincost = current->cost;

    if (!cost)
    {
      DEBUG_printf(("3mime_find_filters: Returning 1 filter, cost %d:",
                    mincost));
      DEBUG_printf(("3mime_find_filters: %s/%s %s/%s %d %s",
                    current->src->super, current->src->type,
                    current->dst->super, current->dst->type,
		    current->cost, current->filter));
      return (mintemp);
    }
  }
  else
  {
   /*
    * No direct filter...
    */

    mintemp = NULL;
    mincost = 9999999;
  }

 /*
  * Initialize this node in the type list...
  */

  listnode.next = list;

 /*
  * OK, now look for filters from the source type to any other type...
  */

  srckey.src = src;

  for (current = (mime_filter_t *)cupsArrayFind(mime->srcs, &srckey);
       current && current->src == src;
       current = (mime_filter_t *)cupsArrayNext(mime->srcs))
  {
   /*
    * See if we have already tried the destination type as a source
    * type (this avoids extra filter looping...)
    */

    mime_type_t *current_dst;		/* Current destination type */

    if (current->maxsize > 0 && srcsize > current->maxsize)
      continue;

    for (listptr = list, current_dst = current->dst;
	 listptr;
	 listptr = listptr->next)
      if (current_dst == listptr->src)
	break;

    if (listptr)
      continue;

   /*
    * See if we have any filters that can convert from the destination type
    * of this filter to the final type...
    */

    listnode.src = current->src;

    cupsArraySave(mime->srcs);
    temp = mime_find_filters(mime, current->dst, srcsize, dst, &tempcost,
                             &listnode);
    cupsArrayRestore(mime->srcs);

    if (!temp)
      continue;

    if (!cost)
    {
      DEBUG_printf(("3mime_find_filters: Returning %d filter(s), cost %d:",
		    cupsArrayCount(temp), tempcost));

#ifdef DEBUG
      for (current = (mime_filter_t *)cupsArrayFirst(temp);
	   current;
	   current = (mime_filter_t *)cupsArrayNext(temp))
	DEBUG_printf(("3mime_find_filters: %s/%s %s/%s %d %s",
		      current->src->super, current->src->type,
		      current->dst->super, current->dst->type,
		      current->cost, current->filter));
#endif /* DEBUG */

      return (temp);
    }

   /*
    * Found a match; see if this one is less costly than the last (if
    * any...)
    */

    tempcost += current->cost;

    if (tempcost < mincost)
    {
      cupsArrayDelete(mintemp);

     /*
      * Hey, we got a match!  Add the current filter to the beginning of the
      * filter list...
      */

      mintemp = temp;
      mincost = tempcost;
      cupsArrayInsert(mintemp, current);
    }
    else
      cupsArrayDelete(temp);
  }

  if (mintemp)
  {
   /*
    * Hey, we got a match!
    */

    DEBUG_printf(("3mime_find_filters: Returning %d filter(s), cost %d:",
                  cupsArrayCount(mintemp), mincost));

#ifdef DEBUG
    for (current = (mime_filter_t *)cupsArrayFirst(mintemp);
         current;
	 current = (mime_filter_t *)cupsArrayNext(mintemp))
      DEBUG_printf(("3mime_find_filters: %s/%s %s/%s %d %s",
                    current->src->super, current->src->type,
                    current->dst->super, current->dst->type,
		    current->cost, current->filter));
#endif /* DEBUG */

    if (cost)
      *cost = mincost;

    return (mintemp);
  }

  DEBUG_puts("3mime_find_filters: Returning NULL (no matches).");

  return (NULL);
}
Ejemplo n.º 7
0
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);
}
Ejemplo n.º 8
0
static int				/* O - 0 on success, 1 on error */
exec_filters(mime_type_t   *srctype,	/* I - Source type */
             cups_array_t  *filters,	/* I - Array of filters to run */
             const char    *infile,	/* I - File to filter */
	     const char    *outfile,	/* I - File to create */
	     const char    *ppdfile,	/* I - PPD file, if any */
	     const char    *printer,	/* I - Printer name */
	     const char    *user,	/* I - Username */
	     const char    *title,	/* I - Job title */
             int           num_options,	/* I - Number of filter options */
	     cups_option_t *options)	/* I - Filter options */
{
  int		i;			/* Looping var */
  const char	*argv[8],		/* Command-line arguments */
		*envp[17],		/* Environment variables */
		*temp;			/* Temporary string */
  char		*optstr,		/* Filter options */
		content_type[1024],	/* CONTENT_TYPE */
		cups_datadir[1024],	/* CUPS_DATADIR */
		cups_fontpath[1024],	/* CUPS_FONTPATH */
		cups_serverbin[1024],	/* CUPS_SERVERBIN */
		cups_serverroot[1024],	/* CUPS_SERVERROOT */
		final_content_type[1024] = "",
					/* FINAL_CONTENT_TYPE */
		lang[1024],		/* LANG */
		path[1024],		/* PATH */
		ppd[1024],		/* PPD */
		printer_info[255],	/* PRINTER_INFO env variable */
		printer_location[255],	/* PRINTER_LOCATION env variable */
		printer_name[255],	/* PRINTER env variable */
		rip_max_cache[1024],	/* RIP_MAX_CACHE */
		userenv[1024],		/* USER */
		program[1024];		/* Program to run */
  mime_filter_t	*filter,		/* Current filter */
		*next;			/* Next filter */
  int		current,		/* Current filter */
		filterfds[2][2],	/* Pipes for filters */
		pid,			/* Process ID of filter */
		status,			/* Exit status */
		retval;			/* Return value */
  cups_array_t	*pids;			/* Executed filters array */
  mime_filter_t	key;			/* Search key for filters */
  cups_lang_t	*language;		/* Current language */
  cups_dest_t	*dest;			/* Destination information */


 /*
  * Figure out the final content type...
  */

  for (filter = (mime_filter_t *)cupsArrayLast(filters);
       filter && filter->dst;
       filter = (mime_filter_t *)cupsArrayPrev(filters))
    if (strcmp(filter->dst->super, "printer"))
      break;

  if (filter && filter->dst)
  {
    const char *ptr;			/* Pointer in type name */

    if ((ptr = strchr(filter->dst->type, '/')) != NULL)
      snprintf(final_content_type, sizeof(final_content_type),
	       "FINAL_CONTENT_TYPE=%s", ptr + 1);
    else
      snprintf(final_content_type, sizeof(final_content_type),
	       "FINAL_CONTENT_TYPE=%s/%s", filter->dst->super,
	       filter->dst->type);
  }

 /*
  * Remove NULL ("-") filters...
  */

  for (filter = (mime_filter_t *)cupsArrayFirst(filters);
       filter;
       filter = (mime_filter_t *)cupsArrayNext(filters))
    if (!strcmp(filter->filter, "-"))
      cupsArrayRemove(filters, filter);

 /*
  * Setup the filter environment and command-line...
  */

  optstr = escape_options(num_options, options);

  snprintf(content_type, sizeof(content_type), "CONTENT_TYPE=%s/%s",
           srctype->super, srctype->type);
  snprintf(cups_datadir, sizeof(cups_datadir), "CUPS_DATADIR=%s", DataDir);
  snprintf(cups_fontpath, sizeof(cups_fontpath), "CUPS_FONTPATH=%s", FontPath);
  snprintf(cups_serverbin, sizeof(cups_serverbin), "CUPS_SERVERBIN=%s",
           ServerBin);
  snprintf(cups_serverroot, sizeof(cups_serverroot), "CUPS_SERVERROOT=%s",
           ServerRoot);
  language = cupsLangDefault();
  snprintf(lang, sizeof(lang), "LANG=%s.UTF8", language->language);
  snprintf(path, sizeof(path), "PATH=%s", Path);
  if (ppdfile)
    snprintf(ppd, sizeof(ppd), "PPD=%s", ppdfile);
  else if ((temp = getenv("PPD")) != NULL)
    snprintf(ppd, sizeof(ppd), "PPD=%s", temp);
  else
#ifdef __APPLE__
  if (!access("/System/Library/Frameworks/ApplicationServices.framework/"
	      "Versions/A/Frameworks/PrintCore.framework/Versions/A/"
	      "Resources/English.lproj/Generic.ppd", 0))
    strlcpy(ppd, "PPD=/System/Library/Frameworks/ApplicationServices.framework/"
                 "Versions/A/Frameworks/PrintCore.framework/Versions/A/"
		 "Resources/English.lproj/Generic.ppd", sizeof(ppd));
  else
    strlcpy(ppd, "PPD=/System/Library/Frameworks/ApplicationServices.framework/"
                 "Versions/A/Frameworks/PrintCore.framework/Versions/A/"
		 "Resources/Generic.ppd", sizeof(ppd));
#else
    snprintf(ppd, sizeof(ppd), "PPD=%s/model/laserjet.ppd", DataDir);
#endif /* __APPLE__ */
  snprintf(rip_max_cache, sizeof(rip_max_cache), "RIP_MAX_CACHE=%s", RIPCache);
  snprintf(userenv, sizeof(userenv), "USER=%s", user);

  if (printer &&
      (dest = cupsGetNamedDest(CUPS_HTTP_DEFAULT, printer, NULL)) != NULL)
  {
    if ((temp = cupsGetOption("printer-info", dest->num_options,
                              dest->options)) != NULL)
      snprintf(printer_info, sizeof(printer_info), "PRINTER_INFO=%s", temp);
    else
      snprintf(printer_info, sizeof(printer_info), "PRINTER_INFO=%s", printer);

    if ((temp = cupsGetOption("printer-location", dest->num_options,
                              dest->options)) != NULL)
      snprintf(printer_location, sizeof(printer_location),
               "PRINTER_LOCATION=%s", temp);
    else
      strlcpy(printer_location, "PRINTER_LOCATION=Unknown",
              sizeof(printer_location));
  }
  else
  {
    snprintf(printer_info, sizeof(printer_info), "PRINTER_INFO=%s",
             printer ? printer : "Unknown");
    strlcpy(printer_location, "PRINTER_LOCATION=Unknown",
            sizeof(printer_location));
  }

  snprintf(printer_name, sizeof(printer_name), "PRINTER=%s",
	   printer ? printer : "Unknown");

  argv[0] = (char *)printer;
  argv[1] = "1";
  argv[2] = user;
  argv[3] = title;
  argv[4] = cupsGetOption("copies", num_options, options);
  argv[5] = optstr;
  argv[6] = infile;
  argv[7] = NULL;

  if (!argv[4])
    argv[4] = "1";

  envp[0]  = "<CFProcessPath>";
  envp[1]  = content_type;
  envp[2]  = cups_datadir;
  envp[3]  = cups_fontpath;
  envp[4]  = cups_serverbin;
  envp[5]  = cups_serverroot;
  envp[6]  = lang;
  envp[7]  = path;
  envp[8]  = ppd;
  envp[9]  = printer_info;
  envp[10] = printer_location;
  envp[11] = printer_name;
  envp[12] = rip_max_cache;
  envp[13] = userenv;
  envp[14] = "CHARSET=utf-8";
  if (final_content_type[0])
  {
    envp[15] = final_content_type;
    envp[16] = NULL;
  }
  else
    envp[15] = NULL;

  for (i = 0; argv[i]; i ++)
    fprintf(stderr, "DEBUG: argv[%d]=\"%s\"\n", i, argv[i]);

  for (i = 0; envp[i]; i ++)
    fprintf(stderr, "DEBUG: envp[%d]=\"%s\"\n", i, envp[i]);

 /*
  * Execute all of the filters...
  */

  pids            = cupsArrayNew((cups_array_func_t)compare_pids, NULL);
  current         = 0;
  filterfds[0][0] = -1;
  filterfds[0][1] = -1;
  filterfds[1][0] = -1;
  filterfds[1][1] = -1;

  if (!infile)
    filterfds[0][0] = 0;

  for (filter = (mime_filter_t *)cupsArrayFirst(filters);
       filter;
       filter = next, current = 1 - current)
  {
    next = (mime_filter_t *)cupsArrayNext(filters);

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

    if (filterfds[!current][1] > 1)
    {
      close(filterfds[1 - current][0]);
      close(filterfds[1 - current][1]);

      filterfds[1 - current][0] = -1;
      filterfds[1 - current][0] = -1;
    }

    if (next)
      open_pipe(filterfds[1 - current]);
    else if (outfile)
    {
      filterfds[1 - current][1] = open(outfile, O_CREAT | O_TRUNC | O_WRONLY,
                                       0666);

      if (filterfds[1 - current][1] < 0)
        fprintf(stderr, "ERROR: Unable to create \"%s\" - %s\n", outfile,
	        strerror(errno));
    }
    else
      filterfds[1 - current][1] = 1;

    pid = exec_filter(program, (char **)argv, (char **)envp,
                      filterfds[current][0], filterfds[1 - current][1]);

    if (pid > 0)
    {
      fprintf(stderr, "INFO: %s (PID %d) started.\n", filter->filter, pid);

      filter->cost = pid;
      cupsArrayAdd(pids, filter);
    }
    else
      break;

    argv[6] = NULL;
  }

 /*
  * Close remaining pipes...
  */

  if (filterfds[0][1] > 1)
  {
    close(filterfds[0][0]);
    close(filterfds[0][1]);
  }

  if (filterfds[1][1] > 1)
  {
    close(filterfds[1][0]);
    close(filterfds[1][1]);
  }

 /*
  * Wait for the children to exit...
  */

  retval = 0;

  while (cupsArrayCount(pids) > 0)
  {
    if ((pid = wait(&status)) < 0)
      continue;

    key.cost = pid;
    if ((filter = (mime_filter_t *)cupsArrayFind(pids, &key)) != NULL)
    {
      cupsArrayRemove(pids, filter);

      if (status)
      {
	if (WIFEXITED(status))
	  fprintf(stderr, "ERROR: %s (PID %d) stopped with status %d\n",
		  filter->filter, pid, WEXITSTATUS(status));
	else
	  fprintf(stderr, "ERROR: %s (PID %d) crashed on signal %d\n",
		  filter->filter, pid, WTERMSIG(status));

        retval = 1;
      }
      else
        fprintf(stderr, "INFO: %s (PID %d) exited with no errors.\n",
	        filter->filter, pid);
    }
  }

  cupsArrayDelete(pids);

  return (retval);
}
Ejemplo n.º 9
0
int					/* O - Exit status */
main(int  argc,				/* I - Number of command-line args */
     char *argv[])			/* I - Command-line arguments */
{
  int		i,			/* Looping vars */
		list_filters = 0;	/* Just list the filters? */
  const char	*command,		/* Command name */
		*opt,			/* Current option */
		*printer;		/* Printer name */
  mime_type_t	*printer_type,		/* Printer MIME type */
		*prefilter_type;	/* Printer prefilter MIME type */
  char		*srctype,		/* Source type */
		*dsttype,		/* Destination type */
		super[MIME_MAX_SUPER],	/* Super-type name */
		type[MIME_MAX_TYPE];	/* Type name */
  int		compression;		/* Compression of file */
  int		cost;			/* Cost of filters */
  mime_t	*mime;			/* MIME database */
  char		mimedir[1024];		/* MIME directory */
  char		*infile,		/* File to filter */
		*outfile;		/* File to create */
  char		cupsfilesconf[1024];	/* cups-files.conf file */
  const char	*server_root;		/* CUPS_SERVERROOT environment variable */
  mime_type_t	*src,			/* Source type */
		*dst;			/* Destination type */
  cups_array_t	*filters;		/* Filters for the file */
  int		num_options;		/* Number of options */
  cups_option_t	*options;		/* Options */
  const char	*ppdfile;		/* PPD file */
  const char	*title,			/* Title string */
		*user;			/* Username */
  int		all_filters,		/* Use all filters */
		removeppd,		/* Remove PPD file */
		removeinfile;		/* Remove input file */
  int		status;			/* Execution status */


 /*
  * Setup defaults...
  */

  if ((command = strrchr(argv[0], '/')) != NULL)
    command ++;
  else
    command = argv[0];

  printer      = !strcmp(command, "convert") ? "tofile" : "cupsfilter";
  mime         = NULL;
  srctype      = NULL;
  compression  = 0;
  dsttype      = "application/pdf";
  infile       = NULL;
  outfile      = NULL;
  num_options  = 0;
  options      = NULL;
  ppdfile      = NULL;
  title        = NULL;
  user         = cupsUser();
  all_filters  = 0;
  removeppd    = 0;
  removeinfile = 0;

  if ((server_root = getenv("CUPS_SERVERROOT")) == NULL)
    server_root = CUPS_SERVERROOT;

  snprintf(cupsfilesconf, sizeof(cupsfilesconf), "%s/cups-files.conf", server_root);

 /*
  * Process command-line arguments...
  */

  _cupsSetLocale(argv);

  for (i = 1; i < argc; i ++)
  {
    if (argv[i][0] == '-')
    {
      if (!strcmp(argv[i], "--list-filters"))
      {
        list_filters = 1;
      }
      else if (!strcmp(argv[i], "--"))
      {
	i ++;
	if (i < argc && !infile)
	  infile = argv[i];
	else
	  usage(NULL);
      }
      else
      {
	for (opt = argv[i] + 1; *opt; opt ++)
	{
	  switch (*opt)
	  {
	    case 'a' : /* Specify option... */
		i ++;
		if (i < argc)
		  num_options = cupsParseOptions(argv[i], num_options, &options);
		else
		  usage(opt);
		break;

	    case 'c' : /* Specify cups-files.conf file location... */
		i ++;
		if (i < argc)
		{
		  if (!strcmp(command, "convert"))
		    num_options = cupsAddOption("copies", argv[i], num_options, &options);
		  else
		    strlcpy(cupsfilesconf, argv[i], sizeof(cupsfilesconf));
		}
		else
		  usage(opt);
		break;

	    case 'd' : /* Specify the real printer name */
		i ++;
		if (i < argc)
		  printer = argv[i];
		else
		  usage(opt);
		break;

	    case 'D' : /* Delete input file after conversion */
		removeinfile = 1;
		break;

	    case 'e' : /* Use every filter from the PPD file */
		all_filters = 1;
		break;

	    case 'f' : /* Specify input file... */
		i ++;
		if (i < argc && !infile)
		  infile = argv[i];
		else
		  usage(opt);
		break;

	    case 'i' : /* Specify source MIME type... */
		i ++;
		if (i < argc)
		{
		  if (sscanf(argv[i], "%15[^/]/%255s", super, type) != 2)
		    usage(opt);

		  srctype = argv[i];
		}
		else
		  usage(opt);
		break;

	    case 'j' : /* Get job file or specify destination MIME type... */
		if (strcmp(command, "convert"))
		{
		  i ++;
		  if (i < argc)
		  {
		    get_job_file(argv[i]);
		    infile = TempFile;
		  }
		  else
		    usage(opt);

		  break;
		}

	    case 'm' : /* Specify destination MIME type... */
		i ++;
		if (i < argc)
		{
		  if (sscanf(argv[i], "%15[^/]/%255s", super, type) != 2)
		    usage(opt);

		  dsttype = argv[i];
		}
		else
		  usage(opt);
		break;

	    case 'n' : /* Specify number of copies... */
		i ++;
		if (i < argc)
		  num_options = cupsAddOption("copies", argv[i], num_options, &options);
		else
		  usage(opt);
		break;

	    case 'o' : /* Specify option(s) or output filename */
		i ++;
		if (i < argc)
		{
		  if (!strcmp(command, "convert"))
		  {
		    if (outfile)
		      usage(NULL);
		    else
		      outfile = argv[i];
		  }
		  else
		    num_options = cupsParseOptions(argv[i], num_options, &options);
		}
		else
		  usage(opt);
		break;

	    case 'p' : /* Specify PPD file... */
	    case 'P' : /* Specify PPD file... */
		i ++;
		if (i < argc)
		  ppdfile = argv[i];
		else
		  usage(opt);
		break;

	    case 't' : /* Specify title... */
	    case 'J' : /* Specify title... */
		i ++;
		if (i < argc)
		  title = argv[i];
		else
		  usage(opt);
		break;

	    case 'u' : /* Delete PPD file after conversion */
		removeppd = 1;
		break;

	    case 'U' : /* Specify username... */
		i ++;
		if (i < argc)
		  user = argv[i];
		else
		  usage(opt);
		break;

	    default : /* Something we don't understand... */
		usage(opt);
		break;
	  }
	}
      }
    }
    else if (!infile)
    {
      if (strcmp(command, "convert"))
	infile = argv[i];
      else
	usage(NULL);
    }
    else
    {
      _cupsLangPuts(stderr,
                    _("cupsfilter: Only one filename can be specified."));
      usage(NULL);
    }
  }

  if (!infile && !srctype)
    usage(NULL);

  if (!title)
  {
    if (!infile)
      title = "(stdin)";
    else if ((title = strrchr(infile, '/')) != NULL)
      title ++;
    else
      title = infile;
  }

 /*
  * Load the cups-files.conf file and create the MIME database...
  */

  if (read_cups_files_conf(cupsfilesconf))
    return (1);

  snprintf(mimedir, sizeof(mimedir), "%s/mime", DataDir);

  mime = mimeLoadTypes(NULL, mimedir);
  mime = mimeLoadTypes(mime, ServerRoot);
  mime = mimeLoadFilters(mime, mimedir, Path);
  mime = mimeLoadFilters(mime, ServerRoot, Path);

  if (!mime)
  {
    _cupsLangPrintf(stderr,
                    _("%s: Unable to read MIME database from \"%s\" or "
		      "\"%s\"."),
		    command, mimedir, ServerRoot);
    return (1);
  }

  prefilter_type = NULL;

  if (all_filters)
    printer_type = add_printer_filters(command, mime, printer, ppdfile,
				       &prefilter_type);
  else
    printer_type   = mimeType(mime, "application", "vnd.cups-postscript");

 /*
  * Get the source and destination types...
  */

  if (srctype)
  {
   /* sscanf return value already checked above */
    sscanf(srctype, "%15[^/]/%255s", super, type);
    if ((src = mimeType(mime, super, type)) == NULL)
    {
      _cupsLangPrintf(stderr,
		      _("%s: Unknown source MIME type %s/%s."),
		      command, super, type);
      return (1);
    }
  }
  else if ((src = mimeFileType(mime, infile, infile, &compression)) == NULL)
  {
    _cupsLangPrintf(stderr,
                    _("%s: Unable to determine MIME type of \"%s\"."),
		    command, infile);
    return (1);
  }

 /* sscanf return value already checked above */
  sscanf(dsttype, "%15[^/]/%255s", super, type);
  if (!_cups_strcasecmp(super, "printer"))
    dst = printer_type;
  else if ((dst = mimeType(mime, super, type)) == NULL)
  {
    _cupsLangPrintf(stderr,
                    _("%s: Unknown destination MIME type %s/%s."),
		    command, super, type);
    return (1);
  }

 /*
  * Figure out how to filter the file...
  */

  if (src == dst)
  {
   /*
    * Special case - no filtering needed...
    */

    filters = cupsArrayNew(NULL, NULL);
    cupsArrayAdd(filters, &GZIPFilter);
    GZIPFilter.src = src;
    GZIPFilter.dst = dst;
  }
  else if ((filters = mimeFilter(mime, src, dst, &cost)) == NULL)
  {
    _cupsLangPrintf(stderr,
                    _("%s: No filter to convert from %s/%s to %s/%s."),
		    command, src->super, src->type, dst->super, dst->type);
    return (1);
  }
  else if (compression)
    cupsArrayInsert(filters, &GZIPFilter);

  if (prefilter_type)
  {
   /*
    * Add pre-filters...
    */

    mime_filter_t	*filter,	/* Current filter */
			*prefilter;	/* Current pre-filter */
    cups_array_t	*prefilters = cupsArrayNew(NULL, NULL);
					/* New filters array */


    for (filter = (mime_filter_t *)cupsArrayFirst(filters);
	 filter;
	 filter = (mime_filter_t *)cupsArrayNext(filters))
    {
      if ((prefilter = mimeFilterLookup(mime, filter->src,
                                        prefilter_type)) != NULL)
	cupsArrayAdd(prefilters, prefilter);

      cupsArrayAdd(prefilters, filter);
    }

    cupsArrayDelete(filters);
    filters = prefilters;
  }

  if (list_filters)
  {
   /*
    * List filters...
    */

    mime_filter_t	*filter;	/* Current filter */

    for (filter = (mime_filter_t *)cupsArrayFirst(filters);
	 filter;
	 filter = (mime_filter_t *)cupsArrayNext(filters))
      if (strcmp(filter->filter, "-"))
        _cupsLangPuts(stdout, filter->filter);

    status = 0;
  }
  else
  {
   /*
    * Run filters...
    */

    status = exec_filters(src, filters, infile, outfile, ppdfile, printer, user,
			  title, num_options, options);
  }

 /*
  * Remove files as needed, then exit...
  */

  if (TempFile[0])
    unlink(TempFile);

  if (removeppd && ppdfile)
    unlink(ppdfile);

  if (removeinfile && infile)
    unlink(infile);

  return (status);
}
Ejemplo n.º 10
0
int					/* O - Exit status */
main(int  argc,				/* I - Number of command-line args */
     char *argv[])			/* I - Command-line arguments */
{
  int		i;			/* Looping vars */
  const char	*command,		/* Command name */
		*opt;			/* Current option */
  char		*srctype,		/* Source type */
		*dsttype,		/* Destination type */
		super[MIME_MAX_SUPER],	/* Super-type name */
		type[MIME_MAX_TYPE];	/* Type name */
  int		compression;		/* Compression of file */
  int		cost;			/* Cost of filters */
  mime_t	*mime;			/* MIME database */
  char		*infile,		/* File to filter */
		*outfile;		/* File to create */
  char		cupsdconf[1024];	/* cupsd.conf file */
  const char	*server_root;		/* CUPS_SERVERROOT environment variable */
  mime_type_t	*src,			/* Source type */
		*dst;			/* Destination type */
  cups_array_t	*filters;		/* Filters for the file */
  int		num_options;		/* Number of options */
  cups_option_t	*options;		/* Options */
  const char	*ppdfile;		/* PPD file */
  const char	*title,			/* Title string */
		*user;			/* Username */
  int		removeppd,		/* Remove PPD file */
		removeinfile;		/* Remove input file */
  int		status;			/* Execution status */


 /*
  * Setup defaults...
  */

  if ((command = strrchr(argv[0], '/')) != NULL)
    command ++;
  else
    command = argv[0];

  mime         = NULL;
  srctype      = NULL;
  compression  = 0;
  dsttype      = "application/pdf";
  infile       = NULL;
  outfile      = NULL;
  num_options  = 0;
  options      = NULL;
  ppdfile      = NULL;
  title        = NULL;
  user         = cupsUser();
  removeppd    = 0;
  removeinfile = 0;

  if ((server_root = getenv("CUPS_SERVERROOT")) == NULL)
    server_root = CUPS_SERVERROOT;

  snprintf(cupsdconf, sizeof(cupsdconf), "%s/cupsd.conf", server_root);

 /*
  * Process command-line arguments...
  */

  _cupsSetLocale(argv);

  for (i = 1; i < argc; i ++)
    if (argv[i][0] == '-')
    {
      for (opt = argv[i] + 1; *opt; opt ++)
        switch (*opt)
	{
	  case '-' : /* Next argument is a filename... */
	      i ++;
	      if (i < argc && !infile)
	        infile = argv[i];
	      else
	        usage(command, opt);
	      break;

          case 'a' : /* Specify option... */
	      i ++;
	      if (i < argc)
	        num_options = cupsParseOptions(argv[i], num_options, &options);
	      else
	        usage(command, opt);
	      break;

          case 'c' : /* Specify cupsd.conf file location... */
	      i ++;
	      if (i < argc)
	      {
	        if (!strcmp(command, "convert"))
		  num_options = cupsAddOption("copies", argv[i], num_options,
					      &options);
		else
		  strlcpy(cupsdconf, argv[i], sizeof(cupsdconf));
	      }
	      else
	        usage(command, opt);
	      break;

	  case 'D' : /* Delete input file after conversion */
	      removeinfile = 1;
	      break;

          case 'f' : /* Specify input file... */
	      i ++;
	      if (i < argc && !infile)
	        infile = argv[i];
	      else
	        usage(command, opt);
	      break;

          case 'i' : /* Specify source MIME type... */
	      i ++;
	      if (i < argc)
	      {
	        if (sscanf(argv[i], "%15[^/]/%255s", super, type) != 2)
		  usage(command, opt);

                srctype = argv[i];
	      }
	      else
	        usage(command, opt);
	      break;

          case 'j' : /* Specify destination MIME type... */
          case 'm' : /* Specify destination MIME type... */
	      i ++;
	      if (i < argc)
	      {
	        if (sscanf(argv[i], "%15[^/]/%255s", super, type) != 2)
		  usage(command, opt);

                dsttype = argv[i];
	      }
	      else
	        usage(command, opt);
	      break;

          case 'n' : /* Specify number of copies... */
	      i ++;
	      if (i < argc)
	        num_options = cupsAddOption("copies", argv[i], num_options,
		                            &options);
	      else
	        usage(command, opt);
	      break;

          case 'o' : /* Specify option(s) or output filename */
	      i ++;
	      if (i < argc)
	      {
	        if (!strcmp(command, "convert"))
		{
		  if (outfile)
		    usage(command, NULL);
		  else
		    outfile = argv[i];
		}
		else
	          num_options = cupsParseOptions(argv[i], num_options,
		                                 &options);
	      }
	      else
	        usage(command, opt);
	      break;

          case 'p' : /* Specify PPD file... */
          case 'P' : /* Specify PPD file... */
	      i ++;
	      if (i < argc)
	        ppdfile = argv[i];
	      else
	        usage(command, opt);
	      break;

          case 't' : /* Specify title... */
          case 'J' : /* Specify title... */
	      i ++;
	      if (i < argc)
	        title = argv[i];
	      else
	        usage(command, opt);
	      break;

	  case 'u' : /* Delete PPD file after conversion */
	      removeinfile = 1;
	      break;

          case 'U' : /* Specify username... */
	      i ++;
	      if (i < argc)
	        user = argv[i];
	      else
	        usage(command, opt);
	      break;

	  default : /* Something we don't understand... */
	      usage(command, opt);
	      break;
	}
    }
    else if (!infile)
    {
      if (strcmp(command, "convert"))
	infile = argv[i];
      else
      {
	_cupsLangPuts(stderr,
		      _("convert: Use the -f option to specify a file to "
		        "convert.\n"));
	usage(command, NULL);
      }
    }
    else
    {
      _cupsLangPuts(stderr,
                    _("cupsfilter: Only one filename can be specified!\n"));
      usage(command, NULL);
    }

  if (!infile && !srctype)
    usage(command, NULL);

  if (!title)
  {
    if (!infile)
      title = "(stdin)";
    else if ((title = strrchr(infile, '/')) != NULL)
      title ++;
    else
      title = infile;
  }

 /*
  * Load the cupsd.conf file and create the MIME database...
  */

  if (read_cupsd_conf(cupsdconf))
    return (1);

  if ((mime = mimeLoad(ServerRoot, Path)) == NULL)
  {
    _cupsLangPrintf(stderr,
                    _("%s: Unable to read MIME database from \"%s\"!\n"),
		    command, ServerRoot);
    return (1);
  }

 /*
  * Get the source and destination types...
  */

  if (srctype)
  {
    sscanf(srctype, "%15[^/]/%255s", super, type);
    if ((src = mimeType(mime, super, type)) == NULL)
    {
      _cupsLangPrintf(stderr,
		      _("%s: Unknown source MIME type %s/%s!\n"),
		      command, super, type);
      return (1);
    }
  }
  else if ((src = mimeFileType(mime, infile, infile, &compression)) == NULL)
  {
    _cupsLangPrintf(stderr,
                    _("%s: Unable to determine MIME type of \"%s\"!\n"),
		    command, infile);
    return (1);
  }

  sscanf(dsttype, "%15[^/]/%255s", super, type);
  if ((dst = mimeType(mime, super, type)) == NULL)
  {
    _cupsLangPrintf(stderr,
                    _("%s: Unknown destination MIME type %s/%s!\n"),
		    command, super, type);
    return (1);
  }

 /*
  * Figure out how to filter the file...
  */

  if (src == dst)
  {
   /*
    * Special case - no filtering needed...
    */

    filters = cupsArrayNew(NULL, NULL);
    cupsArrayAdd(filters, &GZIPFilter);
  }
  else if ((filters = mimeFilter(mime, src, dst, &cost)) == NULL)
  {
    _cupsLangPrintf(stderr,
                    _("%s: No filter to convert from %s/%s to %s/%s!\n"),
		    command, src->super, src->type, dst->super, dst->type);
    return (1);
  }
  else if (compression)
    cupsArrayInsert(filters, &GZIPFilter);

 /*
  * Do it!
  */

  status = exec_filters(filters, infile, outfile, ppdfile,
                        !strcmp(command, "convert") ? "tofile" : "cupsfilter",
			user, title, num_options, options);

 /*
  * Remove files as needed, then exit...
  */

  if (removeppd && ppdfile)
    unlink(ppdfile);

  if (removeinfile && infile)
    unlink(infile);

  return (status);
}
Ejemplo n.º 11
0
mime_type_t *				/* O - New (or existing) MIME type */
mimeAddType(mime_t     *mime,		/* I - MIME database */
            const char *super,		/* I - Super-type name */
	    const char *type)		/* I - Type name */
{
  mime_type_t	*temp;			/* New MIME type */
  size_t	typelen;		/* Length of type name */


  DEBUG_printf(("mimeAddType(mime=%p, super=\"%s\", type=\"%s\")", mime, super,
                type));

 /*
  * Range check input...
  */

  if (!mime || !super || !type)
  {
    DEBUG_puts("1mimeAddType: Returning NULL (bad arguments).");
    return (NULL);
  }

 /*
  * See if the type already exists; if so, return the existing type...
  */

  if ((temp = mimeType(mime, super, type)) != NULL)
  {
    DEBUG_printf(("1mimeAddType: Returning %p (existing).", temp));
    return (temp);
  }

 /*
  * The type doesn't exist; add it...
  */

  if (!mime->types)
    mime->types = cupsArrayNew((cups_array_func_t)mime_compare_types, NULL);

  if (!mime->types)
  {
    DEBUG_puts("1mimeAddType: Returning NULL (no types).");
    return (NULL);
  }

  typelen = strlen(type) + 1;

  if ((temp = calloc(1, sizeof(mime_type_t) - MIME_MAX_TYPE + typelen)) == NULL)
  {
    DEBUG_puts("1mimeAddType: Returning NULL (out of memory).");
    return (NULL);
  }

  strlcpy(temp->super, super, sizeof(temp->super));
  memcpy(temp->type, type, typelen);
  temp->priority = 100;

  cupsArrayAdd(mime->types, temp);

  DEBUG_printf(("1mimeAddType: Returning %p (new).", temp));
  return (temp);
}
Ejemplo n.º 12
0
int					/* O - 1 if successful, 0 on error */
serverLoadConfiguration(
    const char *directory)		/* I - Configuration directory */
{
  cups_dir_t	*dir;			/* Directory pointer */
  cups_dentry_t	*dent;			/* Directory entry */
  char		filename[1024],		/* Configuration file/directory */
                iconname[1024],		/* Icon file */
		resource[1024],		/* Resource path */
                *ptr;			/* Pointer into filename */
  server_printer_t *printer;		/* Printer */
  ipp_t		*attrs;			/* Printer attributes */
  char		*authtype,		/* AuthType value, if any */
		*command,		/* Command value, if any */
		*device_uri,		/* DeviceURI value, if any */
		*make,			/* Make value, if any */
		*model,			/* Model value, if any */
		*proxy_user;		/* ProxyUser value, if any */


 /*
  * First read the system configuration file, if any...
  */

  snprintf(filename, sizeof(filename), "%s/system.conf", directory);
  if (!load_system(filename))
    return (0);

  if (!serverFinalizeConfiguration())
    return (0);

 /*
  * Then see if there are any print queues...
  */

  snprintf(filename, sizeof(filename), "%s/print", directory);
  if ((dir = cupsDirOpen(filename)) != NULL)
  {
    serverLog(SERVER_LOGLEVEL_INFO, "Loading printers from \"%s\".", filename);

    while ((dent = cupsDirRead(dir)) != NULL)
    {
      if ((ptr = dent->filename + strlen(dent->filename) - 5) >= dent->filename && !strcmp(ptr, ".conf"))
      {
       /*
        * Load the conf file, with any associated icon image.
        */

        serverLog(SERVER_LOGLEVEL_INFO, "Loading printer from \"%s\".", dent->filename);

        snprintf(filename, sizeof(filename), "%s/print/%s", directory, dent->filename);
        *ptr = '\0';
        snprintf(iconname, sizeof(iconname), "%s/print/%s.png", directory, dent->filename);

        authtype = command = device_uri = make = model = proxy_user = NULL;

        if ((attrs = serverLoadAttributes(filename, &authtype, &command, &device_uri, &make, &model, &proxy_user)) != NULL)
	{
          snprintf(resource, sizeof(resource), "/ipp/print/%s", dent->filename);

	  if ((printer = serverCreatePrinter(resource, dent->filename, NULL, make, model, access(iconname, R_OK) ? NULL : iconname, NULL, 0, 0, 0, 0, attrs, command, device_uri, proxy_user)) == NULL)
          continue;

	  if (!Printers)
	    Printers = cupsArrayNew((cups_array_func_t)compare_printers, NULL);

	  cupsArrayAdd(Printers, printer);
	}
      }
      else if (!strstr(dent->filename, ".png"))
        serverLog(SERVER_LOGLEVEL_INFO, "Skipping \"%s\".", dent->filename);

    }

    cupsDirClose(dir);
  }

 /*
  * Finally, see if there are any 3D print queues...
  */

  snprintf(filename, sizeof(filename), "%s/print3d", directory);
  if ((dir = cupsDirOpen(filename)) != NULL)
  {
    serverLog(SERVER_LOGLEVEL_INFO, "Loading 3D printers from \"%s\".", filename);

    while ((dent = cupsDirRead(dir)) != NULL)
    {
      if ((ptr = dent->filename + strlen(dent->filename) - 5) >= dent->filename && !strcmp(ptr, ".conf"))
      {
       /*
        * Load the conf file, with any associated icon image.
        */

        serverLog(SERVER_LOGLEVEL_INFO, "Loading 3D printer from \"%s\".", dent->filename);

        snprintf(filename, sizeof(filename), "%s/print3d/%s", directory, dent->filename);
        *ptr = '\0';
        snprintf(iconname, sizeof(iconname), "%s/print3d/%s.png", directory, dent->filename);

        authtype = command = device_uri = make = model = proxy_user = NULL;

        if ((attrs = serverLoadAttributes(filename, &authtype, &command, &device_uri, &make, &model, &proxy_user)) != NULL)
	{
          snprintf(resource, sizeof(resource), "/ipp/print3d/%s", dent->filename);

	  if ((printer = serverCreatePrinter(resource, dent->filename, NULL, make, model, access(iconname, R_OK) ? NULL : iconname, NULL, 0, 0, 0, 0, attrs, command, device_uri, proxy_user)) == NULL)
          continue;

	  if (!Printers)
	    Printers = cupsArrayNew((cups_array_func_t)compare_printers, NULL);

	  cupsArrayAdd(Printers, printer);
	}
      }
      else if (!strstr(dent->filename, ".png"))
        serverLog(SERVER_LOGLEVEL_INFO, "Skipping \"%s\".", dent->filename);

    }

    cupsDirClose(dir);
  }

  return (1);
}
Ejemplo n.º 13
0
int					/* O - Exit status */
main(int  argc,				/* I - Number of command-line args */
     char *argv[])			/* I - Command-line arguments */
{
  const char	*name;			/* Backend name */
  cups_array_t	*devices;		/* Device array */
  cups_device_t	*device;		/* Current device */
  char		uriName[1024];		/* Unquoted fullName for URI */
#ifdef HAVE_DNSSD
  int		fd;			/* Main file descriptor */
  fd_set	input;			/* Input set for select() */
  struct timeval timeout;		/* Timeout for select() */
  DNSServiceRef	main_ref,		/* Main service reference */
		fax_ipp_ref,		/* IPP fax service reference */
		ipp_ref,		/* IPP service reference */
		ipp_tls_ref,		/* IPP w/TLS service reference */
		ipps_ref,		/* IPP service reference */
		local_fax_ipp_ref,	/* Local IPP fax service reference */
		local_ipp_ref,		/* Local IPP service reference */
		local_ipp_tls_ref,	/* Local IPP w/TLS service reference */
		local_ipps_ref,		/* Local IPP service reference */
		local_printer_ref,	/* Local LPD service reference */
		pdl_datastream_ref,	/* AppSocket service reference */
		printer_ref,		/* LPD service reference */
		riousbprint_ref;	/* Remote IO service reference */
#endif /* HAVE_DNSSD */
#ifdef HAVE_AVAHI
  AvahiClient	*client;		/* Client information */
  int		error;			/* Error code, if any */
#endif /* HAVE_AVAHI */
#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
  struct sigaction action;		/* Actions for POSIX signals */
#endif /* HAVE_SIGACTION && !HAVE_SIGSET */


 /*
  * Don't buffer stderr, and catch SIGTERM...
  */

  setbuf(stderr, NULL);

#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
  sigset(SIGTERM, sigterm_handler);
#elif defined(HAVE_SIGACTION)
  memset(&action, 0, sizeof(action));

  sigemptyset(&action.sa_mask);
  action.sa_handler = sigterm_handler;
  sigaction(SIGTERM, &action, NULL);
#else
  signal(SIGTERM, sigterm_handler);
#endif /* HAVE_SIGSET */

 /*
  * Check command-line...
  */

  if (argc >= 6)
    exec_backend(argv);
  else if (argc != 1)
  {
    _cupsLangPrintf(stderr,
                    _("Usage: %s job-id user title copies options [file]"),
		    argv[0]);
    return (1);
  }

 /*
  * Only do discovery when run as "dnssd"...
  */

  if ((name = strrchr(argv[0], '/')) != NULL)
    name ++;
  else
    name = argv[0];

  if (strcmp(name, "dnssd"))
    return (0);

 /*
  * Create an array to track devices...
  */

  devices = cupsArrayNew((cups_array_func_t)compare_devices, NULL);

 /*
  * Browse for different kinds of printers...
  */

#ifdef HAVE_DNSSD
  if (DNSServiceCreateConnection(&main_ref) != kDNSServiceErr_NoError)
  {
    perror("ERROR: Unable to create service connection");
    return (1);
  }

  fd = DNSServiceRefSockFD(main_ref);

  fax_ipp_ref = main_ref;
  DNSServiceBrowse(&fax_ipp_ref, kDNSServiceFlagsShareConnection, 0,
                   "_fax-ipp._tcp", NULL, browse_callback, devices);

  ipp_ref = main_ref;
  DNSServiceBrowse(&ipp_ref, kDNSServiceFlagsShareConnection, 0,
                   "_ipp._tcp", NULL, browse_callback, devices);

  ipp_tls_ref = main_ref;
  DNSServiceBrowse(&ipp_tls_ref, kDNSServiceFlagsShareConnection, 0,
                   "_ipp-tls._tcp", NULL, browse_callback, devices);

  ipps_ref = main_ref;
  DNSServiceBrowse(&ipps_ref, kDNSServiceFlagsShareConnection, 0,
                   "_ipps._tcp", NULL, browse_callback, devices);

  local_fax_ipp_ref = main_ref;
  DNSServiceBrowse(&local_fax_ipp_ref, kDNSServiceFlagsShareConnection,
                   kDNSServiceInterfaceIndexLocalOnly,
		   "_fax-ipp._tcp", NULL, browse_local_callback, devices);

  local_ipp_ref = main_ref;
  DNSServiceBrowse(&local_ipp_ref, kDNSServiceFlagsShareConnection,
                   kDNSServiceInterfaceIndexLocalOnly,
		   "_ipp._tcp", NULL, browse_local_callback, devices);

  local_ipp_tls_ref = main_ref;
  DNSServiceBrowse(&local_ipp_tls_ref, kDNSServiceFlagsShareConnection,
                   kDNSServiceInterfaceIndexLocalOnly,
                   "_ipp-tls._tcp", NULL, browse_local_callback, devices);

  local_ipps_ref = main_ref;
  DNSServiceBrowse(&local_ipps_ref, kDNSServiceFlagsShareConnection,
                   kDNSServiceInterfaceIndexLocalOnly,
		   "_ipps._tcp", NULL, browse_local_callback, devices);

  local_printer_ref = main_ref;
  DNSServiceBrowse(&local_printer_ref, kDNSServiceFlagsShareConnection,
                   kDNSServiceInterfaceIndexLocalOnly,
                   "_printer._tcp", NULL, browse_local_callback, devices);

  pdl_datastream_ref = main_ref;
  DNSServiceBrowse(&pdl_datastream_ref, kDNSServiceFlagsShareConnection, 0,
                   "_pdl-datastream._tcp", NULL, browse_callback, devices);

  printer_ref = main_ref;
  DNSServiceBrowse(&printer_ref, kDNSServiceFlagsShareConnection, 0,
                   "_printer._tcp", NULL, browse_callback, devices);

  riousbprint_ref = main_ref;
  DNSServiceBrowse(&riousbprint_ref, kDNSServiceFlagsShareConnection, 0,
                   "_riousbprint._tcp", NULL, browse_callback, devices);
#endif /* HAVE_DNSSD */

#ifdef HAVE_AVAHI
  if ((simple_poll = avahi_simple_poll_new()) == NULL)
  {
    fputs("DEBUG: Unable to create Avahi simple poll object.\n", stderr);
    return (0);
  }

  avahi_simple_poll_set_func(simple_poll, poll_callback, NULL);

  client = avahi_client_new(avahi_simple_poll_get(simple_poll),
			    0, client_callback, simple_poll, &error);
  if (!client)
  {
    fputs("DEBUG: Unable to create Avahi client.\n", stderr);
    return (0);
  }

  browsers = 6;
  avahi_service_browser_new(client, AVAHI_IF_UNSPEC,
			    AVAHI_PROTO_UNSPEC,
			    "_fax-ipp._tcp", NULL, 0,
			    browse_callback, devices);
  avahi_service_browser_new(client, AVAHI_IF_UNSPEC,
			    AVAHI_PROTO_UNSPEC,
			    "_ipp._tcp", NULL, 0,
			    browse_callback, devices);
  avahi_service_browser_new(client, AVAHI_IF_UNSPEC,
			    AVAHI_PROTO_UNSPEC,
			    "_ipp-tls._tcp", NULL, 0,
			    browse_callback, devices);
  avahi_service_browser_new(client, AVAHI_IF_UNSPEC,
			    AVAHI_PROTO_UNSPEC,
			    "_ipps._tcp", NULL, 0,
			    browse_callback, devices);
  avahi_service_browser_new(client, AVAHI_IF_UNSPEC,
			    AVAHI_PROTO_UNSPEC,
			    "_pdl-datastream._tcp",
			    NULL, 0,
			    browse_callback,
			    devices);
  avahi_service_browser_new(client, AVAHI_IF_UNSPEC,
			    AVAHI_PROTO_UNSPEC,
			    "_printer._tcp", NULL, 0,
			    browse_callback, devices);
#endif /* HAVE_AVAHI */

 /*
  * Loop until we are killed...
  */

  while (!job_canceled)
  {
    int announce = 0;			/* Announce printers? */

#ifdef HAVE_DNSSD
    FD_ZERO(&input);
    FD_SET(fd, &input);

    timeout.tv_sec  = 0;
    timeout.tv_usec = 500000;

    if (select(fd + 1, &input, NULL, NULL, &timeout) < 0)
      continue;

    if (FD_ISSET(fd, &input))
    {
     /*
      * Process results of our browsing...
      */

      DNSServiceProcessResult(main_ref);
    }
    else
      announce = 1;

#elif defined(HAVE_AVAHI)
    got_data = 0;

    if ((error = avahi_simple_poll_iterate(simple_poll, 500)) > 0)
    {
     /*
      * We've been told to exit the loop.  Perhaps the connection to
      * Avahi failed.
      */

      break;
    }

    if (!got_data)
      announce = 1;
#endif /* HAVE_DNSSD */

/*    fprintf(stderr, "DEBUG: announce=%d\n", announce);*/

    if (announce)
    {
     /*
      * Announce any devices we've found...
      */

#ifdef HAVE_DNSSD
      DNSServiceErrorType status;	/* DNS query status */
#endif /* HAVE_DNSSD */
      cups_device_t *best;		/* Best matching device */
      char	device_uri[1024];	/* Device URI */
      int	count;			/* Number of queries */
      int	sent;			/* Number of sent */

      for (device = (cups_device_t *)cupsArrayFirst(devices),
               best = NULL, count = 0, sent = 0;
           device;
	   device = (cups_device_t *)cupsArrayNext(devices))
      {
        if (device->sent)
	  sent ++;

        if (device->ref)
	  count ++;

        if (!device->ref && !device->sent)
	{
	 /*
	  * Found the device, now get the TXT record(s) for it...
	  */

          if (count < 50)
	  {
	    fprintf(stderr, "DEBUG: Querying \"%s\"...\n", device->fullName);

#ifdef HAVE_DNSSD
	    device->ref = main_ref;

	    status = DNSServiceQueryRecord(&(device->ref),
				           kDNSServiceFlagsShareConnection,
				           0, device->fullName,
					   kDNSServiceType_TXT,
				           kDNSServiceClass_IN, query_callback,
				           device);
            if (status != kDNSServiceErr_NoError)
	      fprintf(stderr,
	              "ERROR: Unable to query \"%s\" for TXT records: %d\n",
	              device->fullName, status);
	              			/* Users never see this */
	    else
	      count ++;

#else
	    if ((device->ref = avahi_record_browser_new(client, AVAHI_IF_UNSPEC,
	                                                AVAHI_PROTO_UNSPEC,
	                                                device->fullName,
	                                                AVAHI_DNS_CLASS_IN,
	                                                AVAHI_DNS_TYPE_TXT,
	                                                0,
				                        query_callback,
				                        device)) == NULL)
	      fprintf(stderr,
	              "ERROR: Unable to query \"%s\" for TXT records: %s\n",
	              device->fullName,
	              avahi_strerror(avahi_client_errno(client)));
	              			/* Users never see this */
	    else
	      count ++;
#endif /* HAVE_AVAHI */
          }
	}
	else if (!device->sent)
	{
#ifdef HAVE_DNSSD
	 /*
	  * Got the TXT records, now report the device...
	  */

	  DNSServiceRefDeallocate(device->ref);
#else
          avahi_record_browser_free(device->ref);
#endif /* HAVE_DNSSD */

	  device->ref = NULL;

          if (!best)
	    best = device;
	  else if (_cups_strcasecmp(best->name, device->name) ||
	           _cups_strcasecmp(best->domain, device->domain))
          {
	    unquote(uriName, best->fullName, sizeof(uriName));

            if (best->uuid)
	      httpAssembleURIf(HTTP_URI_CODING_ALL, device_uri,
	                       sizeof(device_uri), "dnssd", NULL, uriName, 0,
			       best->cups_shared ? "/cups?uuid=%s" : "/?uuid=%s",
			       best->uuid);
	    else
	      httpAssembleURI(HTTP_URI_CODING_ALL, device_uri,
	                      sizeof(device_uri), "dnssd", NULL, uriName, 0,
			      best->cups_shared ? "/cups" : "/");

	    cupsBackendReport("network", device_uri, best->make_and_model,
	                      best->name, best->device_id, NULL);
	    best->sent = 1;
	    best       = device;

	    sent ++;
	  }
	  else if (best->priority > device->priority ||
	           (best->priority == device->priority &&
		    best->type < device->type))
          {
	    best->sent = 1;
	    best       = device;

	    sent ++;
	  }
	  else
	  {
	    device->sent = 1;

	    sent ++;
	  }
        }
      }

      if (best)
      {
	unquote(uriName, best->fullName, sizeof(uriName));

	if (best->uuid)
	  httpAssembleURIf(HTTP_URI_CODING_ALL, device_uri,
			   sizeof(device_uri), "dnssd", NULL, uriName, 0,
			   best->cups_shared ? "/cups?uuid=%s" : "/?uuid=%s",
			   best->uuid);
	else
	  httpAssembleURI(HTTP_URI_CODING_ALL, device_uri,
			  sizeof(device_uri), "dnssd", NULL, uriName, 0,
			  best->cups_shared ? "/cups" : "/");

	cupsBackendReport("network", device_uri, best->make_and_model,
			  best->name, best->device_id, NULL);
	best->sent = 1;
	sent ++;
      }

      fprintf(stderr, "DEBUG: sent=%d, count=%d\n", sent, count);

#ifdef HAVE_AVAHI
      if (sent == cupsArrayCount(devices) && browsers == 0)
#else
      if (sent == cupsArrayCount(devices))
#endif /* HAVE_AVAHI */
	break;
    }
  }

  return (CUPS_BACKEND_OK);
}
Ejemplo n.º 14
0
mime_t *				/* O - Updated MIME database */
mimeMerge(mime_t     *mime,		/* I - MIME database to add to */
          const char *pathname,		/* I - Directory to load */
          const char *filterpath)	/* I - Directory to load */
{
  cups_dir_t	*dir;			/* Directory */
  cups_dentry_t	*dent;			/* Directory entry */
  char		filename[1024];		/* Full filename of types/converts file */
  cups_array_t	*filtercache;		/* Filter cache */


 /*
  * First open the directory specified by pathname...  Return NULL if nothing
  * was read or if the pathname is NULL...
  */

  if (!pathname)
    return (NULL);

  if ((dir = cupsDirOpen(pathname)) == NULL)
    return (NULL);

 /*
  * If "mime" is NULL, make a new, blank database...
  */

  if (!mime)
    mime = mimeNew();
  if (!mime)
  {
    cupsDirClose(dir);
    return (NULL);
  }

 /*
  * Read all the .types files...
  */

  while ((dent = cupsDirRead(dir)) != NULL)
  {
    if (strlen(dent->filename) > 6 &&
        !strcmp(dent->filename + strlen(dent->filename) - 6, ".types"))
    {
     /*
      * Load a mime.types file...
      */

      snprintf(filename, sizeof(filename), "%s/%s", pathname, dent->filename);
      load_types(mime, filename);
    }
  }

  cupsDirRewind(dir);

 /*
  * Read all the .convs files...
  */

  filtercache = cupsArrayNew((cups_array_func_t)compare_fcache, NULL);

  while ((dent = cupsDirRead(dir)) != NULL)
  {
    if (strlen(dent->filename) > 6 &&
        !strcmp(dent->filename + strlen(dent->filename) - 6, ".convs"))
    {
     /*
      * Load a mime.convs file...
      */

      snprintf(filename, sizeof(filename), "%s/%s", pathname, dent->filename);
      load_convs(mime, filename, filterpath, filtercache);
    }
  }

  delete_fcache(filtercache);

  cupsDirClose(dir);

  return (mime);
}
Ejemplo n.º 15
0
static void
read_snmp_conf(const char *address)	/* I - Single address to probe */
{
  cups_file_t	*fp;			/* File pointer */
  char		filename[1024],		/* Filename */
		line[1024],		/* Line from file */
		*value;			/* Value on line */
  int		linenum;		/* Line number */
  const char	*cups_serverroot;	/* CUPS_SERVERROOT env var */
  const char	*debug;			/* CUPS_DEBUG_LEVEL env var */
  const char	*runtime;		/* CUPS_MAX_RUN_TIME env var */


 /*
  * Initialize the global address and community lists...
  */

  Addresses   = cupsArrayNew(NULL, NULL);
  Communities = cupsArrayNew(NULL, NULL);

  if (address)
    add_array(Addresses, address);

  if ((debug = getenv("CUPS_DEBUG_LEVEL")) != NULL)
    DebugLevel = atoi(debug);

  if ((runtime = getenv("CUPS_MAX_RUN_TIME")) != NULL)
    MaxRunTime = atoi(runtime);

 /*
  * Find the snmp.conf file...
  */

  if ((cups_serverroot = getenv("CUPS_SERVERROOT")) == NULL)
    cups_serverroot = CUPS_SERVERROOT;

  snprintf(filename, sizeof(filename), "%s/snmp.conf", cups_serverroot);

  if ((fp = cupsFileOpen(filename, "r")) != NULL)
  {
   /*
    * Read the snmp.conf file...
    */

    linenum = 0;

    while (cupsFileGetConf(fp, line, sizeof(line), &value, &linenum))
    {
      if (!value)
        fprintf(stderr, "ERROR: Missing value on line %d of %s!\n", linenum,
	        filename);
      else if (!_cups_strcasecmp(line, "Address"))
      {
        if (!address)
          add_array(Addresses, value);
      }
      else if (!_cups_strcasecmp(line, "Community"))
        add_array(Communities, value);
      else if (!_cups_strcasecmp(line, "DebugLevel"))
        DebugLevel = atoi(value);
      else if (!_cups_strcasecmp(line, "DeviceURI"))
      {
        if (*value != '\"')
	  fprintf(stderr,
	          "ERROR: Missing double quote for regular expression on "
		  "line %d of %s!\n", linenum, filename);
        else
	  add_device_uri(value);
      }
      else if (!_cups_strcasecmp(line, "HostNameLookups"))
        HostNameLookups = !_cups_strcasecmp(value, "on") ||
	                  !_cups_strcasecmp(value, "yes") ||
	                  !_cups_strcasecmp(value, "true") ||
	                  !_cups_strcasecmp(value, "double");
      else if (!_cups_strcasecmp(line, "MaxRunTime"))
        MaxRunTime = atoi(value);
      else
        fprintf(stderr, "ERROR: Unknown directive %s on line %d of %s!\n",
	        line, linenum, filename);
    }

    cupsFileClose(fp);
  }

 /*
  * Use defaults if parameters are undefined...
  */

  if (cupsArrayCount(Addresses) == 0)
  {
   /*
    * If we have no addresses, exit immediately...
    */

    fprintf(stderr,
            "DEBUG: No address specified and no Address line in %s...\n",
	    filename);
    exit(0);
  }

  if (cupsArrayCount(Communities) == 0)
  {
    fputs("INFO: Using default SNMP Community public\n", stderr);
    add_array(Communities, "public");
  }
}
Ejemplo n.º 16
0
int					/* O - Exit status */
main(int  argc,				/* I - Number of command-line args */
     char *argv[])			/* I - Command-line arguments */
{
  int		i;			/* Looping var */
  const char	*opt,			/* Current option character */
		*name = NULL,		/* Service name */
		*type = "_ipp._tcp",	/* Service type */
		*domain = "local.";	/* Service domain */
#ifdef HAVE_DNSSD
  DNSServiceRef	ref;			/* Browsing service reference */
#endif /* HAVE_DNSSD */
#ifdef HAVE_AVAHI
  AvahiClient	*client;		/* Client information */
  int		error;			/* Error code, if any */
#endif /* HAVE_AVAHI */


  for (i = 1; i < argc; i ++)
    if (!strcmp(argv[i], "snmp"))
      snmponly = 1;
    else if (!strcmp(argv[i], "ipp"))
      ipponly = 1;
    else
    {
      puts("Usage: ./ipp-printers [{ipp | snmp}]");
      return (1);
    }

 /*
  * Create an array to track devices...
  */

  devices = cupsArrayNew((cups_array_func_t)compare_devices, NULL);

 /*
  * Browse for different kinds of printers...
  */

  if (DNSServiceCreateConnection(&main_ref) != kDNSServiceErr_NoError)
  {
    perror("ERROR: Unable to create service connection");
    return (1);
  }

  fd = DNSServiceRefSockFD(main_ref);

  ipp_ref = main_ref;
  DNSServiceBrowse(&ipp_ref, kDNSServiceFlagsShareConnection, 0,
                   "_ipp._tcp", NULL, browse_callback, devices);

 /*
  * Loop until we are killed...
  */

  progress();

  for (;;)
  {
    FD_ZERO(&input);
    FD_SET(fd, &input);

    timeout.tv_sec  = 2;
    timeout.tv_usec = 500000;

    if (select(fd + 1, &input, NULL, NULL, &timeout) <= 0)
    {
      time_t curtime = time(NULL);

      for (device = (cups_device_t *)cupsArrayFirst(devices);
           device;
	   device = (cups_device_t *)cupsArrayNext(devices))
        if (!device->got_resolve)
        {
          if (!device->ref)
            break;

          if ((curtime - device->resolve_time) > 10)
          {
            device->got_resolve = -1;
	    fprintf(stderr, "\rUnable to resolve \"%s\": timeout\n",
		    device->name);
	    progress();
	  }
          else
            break;
        }

      if (!device)
        break;
    }

    if (FD_ISSET(fd, &input))
    {
     /*
      * Process results of our browsing...
      */

      progress();
      DNSServiceProcessResult(main_ref);
    }
    else
    {
     /*
      * Query any devices we've found...
      */

      DNSServiceErrorType	status;	/* DNS query status */
      int			count;	/* Number of queries */


      for (device = (cups_device_t *)cupsArrayFirst(devices), count = 0;
           device;
	   device = (cups_device_t *)cupsArrayNext(devices))
      {
        if (!device->ref && !device->sent)
	{
	 /*
	  * Found the device, now get the TXT record(s) for it...
	  */

          if (count < 50)
	  {
	    device->resolve_time = time(NULL);
	    device->ref          = main_ref;

	    status = DNSServiceResolve(&(device->ref),
				       kDNSServiceFlagsShareConnection,
				       0, device->name, device->regtype,
				       device->domain, resolve_callback,
				       device);
            if (status != kDNSServiceErr_NoError)
            {
	      fprintf(stderr, "\rUnable to resolve \"%s\": %d\n",
	              device->name, status);
	      progress();
	    }
	    else
	      count ++;
          }
	}
	else if (!device->sent && device->got_resolve)
	{
	 /*
	  * Got the TXT records, now report the device...
	  */

	  DNSServiceRefDeallocate(device->ref);
	  device->ref  = 0;
	  device->sent = 1;
        }
      }
    }
  }

#ifndef DEBUG
  fprintf(stderr, "\rFound %d printers. Now querying for capabilities...\n",
          cupsArrayCount(devices));
#endif /* !DEBUG */

  puts("#!/bin/sh -x");
  puts("test -d results && rm -rf results");
  puts("mkdir results");
  puts("CUPS_DEBUG_LEVEL=6; export CUPS_DEBUG_LEVEL");
  puts("CUPS_DEBUG_FILTER='^(ipp|http|_ipp|_http|cupsGetResponse|cupsSend|"
       "cupsWrite|cupsDo).*'; export CUPS_DEBUG_FILTER");

  for (device = (cups_device_t *)cupsArrayFirst(devices);
       device;
       device = (cups_device_t *)cupsArrayNext(devices))
  {
    if (device->got_resolve <= 0 || device->cups_shared)
      continue;

#ifdef DEBUG
    fprintf(stderr, "Checking \"%s\" (got_resolve=%d, cups_shared=%d, uri=%s)\n",
            device->name, device->got_resolve, device->cups_shared, device->uri);
#else
    fprintf(stderr, "Checking \"%s\"...\n", device->name);
#endif /* DEBUG */

    if ((http = httpConnect(device->host, device->port)) == NULL)
    {
      fprintf(stderr, "Failed to connect to \"%s\": %s\n", device->name,
              cupsLastErrorString());
      continue;
    }

    request = ippNewRequest(IPP_GET_PRINTER_ATTRIBUTES);
    ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL,
                 device->uri);

    response = cupsDoRequest(http, request, device->rp);

    if (cupsLastError() > IPP_OK_SUBST)
      fprintf(stderr, "Failed to query \"%s\": %s\n", device->name,
              cupsLastErrorString());
    else
    {
      if ((attr = ippFindAttribute(response, "ipp-versions-supported",
				   IPP_TAG_KEYWORD)) != NULL)
      {
	version = attr->values[0].string.text;

	for (i = 1; i < attr->num_values; i ++)
	  if (strcmp(attr->values[i].string.text, version) > 0)
	    version = attr->values[i].string.text;
      }
      else
	version = "1.0";

      testfile = NULL;

      if ((attr = ippFindAttribute(response, "document-format-supported",
                                   IPP_TAG_MIMETYPE)) != NULL)
      {
       /*
        * Figure out the test file for printing, preferring PDF and PostScript
        * over JPEG and plain text...
        */

        for (i = 0; i < attr->num_values; i ++)
        {
          if (!strcasecmp(attr->values[i].string.text, "application/pdf"))
          {
            testfile = "testfile.pdf";
            break;
          }
          else if (!strcasecmp(attr->values[i].string.text,
                               "application/postscript"))
            testfile = "testfile.ps";
          else if (!strcasecmp(attr->values[i].string.text, "image/jpeg") &&
                   !testfile)
            testfile = "testfile.jpg";
          else if (!strcasecmp(attr->values[i].string.text, "text/plain") &&
                   !testfile)
            testfile = "testfile.txt";
          else if (!strcasecmp(attr->values[i].string.text,
                               "application/vnd.hp-PCL") && !testfile)
            testfile = "testfile.pcl";
        }

        if (!testfile)
        {
          fprintf(stderr,
                  "Printer \"%s\" reports the following IPP file formats:\n",
                  device->name);
          for (i = 0; i < attr->num_values; i ++)
            fprintf(stderr, "    \"%s\"\n", attr->values[i].string.text);
        }
      }

      if (!testfile && device->pdl)
      {
	char	*pdl,			/* Copy of pdl string */
		*start, *end;		/* Pointers into pdl string */


        pdl = strdup(device->pdl);
	for (start = device->pdl; start && *start; start = end)
	{
	  if ((end = strchr(start, ',')) != NULL)
	    *end++ = '\0';

	  if (!strcasecmp(start, "application/pdf"))
	  {
	    testfile = "testfile.pdf";
	    break;
	  }
	  else if (!strcasecmp(start, "application/postscript"))
	    testfile = "testfile.ps";
	  else if (!strcasecmp(start, "image/jpeg") && !testfile)
	    testfile = "testfile.jpg";
	  else if (!strcasecmp(start, "text/plain") && !testfile)
	    testfile = "testfile.txt";
	  else if (!strcasecmp(start, "application/vnd.hp-PCL") && !testfile)
	    testfile = "testfile.pcl";
	}
	free(pdl);

        if (testfile)
        {
	  fprintf(stderr,
		  "Using \"%s\" for printer \"%s\" based on TXT record pdl "
		  "info.\n", testfile, device->name);
        }
        else
        {
	  fprintf(stderr,
		  "Printer \"%s\" reports the following TXT file formats:\n",
		  device->name);
	  fprintf(stderr, "    \"%s\"\n", device->pdl);
	}
      }

      if (!device->ty &&
	  (attr = ippFindAttribute(response, "printer-make-and-model",
				   IPP_TAG_TEXT)) != NULL)
	device->ty = strdup(attr->values[0].string.text);

      if (strcmp(version, "1.0") && testfile && device->ty)
      {
	char		filename[1024],	/* Filename */
			*fileptr;	/* Pointer into filename */
	const char	*typtr;		/* Pointer into ty */

        if (!strncasecmp(device->ty, "DeskJet", 7) ||
            !strncasecmp(device->ty, "DesignJet", 9) ||
            !strncasecmp(device->ty, "OfficeJet", 9) ||
            !strncasecmp(device->ty, "Photosmart", 10))
          strlcpy(filename, "HP_", sizeof(filename));
        else
          filename[0] = '\0';

	fileptr = filename + strlen(filename);

        if (!strncasecmp(device->ty, "Lexmark International Lexmark", 29))
          typtr = device->ty + 22;
        else
          typtr = device->ty;

	while (*typtr && fileptr < (filename + sizeof(filename) - 1))
	{
	  if (isalnum(*typtr & 255) || *typtr == '-')
	    *fileptr++ = *typtr++;
	  else
	  {
	    *fileptr++ = '_';
	    typtr++;
	  }
	}

	*fileptr = '\0';

        printf("# %s\n", device->name);
        printf("echo \"Testing %s...\"\n", device->name);

        if (!ipponly)
        {
	  printf("echo \"snmpwalk -c public -v 1 -Cc %s 1.3.6.1.2.1.25 "
	         "1.3.6.1.2.1.43 1.3.6.1.4.1.2699.1\" > results/%s.snmpwalk\n",
	         device->host, filename);
	  printf("snmpwalk -c public -v 1 -Cc %s 1.3.6.1.2.1.25 "
	         "1.3.6.1.2.1.43 1.3.6.1.4.1.2699.1 | "
	         "tee -a results/%s.snmpwalk\n",
	         device->host, filename);
        }

        if (!snmponly)
        {
	  printf("echo \"./ipptool-static -tIf %s -T 30 -d NOPRINT=1 -V %s %s "
	         "ipp-%s.test\" > results/%s.log\n", testfile, version,
	         device->uri, version, filename);
	  printf("CUPS_DEBUG_LOG=results/%s.debug_log "
	         "./ipptool-static -tIf %s -T 30 -d NOPRINT=1 -V %s %s "
	         "ipp-%s.test | tee -a results/%s.log\n", filename,
	         testfile, version, device->uri,
	         version, filename);
        }

	puts("");
      }
      else if (!device->ty)
	fprintf(stderr,
		"Ignoring \"%s\" since it doesn't provide a make and model.\n",
		device->name);
      else if (!testfile)
	fprintf(stderr,
	        "Ignoring \"%s\" since it does not support a common format.\n",
		device->name);
      else
	fprintf(stderr, "Ignoring \"%s\" since it only supports IPP/1.0.\n",
		device->name);
    }

    ippDelete(response);
    httpClose(http);
  }

  return (0);
}
Ejemplo n.º 17
0
cups_array_t *				/* O - Array of filters to run */
mimeFilter2(mime_t      *mime,		/* I - MIME database */
            mime_type_t *src,		/* I - Source file type */
	    size_t      srcsize,	/* I - Size of source file */
	    mime_type_t *dst,		/* I - Destination file type */
	    int         *cost)		/* O - Cost of filters */
{
  cups_array_t	*filters;		/* Array of filters to run */


 /*
  * Range-check the input...
  */

  DEBUG_printf(("mimeFilter2(mime=%p, src=%p(%s/%s), srcsize=" CUPS_LLFMT
                ", dst=%p(%s/%s), cost=%p(%d))", mime,
        	src, src ? src->super : "???", src ? src->type : "???",
		CUPS_LLCAST srcsize,
		dst, dst ? dst->super : "???", dst ? dst->type : "???",
		cost, cost ? *cost : 0));

  if (cost)
    *cost = 0;

  if (!mime || !src || !dst)
    return (NULL);

 /*
  * (Re)build the source lookup array as needed...
  */

  if (!mime->srcs)
  {
    mime_filter_t	*current;	/* Current filter */

    mime->srcs = cupsArrayNew((cups_array_func_t)mime_compare_srcs, NULL);

    for (current = mimeFirstFilter(mime);
         current;
	 current = mimeNextFilter(mime))
      cupsArrayAdd(mime->srcs, current);
  }

 /*
  * Find the filters...
  */

  filters = mime_find_filters(mime, src, srcsize, dst, cost, NULL);

  DEBUG_printf(("1mimeFilter2: Returning %d filter(s), cost %d:",
                cupsArrayCount(filters), cost ? *cost : -1));
#ifdef DEBUG
  {
    mime_filter_t	*filter;	/* Current filter */

    for (filter = (mime_filter_t *)cupsArrayFirst(filters);
         filter;
	 filter = (mime_filter_t *)cupsArrayNext(filters))
      DEBUG_printf(("1mimeFilter2: %s/%s %s/%s %d %s", filter->src->super,
                    filter->src->type, filter->dst->super, filter->dst->type,
		    filter->cost, filter->filter));
  }
#endif /* DEBUG */

  return (filters);
}
Ejemplo n.º 18
0
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 = (size_t)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);
}
Ejemplo n.º 19
0
mime_filter_t *				/* O - New filter */
mimeAddFilter(mime_t      *mime,	/* I - MIME database */
              mime_type_t *src,		/* I - Source type */
	      mime_type_t *dst,		/* I - Destination type */
              int         cost,		/* I - Relative time/resource cost */
	      const char  *filter)	/* I - Filter program to run */
{
  mime_filter_t	*temp;			/* New filter */


  DEBUG_printf(("mimeAddFilter(mime=%p, src=%p(%s/%s), dst=%p(%s/%s), cost=%d, "
                "filter=\"%s\")", mime,
		src, src ? src->super : "???", src ? src->type : "???",
		dst, dst ? dst->super : "???", dst ? dst->type : "???",
		cost, filter));
		
 /*
  * Range-check the input...
  */

  if (!mime || !src || !dst || !filter)
  {
    DEBUG_puts("1mimeAddFilter: Returning NULL.");
    return (NULL);
  }

 /*
  * See if we already have an existing filter for the given source and
  * destination...
  */

  if ((temp = mimeFilterLookup(mime, src, dst)) != NULL)
  {
   /*
    * Yup, does the existing filter have a higher cost?  If so, copy the
    * filter and cost to the existing filter entry and return it...
    */

    if (temp->cost > cost)
    {
      DEBUG_printf(("1mimeAddFilter: Replacing filter \"%s\", cost %d.",
                    temp->filter, temp->cost));
      temp->cost = cost;
      strlcpy(temp->filter, filter, sizeof(temp->filter));
    }
  }
  else
  {
   /*
    * Nope, add a new one...
    */

    if (!mime->filters)
      mime->filters = cupsArrayNew((cups_array_func_t)mime_compare_filters, NULL);

    if (!mime->filters)
      return (NULL);

    if ((temp = calloc(1, sizeof(mime_filter_t))) == NULL)
      return (NULL);

   /*
    * Copy the information over and sort if necessary...
    */

    temp->src  = src;
    temp->dst  = dst;
    temp->cost = cost;
    strlcpy(temp->filter, filter, sizeof(temp->filter));

    DEBUG_puts("1mimeAddFilter: Adding new filter.");
    cupsArrayAdd(mime->filters, temp);
    cupsArrayAdd(mime->srcs, temp);
  }

 /*
  * Return the new/updated filter...
  */

  DEBUG_printf(("1mimeAddFilter: Returning %p.", temp));

  return (temp);
}
Ejemplo n.º 20
0
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);
}
Ejemplo n.º 21
0
mime_t *				/* O - MIME database */
mimeLoadFilters(mime_t     *mime,	/* I - MIME database */
                const char *pathname,	/* I - Directory to load from */
                const char *filterpath)	/* I - Default filter program directory */
{
  cups_dir_t	*dir;			/* Directory */
  cups_dentry_t	*dent;			/* Directory entry */
  char		filename[1024];		/* Full filename of .convs file */
  cups_array_t	*filtercache;		/* Filter cache */


  DEBUG_printf(("mimeLoadFilters(mime=%p, pathname=\"%s\", filterpath=\"%s\")",
		mime, pathname, filterpath));

 /*
  * Range check input...
  */

  if (!mime || !pathname || !filterpath)
  {
    DEBUG_puts("1mimeLoadFilters: Bad arguments.");
    return (mime);
  }

 /*
  * Then open the directory specified by pathname...
  */

  if ((dir = cupsDirOpen(pathname)) == NULL)
  {
    DEBUG_printf(("1mimeLoadFilters: Unable to open \"%s\": %s", pathname,
                  strerror(errno)));
    _mimeError(mime, "Unable to open \"%s\": %s", pathname, strerror(errno));
    return (mime);
  }

 /*
  * Read all the .convs files...
  */

  filtercache = cupsArrayNew((cups_array_func_t)mime_compare_fcache, NULL);

  while ((dent = cupsDirRead(dir)) != NULL)
  {
    if (strlen(dent->filename) > 6 &&
        !strcmp(dent->filename + strlen(dent->filename) - 6, ".convs"))
    {
     /*
      * Load a mime.convs file...
      */

      snprintf(filename, sizeof(filename), "%s/%s", pathname, dent->filename);
      DEBUG_printf(("1mimeLoadFilters: Loading \"%s\".", filename));
      mime_load_convs(mime, filename, filterpath, filtercache);
    }
  }

  mime_delete_fcache(filtercache);

  cupsDirClose(dir);

  return (mime);
}
Ejemplo n.º 22
0
static int				/* O - 0 on success, 1 on error */
exec_filters(cups_array_t  *filters,	/* I - Array of filters to run */
	     char	   **argv)	/* I - Filter options */
{
  int		i;			/* Looping var */
  char		program[1024];		/* Program to run */
  char		*filter,		/* Current filter */
		*next;			/* Next filter */
  int		current,		/* Current filter */
		filterfds[2][2],	/* Pipes for filters */
		pid,			/* Process ID of filter */
		status,			/* Exit status */
		retval;			/* Return value */
  cups_array_t	*pids;			/* Executed filters array */
  filter_pid_t	*pid_entry,		/* Entry in executed filters array */
		key;			/* Search key for filters */
  const char	*cups_serverbin;	/* CUPS_SERVERBIN environment variable */

 /*
  * Remove NULL ("-") filters...
  */

  for (filter = (char *)cupsArrayFirst(filters);
       filter;
       filter = (char *)cupsArrayNext(filters))
    if (!strcmp(filter, "-"))
      cupsArrayRemove(filters, filter);

  for (i = 0; argv[i]; i ++)
    fprintf(stderr, "DEBUG: argv[%d]=\"%s\"\n", i, argv[i]);

 /*
  * Execute all of the filters...
  */

  pids            = cupsArrayNew((cups_array_func_t)compare_pids, NULL);
  current         = 0;
  filterfds[0][0] = 0;
  filterfds[0][1] = -1;
  filterfds[1][0] = -1;
  filterfds[1][1] = -1;

  for (filter = (char *)cupsArrayFirst(filters);
       filter;
       filter = next, current = 1 - current)
  {
    next = (char *)cupsArrayNext(filters);

    if (filter[0] == '/')
      strncpy(program, filter, sizeof(program));
    else
    {
      if ((cups_serverbin = getenv("CUPS_SERVERBIN")) == NULL)
	cups_serverbin = CUPS_SERVERBIN;
      snprintf(program, sizeof(program), "%s/filter/%s", cups_serverbin,
	       filter);
    }

    if (filterfds[!current][1] > 1)
    {
      close(filterfds[1 - current][0]);
      close(filterfds[1 - current][1]);

      filterfds[1 - current][0] = -1;
      filterfds[1 - current][0] = -1;
    }

    if (next)
      open_pipe(filterfds[1 - current]);
    else
      filterfds[1 - current][1] = 1;

    pid = exec_filter(program, argv,
                      filterfds[current][0], filterfds[1 - current][1]);

    if (pid > 0)
    {
      fprintf(stderr, "INFO: %s (PID %d) started.\n", filter, pid);

      pid_entry = malloc(sizeof(filter_pid_t));
      pid_entry->pid = pid;
      pid_entry->name = filter;
      cupsArrayAdd(pids, pid_entry);
    }
    else
      break;

    argv[6] = NULL;
  }

 /*
  * Close remaining pipes...
  */

  if (filterfds[0][1] > 1)
  {
    close(filterfds[0][0]);
    close(filterfds[0][1]);
  }

  if (filterfds[1][1] > 1)
  {
    close(filterfds[1][0]);
    close(filterfds[1][1]);
  }

 /*
  * Wait for the children to exit...
  */

  retval = 0;

  while (cupsArrayCount(pids) > 0)
  {
    if ((pid = wait(&status)) < 0)
    {
      if (errno == EINTR && job_canceled)
      {
	fprintf(stderr, "DEBUG: Job canceled, killing filters ...\n");
	for (pid_entry = (filter_pid_t *)cupsArrayFirst(pids);
	     pid_entry;
	     pid_entry = (filter_pid_t *)cupsArrayNext(pids))
	  kill(pid_entry->pid, SIGTERM);
	job_canceled = 0;
      }
      else
	continue;
    }

    key.pid = pid;
    if ((pid_entry = (filter_pid_t *)cupsArrayFind(pids, &key)) != NULL)
    {
      cupsArrayRemove(pids, pid_entry);

      if (status)
      {
	if (WIFEXITED(status))
	  fprintf(stderr, "ERROR: %s (PID %d) stopped with status %d\n",
		  pid_entry->name, pid, WEXITSTATUS(status));
	else
	  fprintf(stderr, "ERROR: %s (PID %d) crashed on signal %d\n",
		  pid_entry->name, pid, WTERMSIG(status));

        retval = 1;
      }
      else
        fprintf(stderr, "INFO: %s (PID %d) exited with no errors.\n",
	        pid_entry->name, pid);

      free(pid_entry);
    }
  }

  cupsArrayDelete(pids);

  return (retval);
}
Ejemplo n.º 23
0
char *					/* O - String pointer */
_cupsStrAlloc(const char *s)		/* I - 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...
  */

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

    return (NULL);
  }

  item->ref_count = 1;
  strcpy(item->str, s);

#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);
}
Ejemplo n.º 24
0
int					/* O - Exit status */
main(int  argc,				/* I - Number of command-line args */
     char *argv[])			/* I - Command-line arguments */
{
  int		i;			/* Looping var */
  output_format_t    output_format;     /* Output format */
  int		fd = 0;			/* Copy file descriptor */
  char		*filename,		/* PDF file to convert */
		tempfile[1024];		/* Temporary file */
  char		buffer[8192];		/* Copy buffer */
  int		bytes;			/* Bytes copied */
  int		num_options;		/* Number of options */
  cups_option_t	*options;		/* Options */
  const char	*val;			/* Option value */
  char	        *argv_nt[8];		/* NULL-terminated array of the command
					   line arguments */
  int           optbuflen;
  cups_array_t  *filter_chain;          /* Filter chain to execute */
  int		exit_status = 0;	/* Exit status */
  int		color_printing;		/* Do we print in color? */
  char		*filter, *p;
#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
  struct sigaction action;		/* Actions for POSIX signals */
#endif /* HAVE_SIGACTION && !HAVE_SIGSET */
  static const char * const color_mode_option_names[] =
    {	/* Possible names for a color mode option */
      "pwg-raster-document-type",
      "PwgRasterDocumentType",
      "print-color-mode",
      "PrintColorMode",
      "color-space",
      "ColorSpace",
      "color-model",
      "ColorModel",
      NULL
    };


 /*
  * Make sure status messages are not buffered...
  */

  setbuf(stderr, NULL);

 /*
  * Ignore broken pipe signals...
  */

  signal(SIGPIPE, SIG_IGN);

 /*
  * Make sure we have the right number of arguments for CUPS!
  */

  if (argc < 6 || argc > 7)
  {
    fprintf(stderr, "Usage: %s job user title copies options [file]\n",
	    argv[0]);
    return (1);
  }

 /*
  * Register a signal handler to cleanly cancel a job.
  */

#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
  sigset(SIGTERM, cancel_job);
#elif defined(HAVE_SIGACTION)
  memset(&action, 0, sizeof(action));

  sigemptyset(&action.sa_mask);
  action.sa_handler = cancel_job;
  sigaction(SIGTERM, &action, NULL);
#else
  signal(SIGTERM, cancel_job);
#endif /* HAVE_SIGSET */

 /*
  * Copy stdin if needed...
  */

  if (argc == 6)
  {
   /*
    * Copy stdin to a temp file...
    */

    if ((fd = cupsTempFd(tempfile, sizeof(tempfile))) < 0)
    {
      perror("DEBUG: Unable to copy PDF file");
      return (1);
    }

    fprintf(stderr, "DEBUG: sys5ippprinter - copying to temp print file \"%s\"\n",
            tempfile);

    while ((bytes = fread(buffer, 1, sizeof(buffer), stdin)) > 0)
      bytes = write(fd, buffer, bytes);

    close(fd);

    filename = tempfile;
  }
  else
  {
   /*
    * Use the filename on the command-line...
    */

    filename    = argv[6];
    tempfile[0] = '\0';
  }

 /*
  * Get the options from the fifth command line argument
  */

  num_options = cupsParseOptions(argv[5], 0, &options);

 /*
  * Copy the command line arguments into a NULL-terminated array
  */

  for (i = 0; i < 5; i++)
    argv_nt[i] = argv[i];
  /* We copy the contents of argv[5] into a somewhat larger buffer so that
     we can manipulate it */
  optbuflen = strlen(argv[5]) + 256;
  argv_nt[5] = calloc(optbuflen, sizeof(char));
  strcpy(argv_nt[5], (const char*)argv[5]);
  argv_nt[6] = filename;
  argv_nt[7] = NULL;

 /*
  * Create filter chain
  */

  filter_chain = cupsArrayNew(NULL, NULL);

 /*
  * Add the gziptoany filter if installed
  */

  if (filter_present("gziptoany"))
    cupsArrayAdd(filter_chain, "gziptoany");

 /*
  * If the rastertopdf filter is present and the input is in PWG Raster format
  * add the rastertopdf filter to the filter chain to support the PWG Raster
  * input. Same for JPEG input if imagetopdf is present. This way the PPD-less
  * auto-generated print queue emulates an IPP Everywhere printer, as PPDed
  * CUPS queues do.
  */
  
  if (filter_present("rastertopdf") && (val = getenv("CONTENT_TYPE")) != NULL &&
      strcasestr(val, "pwg-raster") != NULL) {
    cupsArrayAdd(filter_chain, "rastertopdf");
  } else if (filter_present("imagetopdf") &&
	     (val = getenv("CONTENT_TYPE")) != NULL &&
	     strcasestr(val, "jpeg") != NULL) {
    cupsArrayAdd(filter_chain, "imagetopdf");
  }

 /*
  * Check the presence of the pdftopdf filter and add it to the filter
  * chain if it is there
  */

  if (filter_present("pdftopdf"))
    cupsArrayAdd(filter_chain, "pdftopdf");

 /*
  * Select the output format: PDF, PostScript, PWG Raster, PCL-XL, and
  * PCL 5c/e
  * Add the needed filters to the filter chain
  */

  if ((val = cupsGetOption("output-format", num_options, options)) != NULL)
  {
    if (strcasestr(val, "raster"))
    {
      output_format = PWGRASTER;
      /* PWG Raster output */
      set_option_in_str(argv_nt[5], optbuflen, "MediaClass", NULL);
      set_option_in_str(argv_nt[5], optbuflen, "media-class", "PwgRaster");
      if (filter_present("gstoraster") && access(CUPS_GHOSTSCRIPT, X_OK) == 0)
	cupsArrayAdd(filter_chain, "gstoraster");
      else
      {
	fprintf(stderr,
		"DEBUG: Filter gstoraster or Ghostscript (%s) missing for \"output-format=%s\", using pdftoraster.\n", CUPS_GHOSTSCRIPT, val);
	if (filter_present("pdftoraster"))
	  cupsArrayAdd(filter_chain, "pdftoraster");
	else
	{
	  fprintf(stderr,
		  "ERROR: Filter pdftoraster missing for \"output-format=%s\"\n", val);
	  exit_status = 1;
	  goto error;
	}
      }
    }
    else if (strcasestr(val, "pdf"))
      output_format = PDF;
    else if (strcasestr(val, "postscript"))
    {
      output_format = POSTSCRIPT;
      if (filter_present("pdftops"))
      {
	cupsArrayAdd(filter_chain, "pdftops");
	if (access(CUPS_GHOSTSCRIPT, X_OK) != 0)
	{
	  fprintf(stderr,
		  "DEBUG: Ghostscript (%s) missing for \"output-format=%s\", using Poppler's pdftops instead.\n", CUPS_GHOSTSCRIPT, val);
	  set_option_in_str(argv_nt[5], optbuflen, "pdftops-renderer",
			    "pdftops");
	}
	else if (access(CUPS_POPPLER_PDFTOPS, X_OK) != 0)
	{
	  fprintf(stderr,
		  "DEBUG: Poppler's pdftops (%s) missing for \"output-format=%s\", using Ghostscript instead.\n", CUPS_POPPLER_PDFTOPS, val);
	  set_option_in_str(argv_nt[5], optbuflen, "pdftops-renderer",
			    "gs");
	}
	else
	  set_option_in_str(argv_nt[5], optbuflen, "pdftops-renderer",
			    "hybrid");
      }
      else
      {
	fprintf(stderr,
		"ERROR: Filter pdftops missing for \"output-format=%s\"\n", val);
	exit_status = 1;
	goto error;
      }
    }
    else if ((p = strcasestr(val, "pcl")) != NULL)
    {
      if (!strcasecmp(p, "pclxl"))
      {
	output_format = PCLXL;
	if (filter_present("gstopxl") && access(CUPS_GHOSTSCRIPT, X_OK) == 0)
	  cupsArrayAdd(filter_chain, "gstopxl");
	else
	{
	  fprintf(stderr,
		  "DEBUG: Filter gstopxl or Ghostscript (%s) missing for \"output-format=%s\", falling back to PCL 5c/e.\n", CUPS_GHOSTSCRIPT, val);
	  output_format = PCL;
	}
      }
      else
      {
	output_format = PCL;
      }
    }
    else
    {
      fprintf(stderr,
	      "ERROR: Invalid value for \"output-format\": \"%s\"\n", val);
      exit_status = 1;
      goto error;
    }
  }
  else
  {
    fprintf(stderr,
	    "ERROR: Missing option \"output-format\".\n");
    exit_status = 1;
    goto error;
  }
  if (output_format == PCL)
  {
    /* We need CUPS Raster as we want to use rastertopclx with unprintable
       margins */
    set_option_in_str(argv_nt[5], optbuflen, "MediaClass", NULL);
    set_option_in_str(argv_nt[5], optbuflen, "media-class", "");
    /* Does the client send info about margins? */
    if (!get_option_in_str(argv_nt[5], "media-left-margin", 0) &&
	!get_option_in_str(argv_nt[5], "media-right-margin", 0) &&
	!get_option_in_str(argv_nt[5], "media-top-margin", 0) &&
	!get_option_in_str(argv_nt[5], "media-bottom-margin", 0))
    {
      /* Set default 12pt margins if there is no info about printer's
	 unprintable margins (100th of mm units, 12.0 * 2540.0 / 72.0 = 423.33)
      */
      set_option_in_str(argv_nt[5], optbuflen, "media-left-margin", "423.33");
      set_option_in_str(argv_nt[5], optbuflen, "media-right-margin", "423.33");
      set_option_in_str(argv_nt[5], optbuflen, "media-top-margin", "423.33");
      set_option_in_str(argv_nt[5], optbuflen, "media-bottom-margin", "423.33");
    }
    /* Check whether the job is requested to be printed in color and if so,
       set the color space to RGB as this is the best color printing support
       in PCL 5c */
    color_printing = 0;
    for (i = 0; color_mode_option_names[i]; i ++)
    {
      p = get_option_in_str(argv_nt[5], color_mode_option_names[i], 1);
      if (p && (strcasestr(p, "RGB") || strcasestr(p, "CMY") ||
		strcasestr(p, "color")))
      {
	color_printing = 1;
	break;
      }
    }
    if (color_printing == 1)
    {
      /* Remove unneeded color mode options */
      for (i = 0; color_mode_option_names[i]; i ++)
	set_option_in_str(argv_nt[5], optbuflen, color_mode_option_names[i],
			  NULL);
      /* Set RGB as color mode */
      set_option_in_str(argv_nt[5], optbuflen, "print-color-mode", "RGB");
    }
    if (filter_present("gstoraster") && access(CUPS_GHOSTSCRIPT, X_OK) == 0)
      cupsArrayAdd(filter_chain, "gstoraster");
    else
    {
      fprintf(stderr,
	      "DEBUG: Filter gstoraster or Ghostscript (%s) missing for \"output-format=%s\", using pdftoraster.\n", CUPS_GHOSTSCRIPT, val);
      if (filter_present("pdftoraster"))
	cupsArrayAdd(filter_chain, "pdftoraster");
      else
      {
	fprintf(stderr,
		"ERROR: Filter pdftoraster missing for \"output-format=%s\"\n", val);
	exit_status = 1;
	goto error;
      }
    }
    if (filter_present("rastertopclx"))
      cupsArrayAdd(filter_chain, "rastertopclx");
    else
    {
      fprintf(stderr,
	      "ERROR: Filter rastertopclx missing for \"output-format=%s\"\n", val);
      exit_status = 1;
      goto error;
    }
  }

  fprintf(stderr,
	  "DEBUG: Printer supports output formats: %s\nDEBUG: Using following CUPS filter chain to convert input data to the %s format:",
	  val,
	  output_format == PDF ? "PDF" :
	  (output_format == POSTSCRIPT ? "Postscript" :
	   (output_format == PWGRASTER ? "PWG Raster" :
	    (output_format == PCLXL ? "PCL XL" :
	     (output_format == PCL ? "PCL 5c/e" : "unknown")))));
  for (filter = (char *)cupsArrayFirst(filter_chain);
       filter;
       filter = (char *)cupsArrayNext(filter_chain))
    fprintf(stderr, " %s", filter);
  fprintf(stderr, "\n");

 /*
  * Execute the filter chain
  */

  exit_status = exec_filters(filter_chain, (char **)argv_nt);

 /*
  * Cleanup and exit...
  */

  error:

  if (tempfile[0])
    unlink(tempfile);

  return (exit_status);
}
Ejemplo n.º 25
0
char *					/* O - String containing option code or @code NULL@ if there is no option code */
ppdEmitString(ppd_file_t    *ppd,	/* I - PPD file record */
              ppd_section_t section,	/* I - Section to write */
	      float         min_order)	/* I - Lowest OrderDependency */
{
  int		i, j,			/* Looping vars */
		count;			/* Number of choices */
  ppd_choice_t	**choices;		/* Choices */
  ppd_size_t	*size;			/* Custom page size */
  ppd_coption_t	*coption;		/* Custom option */
  ppd_cparam_t	*cparam;		/* Custom parameter */
  size_t	bufsize;		/* Size of string buffer needed */
  char		*buffer,		/* String buffer */
		*bufptr,		/* Pointer into buffer */
		*bufend;		/* End of buffer */
  struct lconv	*loc;			/* Locale data */


  DEBUG_printf(("ppdEmitString(ppd=%p, section=%d, min_order=%f)",
                ppd, section, min_order));

 /*
  * Range check input...
  */

  if (!ppd)
    return (NULL);

 /*
  * Use PageSize or PageRegion as required...
  */

  ppd_handle_media(ppd);

 /*
  * Collect the options we need to emit...
  */

  if ((count = ppdCollect2(ppd, section, min_order, &choices)) == 0)
    return (NULL);

 /*
  * Count the number of bytes that are required to hold all of the
  * option code...
  */

  for (i = 0, bufsize = 1; i < count; i ++)
  {
    if (section == PPD_ORDER_JCL)
    {
      if (!_cups_strcasecmp(choices[i]->choice, "Custom") &&
	  (coption = ppdFindCustomOption(ppd, choices[i]->option->keyword))
	      != NULL)
      {
       /*
        * Add space to account for custom parameter substitution...
	*/

        for (cparam = (ppd_cparam_t *)cupsArrayFirst(coption->params);
	     cparam;
	     cparam = (ppd_cparam_t *)cupsArrayNext(coption->params))
	{
          switch (cparam->type)
	  {
	    case PPD_CUSTOM_CURVE :
	    case PPD_CUSTOM_INVCURVE :
	    case PPD_CUSTOM_POINTS :
	    case PPD_CUSTOM_REAL :
	    case PPD_CUSTOM_INT :
	        bufsize += 10;
	        break;

	    case PPD_CUSTOM_PASSCODE :
	    case PPD_CUSTOM_PASSWORD :
	    case PPD_CUSTOM_STRING :
	        if (cparam->current.custom_string)
		  bufsize += strlen(cparam->current.custom_string);
	        break;
          }
	}
      }
    }
    else if (section != PPD_ORDER_EXIT)
    {
      bufsize += 3;			/* [{\n */

      if ((!_cups_strcasecmp(choices[i]->option->keyword, "PageSize") ||
           !_cups_strcasecmp(choices[i]->option->keyword, "PageRegion")) &&
          !_cups_strcasecmp(choices[i]->choice, "Custom"))
      {
        DEBUG_puts("2ppdEmitString: Custom size set!");

        bufsize += 37;			/* %%BeginFeature: *CustomPageSize True\n */
        bufsize += 50;			/* Five 9-digit numbers + newline */
      }
      else if (!_cups_strcasecmp(choices[i]->choice, "Custom") &&
               (coption = ppdFindCustomOption(ppd,
	                                      choices[i]->option->keyword))
	           != NULL)
      {
        bufsize += 23 + strlen(choices[i]->option->keyword) + 6;
					/* %%BeginFeature: *Customkeyword True\n */


        for (cparam = (ppd_cparam_t *)cupsArrayFirst(coption->params);
	     cparam;
	     cparam = (ppd_cparam_t *)cupsArrayNext(coption->params))
	{
          switch (cparam->type)
	  {
	    case PPD_CUSTOM_CURVE :
	    case PPD_CUSTOM_INVCURVE :
	    case PPD_CUSTOM_POINTS :
	    case PPD_CUSTOM_REAL :
	    case PPD_CUSTOM_INT :
	        bufsize += 10;
	        break;

	    case PPD_CUSTOM_PASSCODE :
	    case PPD_CUSTOM_PASSWORD :
	    case PPD_CUSTOM_STRING :
		bufsize += 3;
	        if (cparam->current.custom_string)
		  bufsize += 4 * strlen(cparam->current.custom_string);
	        break;
          }
	}
      }
      else
        bufsize += 17 + strlen(choices[i]->option->keyword) + 1 +
	           strlen(choices[i]->choice) + 1;
					/* %%BeginFeature: *keyword choice\n */

      bufsize += 13;			/* %%EndFeature\n */
      bufsize += 22;			/* } stopped cleartomark\n */
    }

    if (choices[i]->code)
      bufsize += strlen(choices[i]->code) + 1;
    else
      bufsize += strlen(ppd_custom_code);
  }

 /*
  * Allocate memory...
  */

  DEBUG_printf(("2ppdEmitString: Allocating %d bytes for string...",
                (int)bufsize));

  if ((buffer = calloc(1, bufsize)) == NULL)
  {
    free(choices);
    return (NULL);
  }

  bufend = buffer + bufsize - 1;
  loc    = localeconv();

 /*
  * Copy the option code to the buffer...
  */

  for (i = 0, bufptr = buffer; i < count; i ++, bufptr += strlen(bufptr))
    if (section == PPD_ORDER_JCL)
    {
      if (!_cups_strcasecmp(choices[i]->choice, "Custom") &&
	  choices[i]->code &&
          (coption = ppdFindCustomOption(ppd, choices[i]->option->keyword))
	      != NULL)
      {
       /*
        * Handle substitutions in custom JCL options...
	*/

	char	*cptr;			/* Pointer into code */
	int	pnum;			/* Parameter number */


        for (cptr = choices[i]->code; *cptr && bufptr < bufend;)
	{
	  if (*cptr == '\\')
	  {
	    cptr ++;

	    if (isdigit(*cptr & 255))
	    {
	     /*
	      * Substitute parameter...
	      */

              pnum = *cptr++ - '0';
	      while (isdigit(*cptr & 255))
	        pnum = pnum * 10 + *cptr++ - '0';

              for (cparam = (ppd_cparam_t *)cupsArrayFirst(coption->params);
	           cparam;
		   cparam = (ppd_cparam_t *)cupsArrayNext(coption->params))
		if (cparam->order == pnum)
		  break;

              if (cparam)
	      {
	        switch (cparam->type)
		{
		  case PPD_CUSTOM_CURVE :
		  case PPD_CUSTOM_INVCURVE :
		  case PPD_CUSTOM_POINTS :
		  case PPD_CUSTOM_REAL :
		      bufptr = _cupsStrFormatd(bufptr, bufend,
					       cparam->current.custom_real,
					       loc);
		      break;

		  case PPD_CUSTOM_INT :
		      snprintf(bufptr, (size_t)(bufend - bufptr), "%d", cparam->current.custom_int);
		      bufptr += strlen(bufptr);
		      break;

		  case PPD_CUSTOM_PASSCODE :
		  case PPD_CUSTOM_PASSWORD :
		  case PPD_CUSTOM_STRING :
		      if (cparam->current.custom_string)
		      {
			strlcpy(bufptr, cparam->current.custom_string, (size_t)(bufend - bufptr));
			bufptr += strlen(bufptr);
		      }
		      break;
		}
	      }
	    }
	    else if (*cptr)
	      *bufptr++ = *cptr++;
	  }
	  else
	    *bufptr++ = *cptr++;
	}
      }
      else
      {
       /*
        * Otherwise just copy the option code directly...
	*/

        strlcpy(bufptr, choices[i]->code, (size_t)(bufend - bufptr + 1));
        bufptr += strlen(bufptr);
      }
    }
    else if (section != PPD_ORDER_EXIT)
    {
     /*
      * Add wrapper commands to prevent printer errors for unsupported
      * options...
      */

      strlcpy(bufptr, "[{\n", (size_t)(bufend - bufptr + 1));
      bufptr += 3;

     /*
      * Send DSC comments with option...
      */

      DEBUG_printf(("2ppdEmitString: Adding code for %s=%s...",
		    choices[i]->option->keyword, choices[i]->choice));

      if ((!_cups_strcasecmp(choices[i]->option->keyword, "PageSize") ||
           !_cups_strcasecmp(choices[i]->option->keyword, "PageRegion")) &&
          !_cups_strcasecmp(choices[i]->choice, "Custom"))
      {
       /*
        * Variable size; write out standard size options, using the
	* parameter positions defined in the PPD file...
	*/

        ppd_attr_t	*attr;		/* PPD attribute */
	int		pos,		/* Position of custom value */
			orientation;	/* Orientation to use */
	float		values[5];	/* Values for custom command */


        strlcpy(bufptr, "%%BeginFeature: *CustomPageSize True\n", (size_t)(bufend - bufptr + 1));
        bufptr += 37;

        size = ppdPageSize(ppd, "Custom");

        memset(values, 0, sizeof(values));

	if ((attr = ppdFindAttr(ppd, "ParamCustomPageSize", "Width")) != NULL)
	{
	  pos = atoi(attr->value) - 1;

          if (pos < 0 || pos > 4)
	    pos = 0;
	}
	else
	  pos = 0;

	values[pos] = size->width;

	if ((attr = ppdFindAttr(ppd, "ParamCustomPageSize", "Height")) != NULL)
	{
	  pos = atoi(attr->value) - 1;

          if (pos < 0 || pos > 4)
	    pos = 1;
	}
	else
	  pos = 1;

	values[pos] = size->length;

       /*
        * According to the Adobe PPD specification, an orientation of 1
	* will produce a print that comes out upside-down with the X
	* axis perpendicular to the direction of feed, which is exactly
	* what we want to be consistent with non-PS printers.
	*
	* We could also use an orientation of 3 to produce output that
	* comes out rightside-up (this is the default for many large format
	* printer PPDs), however for consistency we will stick with the
	* value 1.
	*
	* If we wanted to get fancy, we could use orientations of 0 or
	* 2 and swap the width and length, however we don't want to get
	* fancy, we just want it to work consistently.
	*
	* The orientation value is range limited by the Orientation
	* parameter definition, so certain non-PS printer drivers that
	* only support an Orientation of 0 will get the value 0 as
	* expected.
	*/

        orientation = 1;

	if ((attr = ppdFindAttr(ppd, "ParamCustomPageSize",
	                        "Orientation")) != NULL)
	{
	  int min_orient, max_orient;	/* Minimum and maximum orientations */


          if (sscanf(attr->value, "%d%*s%d%d", &pos, &min_orient,
	             &max_orient) != 3)
	    pos = 4;
	  else
	  {
	    pos --;

            if (pos < 0 || pos > 4)
	      pos = 4;

            if (orientation > max_orient)
	      orientation = max_orient;
	    else if (orientation < min_orient)
	      orientation = min_orient;
	  }
	}
	else
	  pos = 4;

	values[pos] = (float)orientation;

        for (pos = 0; pos < 5; pos ++)
	{
	  bufptr    = _cupsStrFormatd(bufptr, bufend, values[pos], loc);
	  *bufptr++ = '\n';
        }

	if (!choices[i]->code)
	{
	 /*
	  * This can happen with certain buggy PPD files that don't include
	  * a CustomPageSize command sequence...  We just use a generic
	  * Level 2 command sequence...
	  */

	  strlcpy(bufptr, ppd_custom_code, (size_t)(bufend - bufptr + 1));
          bufptr += strlen(bufptr);
	}
      }
      else if (!_cups_strcasecmp(choices[i]->choice, "Custom") &&
               (coption = ppdFindCustomOption(ppd, choices[i]->option->keyword))
	           != NULL)
      {
       /*
        * Custom option...
	*/

        const char	*s;		/* Pointer into string value */
        cups_array_t	*params;	/* Parameters in the correct output order */


        params = cupsArrayNew((cups_array_func_t)ppd_compare_cparams, NULL);

        for (cparam = (ppd_cparam_t *)cupsArrayFirst(coption->params);
	     cparam;
	     cparam = (ppd_cparam_t *)cupsArrayNext(coption->params))
          cupsArrayAdd(params, cparam);

        snprintf(bufptr, (size_t)(bufend - bufptr + 1), "%%%%BeginFeature: *Custom%s True\n", coption->keyword);
        bufptr += strlen(bufptr);

        for (cparam = (ppd_cparam_t *)cupsArrayFirst(params);
	     cparam;
	     cparam = (ppd_cparam_t *)cupsArrayNext(params))
	{
          switch (cparam->type)
	  {
	    case PPD_CUSTOM_CURVE :
	    case PPD_CUSTOM_INVCURVE :
	    case PPD_CUSTOM_POINTS :
	    case PPD_CUSTOM_REAL :
	        bufptr    = _cupsStrFormatd(bufptr, bufend,
		                            cparam->current.custom_real, loc);
                *bufptr++ = '\n';
	        break;

	    case PPD_CUSTOM_INT :
	        snprintf(bufptr, (size_t)(bufend - bufptr + 1), "%d\n", cparam->current.custom_int);
		bufptr += strlen(bufptr);
	        break;

	    case PPD_CUSTOM_PASSCODE :
	    case PPD_CUSTOM_PASSWORD :
	    case PPD_CUSTOM_STRING :
	        *bufptr++ = '(';

		if (cparam->current.custom_string)
		{
		  for (s = cparam->current.custom_string; *s; s ++)
		  {
		    if (*s < ' ' || *s == '(' || *s == ')' || *s >= 127)
		    {
		      snprintf(bufptr, (size_t)(bufend - bufptr + 1), "\\%03o", *s & 255);
		      bufptr += strlen(bufptr);
		    }
		    else
		      *bufptr++ = *s;
		  }
		}

	        *bufptr++ = ')';
		*bufptr++ = '\n';
	        break;
          }
	}

	cupsArrayDelete(params);
      }
      else
      {
        snprintf(bufptr, (size_t)(bufend - bufptr + 1), "%%%%BeginFeature: *%s %s\n", choices[i]->option->keyword, choices[i]->choice);
	bufptr += strlen(bufptr);
      }

      if (choices[i]->code && choices[i]->code[0])
      {
        j = (int)strlen(choices[i]->code);
	memcpy(bufptr, choices[i]->code, (size_t)j);
	bufptr += j;

	if (choices[i]->code[j - 1] != '\n')
	  *bufptr++ = '\n';
      }

      strlcpy(bufptr, "%%EndFeature\n"
		      "} stopped cleartomark\n", (size_t)(bufend - bufptr + 1));
      bufptr += strlen(bufptr);

      DEBUG_printf(("2ppdEmitString: Offset in string is %d...",
                    (int)(bufptr - buffer)));
    }
    else
    {
      strlcpy(bufptr, choices[i]->code, (size_t)(bufend - bufptr + 1));
      bufptr += strlen(bufptr);
    }

 /*
  * Nul-terminate, free, and return...
  */

  *bufptr = '\0';

  free(choices);

  return (buffer);
}
Ejemplo n.º 26
0
int					/* O - Exit status */
main(int  argc,				/* I - Number of command-line arguments (6 or 7) */
     char *argv[])			/* I - Command-line arguments */
{
  int		ipv4,			/* SNMP IPv4 socket */
		ipv6;			/* SNMP IPv6 socket */
#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
  struct sigaction action;		/* Actions for POSIX signals */
#endif /* HAVE_SIGACTION && !HAVE_SIGSET */


 /*
  * Check command-line options...
  */

  if (argc > 2)
  {
    _cupsLangPuts(stderr, _("Usage: snmp [host-or-ip-address]"));
    return (1);
  }

 /*
  * Set the password callback for IPP operations...
  */

  cupsSetPasswordCB(password_cb);

 /*
  * Catch SIGALRM signals...
  */

#ifdef HAVE_SIGSET
  sigset(SIGALRM, alarm_handler);
#elif defined(HAVE_SIGACTION)
  memset(&action, 0, sizeof(action));

  sigemptyset(&action.sa_mask);
  sigaddset(&action.sa_mask, SIGALRM);
  action.sa_handler = alarm_handler;
  sigaction(SIGALRM, &action, NULL);
#else
  signal(SIGALRM, alarm_handler);
#endif /* HAVE_SIGSET */

 /*
  * Open the SNMP socket...
  */

  if ((ipv4 = _cupsSNMPOpen(AF_INET)) < 0)
    return (1);

#ifdef AF_INET6
  if ((ipv6 = _cupsSNMPOpen(AF_INET6)) < 0)
    perror("DEBUG: Unable to create IPv6 socket");
#else
  ipv6 = -1;
#endif /* AF_INET6 */

 /*
  * Read the configuration file and any cache data...
  */

  read_snmp_conf(argv[1]);

  _cupsSNMPSetDebug(DebugLevel);

  Devices = cupsArrayNew((cups_array_func_t)compare_cache, NULL);

 /*
  * Scan for devices...
  */

  scan_devices(ipv4, ipv6);

 /*
  * Close, free, and return with no errors...
  */

  _cupsSNMPClose(ipv4);
  if (ipv6 >= 0)
    _cupsSNMPClose(ipv6);

  free_array(Addresses);
  free_array(Communities);
  free_cache();

  return (0);
}
Ejemplo n.º 27
0
cups_array_t *				/* O - Array of objects */
cgiGetIPPObjects(ipp_t *response,	/* I - IPP response */
                 void  *search)		/* I - Search filter */
{
  int			i;		/* Looping var */
  cups_array_t		*objs;		/* Array of objects */
  ipp_attribute_t	*attr,		/* Current attribute */
			*first;		/* First attribute for object */
  ipp_tag_t		group;		/* Current group tag */
  int			add;		/* Add this object to the array? */


  if (!response)
    return (0);

  for (add = 0, first = NULL, objs = cupsArrayNew(NULL, NULL),
           group = IPP_TAG_ZERO, attr = response->attrs;
       attr;
       attr = attr->next)
  {
    if (attr->group_tag != group)
    {
      group = attr->group_tag;

      if (group != IPP_TAG_ZERO && group != IPP_TAG_OPERATION)
      {
        first = attr;
	add   = 0;
      }
      else if (add && first)
      {
        cupsArrayAdd(objs, first);

	add   = 0;
	first = NULL;
      }
    }

    if (attr->name && attr->group_tag != IPP_TAG_OPERATION && !add)
    {
      if (!search)
      {
       /*
        * Add all objects if there is no search...
	*/

        add = 1;
      }
      else
      {
       /*
        * Check the search string against the string and integer values.
	*/

        switch (attr->value_tag)
	{
	  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_MIMETYPE :
	      for (i = 0; !add && i < attr->num_values; i ++)
		if (cgiDoSearch(search, attr->values[i].string.text))
		  add = 1;
	      break;

          case IPP_TAG_INTEGER :
	      for (i = 0; !add && i < attr->num_values; i ++)
	      {
	        char	buf[255];	/* Number buffer */


                sprintf(buf, "%d", attr->values[i].integer);

		if (cgiDoSearch(search, buf))
		  add = 1;
	      }
	      break;

          default :
	      break;
	}
      }
    }
  }

  if (add && first)
    cupsArrayAdd(objs, first);

  return (objs);
}
Ejemplo n.º 28
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);
}
Ejemplo n.º 29
0
pwg_media_t *				/* O - Matching size or NULL */
pwgMediaForPWG(const char *pwg)		/* I - PWG size name */
{
  char		*ptr;			/* Pointer into name */
  pwg_media_t	key,			/* Search key */
		*size;			/* Matching size */
  _cups_globals_t *cg = _cupsGlobals();	/* Global data */


 /*
  * Range check input...
  */

  if (!pwg)
    return (NULL);

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

  if (!cg->pwg_size_lut)
  {
    int	i;				/* Looping var */

    cg->pwg_size_lut = cupsArrayNew((cups_array_func_t)pwg_compare_pwg, NULL);

    for (i = (int)(sizeof(cups_pwg_media) / sizeof(cups_pwg_media[0])),
             size = (pwg_media_t *)cups_pwg_media;
	 i > 0;
	 i --, size ++)
      cupsArrayAdd(cg->pwg_size_lut, size);
  }

 /*
  * Lookup the name...
  */

  key.pwg = pwg;
  if ((size = (pwg_media_t *)cupsArrayFind(cg->pwg_size_lut, &key)) == NULL &&
      (ptr = (char *)strchr(pwg, '_')) != NULL &&
      (ptr = (char *)strchr(ptr + 1, '_')) != NULL)
  {
   /*
    * Try decoding the self-describing name of the form:
    *
    * class_name_WWWxHHHin
    * class_name_WWWxHHHmm
    */

    int		w, l;			/* Width and length of page */
    int		numer;			/* Scale factor for units */
    const char	*units = ptr + strlen(ptr) - 2;
					/* Units from size */

    ptr ++;

    if (units >= ptr && !strcmp(units, "in"))
      numer = 2540;
    else
      numer = 100;

    w = pwg_scan_measurement(ptr, &ptr, numer, 1);

    if (ptr && *ptr == 'x')
    {
      l = pwg_scan_measurement(ptr + 1, &ptr, numer, 1);

      if (ptr)
      {
        char	wstr[32], lstr[32];	/* Width and length strings */

        if (!strncmp(pwg, "disc_", 5))
          w = l;			/* Make the media size OUTERxOUTER */

        size         = &(cg->pwg_media);
        size->width  = w;
        size->length = l;

        strlcpy(cg->pwg_name, pwg, sizeof(cg->pwg_name));
	size->pwg = cg->pwg_name;

        if (numer == 100)
          snprintf(cg->ppd_name, sizeof(cg->ppd_name), "%sx%smm", pwg_format_millimeters(wstr, sizeof(wstr), w), pwg_format_millimeters(lstr, sizeof(lstr), l));
        else
          snprintf(cg->ppd_name, sizeof(cg->ppd_name), "%sx%s", pwg_format_inches(wstr, sizeof(wstr), w), pwg_format_inches(lstr, sizeof(lstr), l));
        size->ppd = cg->ppd_name;
      }
    }
  }

  return (size);
}
Ejemplo n.º 30
0
int					/* O - Exit status */
main(int  argc,				/* I - Number of command-line arguments */
     char *argv[])			/* I - Command-line arguments */
{
  int		i;			/* Looping var */
  ipp_t		*event;			/* Event from scheduler */
  ipp_state_t	state;			/* IPP event state */
  char		scheme[32],		/* URI scheme ("rss") */
		username[256],		/* Username for remote RSS */
		host[1024],		/* Hostname for remote RSS */
		resource[1024],		/* RSS file */
		*options;		/* Options */
  int		port,			/* Port number for remote RSS */
		max_events;		/* Maximum number of events */
  http_t	*http;			/* Connection to remote server */
  http_status_t	status;			/* HTTP GET/PUT status code */
  char		filename[1024],		/* Local filename */
		newname[1024];		/* filename.N */
  cups_lang_t	*language;		/* Language information */
  ipp_attribute_t *printer_up_time,	/* Timestamp on event */
		*notify_sequence_number,/* Sequence number */
		*notify_printer_uri;	/* Printer URI */
  char		*subject,		/* Subject for notification message */
		*text,			/* Text for notification message */
		link_url[1024],		/* Link to printer */
		link_scheme[32],	/* Scheme for link */
		link_username[256],	/* Username for link */
		link_host[1024],	/* Host for link */
		link_resource[1024];	/* Resource for link */
  int		link_port;		/* Link port */
  cups_array_t	*rss;			/* RSS message array */
  _cups_rss_t	*msg;			/* RSS message */
  char		baseurl[1024];		/* Base URL */
  fd_set	input;			/* Input set for select() */
  struct timeval timeout;		/* Timeout for select() */
  int		changed;		/* Has the RSS data changed? */
  int		exit_status;		/* Exit status */


  fprintf(stderr, "DEBUG: argc=%d\n", argc);
  for (i = 0; i < argc; i ++)
    fprintf(stderr, "DEBUG: argv[%d]=\"%s\"\n", i, argv[i]);

 /*
  * See whether we are publishing this RSS feed locally or remotely...
  */

  if (httpSeparateURI(HTTP_URI_CODING_ALL, argv[1], scheme, sizeof(scheme),
                      username, sizeof(username), host, sizeof(host), &port,
		      resource, sizeof(resource)) < HTTP_URI_OK)
  {
    fprintf(stderr, "ERROR: Bad RSS URI \"%s\"!\n", argv[1]);
    return (1);
  }

  max_events = 20;

  if ((options = strchr(resource, '?')) != NULL)
  {
    *options++ = '\0';

    if (!strncmp(options, "max_events=", 11))
    {
      max_events = atoi(options + 11);

      if (max_events <= 0)
        max_events = 20;
    }
  }

  rss = cupsArrayNew((cups_array_func_t)compare_rss, NULL);

  if (host[0])
  {
   /*
    * Remote feed, see if we can get the current file...
    */

    int	fd;				/* Temporary file */


    if ((rss_password = strchr(username, ':')) != NULL)
      *rss_password++ = '\0';

    cupsSetPasswordCB(password_cb);
    cupsSetUser(username);

    if ((fd = cupsTempFd(filename, sizeof(filename))) < 0)
    {
      fprintf(stderr, "ERROR: Unable to create temporary file: %s\n",
              strerror(errno));

      return (1);
    }

    if ((http = httpConnect(host, port)) == NULL)
    {
      fprintf(stderr, "ERROR: Unable to connect to %s on port %d: %s\n",
              host, port, strerror(errno));

      close(fd);
      unlink(filename);

      return (1);
    }

    status = cupsGetFd(http, resource, fd);

    close(fd);

    if (status != HTTP_OK && status != HTTP_NOT_FOUND)
    {
      fprintf(stderr, "ERROR: Unable to GET %s from %s on port %d: %d %s\n",
	      resource, host, port, status, httpStatus(status));

      httpClose(http);
      unlink(filename);

      return (1);
    }

    strlcpy(newname, filename, sizeof(newname));

    httpAssembleURI(HTTP_URI_CODING_ALL, baseurl, sizeof(baseurl), "http",
                    NULL, host, port, resource);
  }
  else
  {
    const char	*cachedir,		/* CUPS_CACHEDIR */
		*server_name,		/* SERVER_NAME */
		*server_port;		/* SERVER_PORT */


    http = NULL;

    if ((cachedir = getenv("CUPS_CACHEDIR")) == NULL)
      cachedir = CUPS_CACHEDIR;

    if ((server_name = getenv("SERVER_NAME")) == NULL)
      server_name = "localhost";

    if ((server_port = getenv("SERVER_PORT")) == NULL)
      server_port = "631";

    snprintf(filename, sizeof(filename), "%s/rss%s", cachedir, resource);
    snprintf(newname, sizeof(newname), "%s.N", filename);

    httpAssembleURIf(HTTP_URI_CODING_ALL, baseurl, sizeof(baseurl), "http",
                     NULL, server_name, atoi(server_port), "/rss%s", resource);
  }

 /*
  * Load the previous RSS file, if any...
  */

  load_rss(rss, filename);

  changed = cupsArrayCount(rss) == 0;

 /*
  * Localize for the user's chosen language...
  */

  language = cupsLangDefault();

 /*
  * Read events and update the RSS file until we are out of events.
  */

  for (exit_status = 0, event = NULL;;)
  {
    if (changed)
    {
     /*
      * Save the messages to the file again, uploading as needed...
      */

      if (save_rss(rss, newname, baseurl))
      {
	if (http)
	{
	 /*
          * Upload the RSS file...
	  */

          if ((status = cupsPutFile(http, resource, filename)) != HTTP_CREATED)
            fprintf(stderr, "ERROR: Unable to PUT %s from %s on port %d: %d %s\n",
	            resource, host, port, status, httpStatus(status));
	}
	else
	{
	 /*
          * Move the new RSS file over top the old one...
	  */

          if (rename(newname, filename))
            fprintf(stderr, "ERROR: Unable to rename %s to %s: %s\n",
	            newname, filename, strerror(errno));
	}

	changed = 0;
      }
    }

   /*
    * Wait up to 30 seconds for an event...
    */

    timeout.tv_sec  = 30;
    timeout.tv_usec = 0;

    FD_ZERO(&input);
    FD_SET(0, &input);

    if (select(1, &input, NULL, NULL, &timeout) < 0)
      continue;
    else if (!FD_ISSET(0, &input))
    {
      fprintf(stderr, "DEBUG: %s is bored, exiting...\n", argv[1]);
      break;
    }

   /*
    * Read the next event...
    */

    event = ippNew();
    while ((state = ippReadFile(0, event)) != IPP_DATA)
    {
      if (state <= IPP_IDLE)
        break;
    }

    if (state == IPP_ERROR)
      fputs("DEBUG: ippReadFile() returned IPP_ERROR!\n", stderr);

    if (state <= IPP_IDLE)
      break;

   /*
    * Collect the info from the event...
    */

    printer_up_time        = ippFindAttribute(event, "printer-up-time",
                                              IPP_TAG_INTEGER);
    notify_sequence_number = ippFindAttribute(event, "notify-sequence-number",
                                	      IPP_TAG_INTEGER);
    notify_printer_uri     = ippFindAttribute(event, "notify-printer-uri",
                                	      IPP_TAG_URI);
    subject                = cupsNotifySubject(language, event);
    text                   = cupsNotifyText(language, event);

    if (printer_up_time && notify_sequence_number && subject && text)
    {
     /*
      * Create a new RSS message...
      */

      if (notify_printer_uri)
      {
        httpSeparateURI(HTTP_URI_CODING_ALL,
	                notify_printer_uri->values[0].string.text,
			link_scheme, sizeof(link_scheme),
                        link_username, sizeof(link_username),
			link_host, sizeof(link_host), &link_port,
		        link_resource, sizeof(link_resource));
        httpAssembleURI(HTTP_URI_CODING_ALL, link_url, sizeof(link_url),
	                "http", link_username, link_host, link_port,
			link_resource);
      }

      msg = new_message(notify_sequence_number->values[0].integer,
                        xml_escape(subject), xml_escape(text),
			notify_printer_uri ? xml_escape(link_url) : NULL,
			printer_up_time->values[0].integer);

      if (!msg)
      {
        fprintf(stderr, "ERROR: Unable to create message: %s\n",
	        strerror(errno));
        exit_status = 1;
	break;
      }

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

      cupsArrayAdd(rss, msg);

      changed = 1;

     /*
      * Trim the array as needed...
      */

      while (cupsArrayCount(rss) > max_events)
      {
        msg = cupsArrayFirst(rss);

	cupsArrayRemove(rss, msg);

	delete_message(msg);
      }
    }

    if (subject)
      free(subject);

    if (text)
      free(text);

    ippDelete(event);
    event = NULL;
  }

 /*
  * We only get here when idle or error...
  */

  ippDelete(event);

  if (http)
  {
    unlink(filename);
    httpClose(http);
  }

  return (exit_status);
}