Blame systemv/lpadmin.c

Packit 2fc92b
/*
Packit 2fc92b
 * "lpadmin" command for CUPS.
Packit 2fc92b
 *
Packit 2fc92b
 * Copyright 2007-2016 by Apple Inc.
Packit 2fc92b
 * Copyright 1997-2006 by Easy Software Products.
Packit 2fc92b
 *
Packit 2fc92b
 * These coded instructions, statements, and computer programs are the
Packit 2fc92b
 * property of Apple Inc. and are protected by Federal copyright
Packit 2fc92b
 * law.  Distribution and use rights are outlined in the file "LICENSE.txt"
Packit 2fc92b
 * which should have been included with this file.  If this file is
Packit 2fc92b
 * missing or damaged, see the license at "http://www.cups.org/".
Packit 2fc92b
 */
Packit 2fc92b
Packit 2fc92b
/*
Packit 2fc92b
 * Include necessary headers...
Packit 2fc92b
 */
Packit 2fc92b
Packit 2fc92b
#define _CUPS_NO_DEPRECATED
Packit 2fc92b
#define _PPD_DEPRECATED
Packit 2fc92b
#include <cups/cups-private.h>
Packit 2fc92b
#include <cups/ppd-private.h>
Packit 2fc92b
Packit 2fc92b
Packit 2fc92b
/*
Packit 2fc92b
 * Local functions...
Packit 2fc92b
 */
Packit 2fc92b
Packit 2fc92b
static int		add_printer_to_class(http_t *http, char *printer, char *pclass);
Packit 2fc92b
static int		default_printer(http_t *http, char *printer);
Packit 2fc92b
static int		delete_printer(http_t *http, char *printer);
Packit 2fc92b
static int		delete_printer_from_class(http_t *http, char *printer,
Packit 2fc92b
			                          char *pclass);
Packit 2fc92b
static int		delete_printer_option(http_t *http, char *printer,
Packit 2fc92b
			                      char *option);
Packit 2fc92b
static int		enable_printer(http_t *http, char *printer);
Packit 2fc92b
static char		*get_printer_ppd(const char *uri, char *buffer, size_t bufsize);
Packit 2fc92b
static cups_ptype_t	get_printer_type(http_t *http, char *printer, char *uri,
Packit 2fc92b
			                 size_t urisize);
Packit 2fc92b
static int		set_printer_options(http_t *http, char *printer,
Packit 2fc92b
			                    int num_options, cups_option_t *options,
Packit 2fc92b
					    char *file);
Packit 2fc92b
static int		validate_name(const char *name);
Packit 2fc92b
Packit 2fc92b
Packit 2fc92b
/*
Packit 2fc92b
 * 'main()' - Parse options and configure the scheduler.
Packit 2fc92b
 */
Packit 2fc92b
Packit 2fc92b
int
Packit 2fc92b
main(int  argc,			/* I - Number of command-line arguments */
Packit 2fc92b
     char *argv[])		/* I - Command-line arguments */
Packit 2fc92b
{
Packit 2fc92b
  int		i;		/* Looping var */
Packit 2fc92b
  http_t	*http;		/* Connection to server */
Packit 2fc92b
  char		*printer,	/* Destination printer */
Packit 2fc92b
		*pclass,	/* Printer class name */
Packit 2fc92b
		*opt,		/* Option pointer */
Packit 2fc92b
		*val;		/* Pointer to allow/deny value */
Packit 2fc92b
  int		num_options;	/* Number of options */
Packit 2fc92b
  cups_option_t	*options;	/* Options */
Packit 2fc92b
  char		*file,		/* New PPD file */
Packit 2fc92b
		evefile[1024] = "";
Packit 2fc92b
				/* IPP Everywhere PPD */
Packit 2fc92b
  const char	*ppd_name,	/* ppd-name value */
Packit 2fc92b
		*device_uri;	/* device-uri value */
Packit 2fc92b
Packit 2fc92b
Packit 2fc92b
  _cupsSetLocale(argv);
Packit 2fc92b
Packit 2fc92b
  http        = NULL;
Packit 2fc92b
  printer     = NULL;
Packit 2fc92b
  num_options = 0;
Packit 2fc92b
  options     = NULL;
Packit 2fc92b
  file        = NULL;
Packit 2fc92b
Packit 2fc92b
  for (i = 1; i < argc; i ++)
Packit 2fc92b
  {
Packit 2fc92b
    if (argv[i][0] == '-')
Packit 2fc92b
    {
Packit 2fc92b
      for (opt = argv[i] + 1; *opt; opt ++)
Packit 2fc92b
      {
Packit 2fc92b
	switch (*opt)
Packit 2fc92b
	{
Packit 2fc92b
	  case 'c' : /* Add printer to class */
Packit 2fc92b
	      if (!http)
Packit 2fc92b
	      {
Packit 2fc92b
		http = httpConnect2(cupsServer(), ippPort(), NULL, AF_UNSPEC, cupsEncryption(), 1, 30000, NULL);
Packit 2fc92b
Packit 2fc92b
		if (http == NULL)
Packit 2fc92b
		{
Packit 2fc92b
		  _cupsLangPrintf(stderr, _("lpadmin: Unable to connect to server: %s"), strerror(errno));
Packit 2fc92b
		  return (1);
Packit 2fc92b
		}
Packit 2fc92b
	      }
Packit 2fc92b
Packit 2fc92b
	      if (printer == NULL)
Packit 2fc92b
	      {
Packit 2fc92b
		_cupsLangPuts(stderr,
Packit 2fc92b
			      _("lpadmin: Unable to add a printer to the class:\n"
Packit 2fc92b
				"         You must specify a printer name first."));
Packit 2fc92b
		return (1);
Packit 2fc92b
	      }
Packit 2fc92b
Packit 2fc92b
	      if (opt[1] != '\0')
Packit 2fc92b
	      {
Packit 2fc92b
		pclass = opt + 1;
Packit 2fc92b
		opt += strlen(opt) - 1;
Packit 2fc92b
	      }
Packit 2fc92b
	      else
Packit 2fc92b
	      {
Packit 2fc92b
		i ++;
Packit 2fc92b
Packit 2fc92b
		if (i >= argc)
Packit 2fc92b
		{
Packit 2fc92b
		  _cupsLangPuts(stderr, _("lpadmin: Expected class name after \"-c\" option."));
Packit 2fc92b
		  return (1);
Packit 2fc92b
		}
Packit 2fc92b
Packit 2fc92b
		pclass = argv[i];
Packit 2fc92b
	      }
Packit 2fc92b
Packit 2fc92b
	      if (!validate_name(pclass))
Packit 2fc92b
	      {
Packit 2fc92b
		_cupsLangPuts(stderr,
Packit 2fc92b
			      _("lpadmin: Class name can only contain printable "
Packit 2fc92b
				"characters."));
Packit 2fc92b
		return (1);
Packit 2fc92b
	      }
Packit 2fc92b
Packit 2fc92b
	      if (add_printer_to_class(http, printer, pclass))
Packit 2fc92b
		return (1);
Packit 2fc92b
	      break;
Packit 2fc92b
Packit 2fc92b
	  case 'd' : /* Set as default destination */
Packit 2fc92b
	      if (!http)
Packit 2fc92b
	      {
Packit 2fc92b
		http = httpConnect2(cupsServer(), ippPort(), NULL, AF_UNSPEC, cupsEncryption(), 1, 30000, NULL);
Packit 2fc92b
Packit 2fc92b
		if (http == NULL)
Packit 2fc92b
		{
Packit 2fc92b
		  _cupsLangPrintf(stderr, _("lpadmin: Unable to connect to server: %s"), strerror(errno));
Packit 2fc92b
		  return (1);
Packit 2fc92b
		}
Packit 2fc92b
	      }
Packit 2fc92b
Packit 2fc92b
	      if (opt[1] != '\0')
Packit 2fc92b
	      {
Packit 2fc92b
		printer = opt + 1;
Packit 2fc92b
		opt += strlen(opt) - 1;
Packit 2fc92b
	      }
Packit 2fc92b
	      else
Packit 2fc92b
	      {
Packit 2fc92b
		i ++;
Packit 2fc92b
Packit 2fc92b
		if (i >= argc)
Packit 2fc92b
		{
Packit 2fc92b
		  _cupsLangPuts(stderr, _("lpadmin: Expected printer name after \"-d\" option."));
Packit 2fc92b
		  return (1);
Packit 2fc92b
		}
Packit 2fc92b
Packit 2fc92b
		printer = argv[i];
Packit 2fc92b
	      }
Packit 2fc92b
Packit 2fc92b
	      if (!validate_name(printer))
Packit 2fc92b
	      {
Packit 2fc92b
		_cupsLangPuts(stderr, _("lpadmin: Printer name can only contain printable characters."));
Packit 2fc92b
		return (1);
Packit 2fc92b
	      }
Packit 2fc92b
Packit 2fc92b
	      if (default_printer(http, printer))
Packit 2fc92b
		return (1);
Packit 2fc92b
Packit 2fc92b
	      i = argc;
Packit 2fc92b
	      break;
Packit 2fc92b
Packit 2fc92b
	  case 'h' : /* Connect to host */
Packit 2fc92b
	      if (http)
Packit 2fc92b
	      {
Packit 2fc92b
		httpClose(http);
Packit 2fc92b
		http = NULL;
Packit 2fc92b
	      }
Packit 2fc92b
Packit 2fc92b
	      if (opt[1] != '\0')
Packit 2fc92b
	      {
Packit 2fc92b
		cupsSetServer(opt + 1);
Packit 2fc92b
		opt += strlen(opt) - 1;
Packit 2fc92b
	      }
Packit 2fc92b
	      else
Packit 2fc92b
	      {
Packit 2fc92b
		i ++;
Packit 2fc92b
Packit 2fc92b
		if (i >= argc)
Packit 2fc92b
		{
Packit 2fc92b
		  _cupsLangPuts(stderr, _("lpadmin: Expected hostname after \"-h\" option."));
Packit 2fc92b
		  return (1);
Packit 2fc92b
		}
Packit 2fc92b
Packit 2fc92b
		cupsSetServer(argv[i]);
Packit 2fc92b
	      }
Packit 2fc92b
	      break;
Packit 2fc92b
Packit 2fc92b
	  case 'P' : /* Use the specified PPD file */
Packit 2fc92b
	  case 'i' : /* Use the specified PPD file */
Packit 2fc92b
	      if (opt[1] != '\0')
Packit 2fc92b
	      {
Packit 2fc92b
		file = opt + 1;
Packit 2fc92b
		opt += strlen(opt) - 1;
Packit 2fc92b
	      }
Packit 2fc92b
	      else
Packit 2fc92b
	      {
Packit 2fc92b
		i ++;
Packit 2fc92b
Packit 2fc92b
		if (i >= argc)
Packit 2fc92b
		{
Packit 2fc92b
		  _cupsLangPrintf(stderr, _("lpadmin: Expected PPD after \"-%c\" option."), argv[i - 1][1]);
Packit 2fc92b
		  return (1);
Packit 2fc92b
		}
Packit 2fc92b
Packit 2fc92b
		file = argv[i];
Packit 2fc92b
	      }
Packit 2fc92b
	      break;
Packit 2fc92b
Packit 2fc92b
	  case 'E' : /* Enable the printer/enable encryption */
Packit 2fc92b
	      if (printer == NULL)
Packit 2fc92b
	      {
Packit 2fc92b
#ifdef HAVE_SSL
Packit 2fc92b
		cupsSetEncryption(HTTP_ENCRYPTION_REQUIRED);
Packit 2fc92b
Packit 2fc92b
		if (http)
Packit 2fc92b
		  httpEncryption(http, HTTP_ENCRYPTION_REQUIRED);
Packit 2fc92b
#else
Packit 2fc92b
		_cupsLangPrintf(stderr, _("%s: Sorry, no encryption support."), argv[0]);
Packit 2fc92b
#endif /* HAVE_SSL */
Packit 2fc92b
		break;
Packit 2fc92b
	      }
Packit 2fc92b
Packit 2fc92b
	      if (!http)
Packit 2fc92b
	      {
Packit 2fc92b
		http = httpConnect2(cupsServer(), ippPort(), NULL, AF_UNSPEC, cupsEncryption(), 1, 30000, NULL);
Packit 2fc92b
Packit 2fc92b
		if (http == NULL)
Packit 2fc92b
		{
Packit 2fc92b
		  _cupsLangPrintf(stderr,
Packit 2fc92b
				  _("lpadmin: Unable to connect to server: %s"),
Packit 2fc92b
				  strerror(errno));
Packit 2fc92b
		  return (1);
Packit 2fc92b
		}
Packit 2fc92b
	      }
Packit 2fc92b
Packit 2fc92b
	      if (enable_printer(http, printer))
Packit 2fc92b
		return (1);
Packit 2fc92b
	      break;
Packit 2fc92b
Packit 2fc92b
	  case 'm' : /* Use the specified standard script/PPD file */
Packit 2fc92b
	      if (opt[1] != '\0')
Packit 2fc92b
	      {
Packit 2fc92b
		num_options = cupsAddOption("ppd-name", opt + 1, num_options, &options);
Packit 2fc92b
		opt += strlen(opt) - 1;
Packit 2fc92b
	      }
Packit 2fc92b
	      else
Packit 2fc92b
	      {
Packit 2fc92b
		i ++;
Packit 2fc92b
Packit 2fc92b
		if (i >= argc)
Packit 2fc92b
		{
Packit 2fc92b
		  _cupsLangPuts(stderr, _("lpadmin: Expected model after \"-m\" option."));
Packit 2fc92b
		  return (1);
Packit 2fc92b
		}
Packit 2fc92b
Packit 2fc92b
		num_options = cupsAddOption("ppd-name", argv[i], num_options, &options);
Packit 2fc92b
	      }
Packit 2fc92b
	      break;
Packit 2fc92b
Packit 2fc92b
	  case 'o' : /* Set option */
Packit 2fc92b
	      if (opt[1] != '\0')
Packit 2fc92b
	      {
Packit 2fc92b
		num_options = cupsParseOptions(opt + 1, num_options, &options);
Packit 2fc92b
		opt += strlen(opt) - 1;
Packit 2fc92b
	      }
Packit 2fc92b
	      else
Packit 2fc92b
	      {
Packit 2fc92b
		i ++;
Packit 2fc92b
Packit 2fc92b
		if (i >= argc)
Packit 2fc92b
		{
Packit 2fc92b
		  _cupsLangPuts(stderr, _("lpadmin: Expected name=value after \"-o\" option."));
Packit 2fc92b
		  return (1);
Packit 2fc92b
		}
Packit 2fc92b
Packit 2fc92b
		num_options = cupsParseOptions(argv[i], num_options, &options);
Packit 2fc92b
	      }
Packit 2fc92b
	      break;
Packit 2fc92b
Packit 2fc92b
	  case 'p' : /* Add/modify a printer */
Packit 2fc92b
	      if (opt[1] != '\0')
Packit 2fc92b
	      {
Packit 2fc92b
		printer = opt + 1;
Packit 2fc92b
		opt += strlen(opt) - 1;
Packit 2fc92b
	      }
Packit 2fc92b
	      else
Packit 2fc92b
	      {
Packit 2fc92b
		i ++;
Packit 2fc92b
Packit 2fc92b
		if (i >= argc)
Packit 2fc92b
		{
Packit 2fc92b
		  _cupsLangPuts(stderr, _("lpadmin: Expected printer after \"-p\" option."));
Packit 2fc92b
		  return (1);
Packit 2fc92b
		}
Packit 2fc92b
Packit 2fc92b
		printer = argv[i];
Packit 2fc92b
	      }
Packit 2fc92b
Packit 2fc92b
	      if (!validate_name(printer))
Packit 2fc92b
	      {
Packit 2fc92b
		_cupsLangPuts(stderr, _("lpadmin: Printer name can only contain printable characters."));
Packit 2fc92b
		return (1);
Packit 2fc92b
	      }
Packit 2fc92b
	      break;
Packit 2fc92b
Packit 2fc92b
	  case 'r' : /* Remove printer from class */
Packit 2fc92b
	      if (!http)
Packit 2fc92b
	      {
Packit 2fc92b
		http = httpConnect2(cupsServer(), ippPort(), NULL, AF_UNSPEC, cupsEncryption(), 1, 30000, NULL);
Packit 2fc92b
Packit 2fc92b
		if (http == NULL)
Packit 2fc92b
		{
Packit 2fc92b
		  _cupsLangPrintf(stderr,
Packit 2fc92b
				  _("lpadmin: Unable to connect to server: %s"),
Packit 2fc92b
				  strerror(errno));
Packit 2fc92b
		  return (1);
Packit 2fc92b
		}
Packit 2fc92b
	      }
Packit 2fc92b
Packit 2fc92b
	      if (printer == NULL)
Packit 2fc92b
	      {
Packit 2fc92b
		_cupsLangPuts(stderr,
Packit 2fc92b
			      _("lpadmin: Unable to remove a printer from the class:\n"
Packit 2fc92b
				"         You must specify a printer name first."));
Packit 2fc92b
		return (1);
Packit 2fc92b
	      }
Packit 2fc92b
Packit 2fc92b
	      if (opt[1] != '\0')
Packit 2fc92b
	      {
Packit 2fc92b
		pclass = opt + 1;
Packit 2fc92b
		opt += strlen(opt) - 1;
Packit 2fc92b
	      }
Packit 2fc92b
	      else
Packit 2fc92b
	      {
Packit 2fc92b
		i ++;
Packit 2fc92b
Packit 2fc92b
		if (i >= argc)
Packit 2fc92b
		{
Packit 2fc92b
		  _cupsLangPuts(stderr, _("lpadmin: Expected class after \"-r\" option."));
Packit 2fc92b
		  return (1);
Packit 2fc92b
		}
Packit 2fc92b
Packit 2fc92b
		pclass = argv[i];
Packit 2fc92b
	      }
Packit 2fc92b
Packit 2fc92b
	      if (!validate_name(pclass))
Packit 2fc92b
	      {
Packit 2fc92b
		_cupsLangPuts(stderr, _("lpadmin: Class name can only contain printable characters."));
Packit 2fc92b
		return (1);
Packit 2fc92b
	      }
Packit 2fc92b
Packit 2fc92b
	      if (delete_printer_from_class(http, printer, pclass))
Packit 2fc92b
		return (1);
Packit 2fc92b
	      break;
Packit 2fc92b
Packit 2fc92b
	  case 'R' : /* Remove option */
Packit 2fc92b
	      if (!http)
Packit 2fc92b
	      {
Packit 2fc92b
		http = httpConnect2(cupsServer(), ippPort(), NULL, AF_UNSPEC, cupsEncryption(), 1, 30000, NULL);
Packit 2fc92b
Packit 2fc92b
		if (http == NULL)
Packit 2fc92b
		{
Packit 2fc92b
		  _cupsLangPrintf(stderr, _("lpadmin: Unable to connect to server: %s"), strerror(errno));
Packit 2fc92b
		  return (1);
Packit 2fc92b
		}
Packit 2fc92b
	      }
Packit 2fc92b
Packit 2fc92b
	      if (printer == NULL)
Packit 2fc92b
	      {
Packit 2fc92b
		_cupsLangPuts(stderr,
Packit 2fc92b
			      _("lpadmin: Unable to delete option:\n"
Packit 2fc92b
				"         You must specify a printer name first."));
Packit 2fc92b
		return (1);
Packit 2fc92b
	      }
Packit 2fc92b
Packit 2fc92b
	      if (opt[1] != '\0')
Packit 2fc92b
	      {
Packit 2fc92b
		val = opt + 1;
Packit 2fc92b
		opt += strlen(opt) - 1;
Packit 2fc92b
	      }
Packit 2fc92b
	      else
Packit 2fc92b
	      {
Packit 2fc92b
		i ++;
Packit 2fc92b
Packit 2fc92b
		if (i >= argc)
Packit 2fc92b
		{
Packit 2fc92b
		  _cupsLangPuts(stderr, _("lpadmin: Expected name after \"-R\" option."));
Packit 2fc92b
		  return (1);
Packit 2fc92b
		}
Packit 2fc92b
Packit 2fc92b
		val = argv[i];
Packit 2fc92b
	      }
Packit 2fc92b
Packit 2fc92b
	      if (delete_printer_option(http, printer, val))
Packit 2fc92b
		return (1);
Packit 2fc92b
	      break;
Packit 2fc92b
Packit 2fc92b
	  case 'U' : /* Username */
Packit 2fc92b
	      if (opt[1] != '\0')
Packit 2fc92b
	      {
Packit 2fc92b
		cupsSetUser(opt + 1);
Packit 2fc92b
		opt += strlen(opt) - 1;
Packit 2fc92b
	      }
Packit 2fc92b
	      else
Packit 2fc92b
	      {
Packit 2fc92b
		i ++;
Packit 2fc92b
		if (i >= argc)
Packit 2fc92b
		{
Packit 2fc92b
		  _cupsLangPrintf(stderr, _("%s: Error - expected username after \"-U\" option."), argv[0]);
Packit 2fc92b
		  return (1);
Packit 2fc92b
		}
Packit 2fc92b
Packit 2fc92b
		cupsSetUser(argv[i]);
Packit 2fc92b
	      }
Packit 2fc92b
	      break;
Packit 2fc92b
Packit 2fc92b
	  case 'u' : /* Allow/deny users */
Packit 2fc92b
	      if (opt[1] != '\0')
Packit 2fc92b
	      {
Packit 2fc92b
		val = opt + 1;
Packit 2fc92b
		opt += strlen(opt) - 1;
Packit 2fc92b
	      }
Packit 2fc92b
	      else
Packit 2fc92b
	      {
Packit 2fc92b
		i ++;
Packit 2fc92b
Packit 2fc92b
		if (i >= argc)
Packit 2fc92b
		{
Packit 2fc92b
		  _cupsLangPuts(stderr, _("lpadmin: Expected allow/deny:userlist after \"-u\" option."));
Packit 2fc92b
		  return (1);
Packit 2fc92b
		}
Packit 2fc92b
Packit 2fc92b
		val = argv[i];
Packit 2fc92b
	      }
Packit 2fc92b
Packit 2fc92b
	      if (!_cups_strncasecmp(val, "allow:", 6))
Packit 2fc92b
		num_options = cupsAddOption("requesting-user-name-allowed", val + 6, num_options, &options);
Packit 2fc92b
	      else if (!_cups_strncasecmp(val, "deny:", 5))
Packit 2fc92b
		num_options = cupsAddOption("requesting-user-name-denied", val + 5, num_options, &options);
Packit 2fc92b
	      else
Packit 2fc92b
	      {
Packit 2fc92b
		_cupsLangPrintf(stderr, _("lpadmin: Unknown allow/deny option \"%s\"."), val);
Packit 2fc92b
		return (1);
Packit 2fc92b
	      }
Packit 2fc92b
	      break;
Packit 2fc92b
Packit 2fc92b
	  case 'v' : /* Set the device-uri attribute */
Packit 2fc92b
	      if (opt[1] != '\0')
Packit 2fc92b
	      {
Packit 2fc92b
		num_options = cupsAddOption("device-uri", opt + 1, num_options, &options);
Packit 2fc92b
		opt += strlen(opt) - 1;
Packit 2fc92b
	      }
Packit 2fc92b
	      else
Packit 2fc92b
	      {
Packit 2fc92b
		i ++;
Packit 2fc92b
Packit 2fc92b
		if (i >= argc)
Packit 2fc92b
		{
Packit 2fc92b
		  _cupsLangPuts(stderr, _("lpadmin: Expected device URI after \"-v\" option."));
Packit 2fc92b
		  return (1);
Packit 2fc92b
		}
Packit 2fc92b
Packit 2fc92b
		num_options = cupsAddOption("device-uri", argv[i], num_options, &options);
Packit 2fc92b
	      }
Packit 2fc92b
	      break;
Packit 2fc92b
Packit 2fc92b
	  case 'x' : /* Delete a printer */
Packit 2fc92b
	      if (!http)
Packit 2fc92b
	      {
Packit 2fc92b
		http = httpConnect2(cupsServer(), ippPort(), NULL, AF_UNSPEC, cupsEncryption(), 1, 30000, NULL);
Packit 2fc92b
Packit 2fc92b
		if (http == NULL)
Packit 2fc92b
		{
Packit 2fc92b
		  _cupsLangPrintf(stderr,
Packit 2fc92b
				  _("lpadmin: Unable to connect to server: %s"),
Packit 2fc92b
				  strerror(errno));
Packit 2fc92b
		  return (1);
Packit 2fc92b
		}
Packit 2fc92b
	      }
Packit 2fc92b
Packit 2fc92b
	      if (opt[1] != '\0')
Packit 2fc92b
	      {
Packit 2fc92b
		printer = opt + 1;
Packit 2fc92b
		opt += strlen(opt) - 1;
Packit 2fc92b
	      }
Packit 2fc92b
	      else
Packit 2fc92b
	      {
Packit 2fc92b
		i ++;
Packit 2fc92b
Packit 2fc92b
		if (i >= argc)
Packit 2fc92b
		{
Packit 2fc92b
		  _cupsLangPuts(stderr, _("lpadmin: Expected printer or class after \"-x\" option."));
Packit 2fc92b
		  return (1);
Packit 2fc92b
		}
Packit 2fc92b
Packit 2fc92b
		printer = argv[i];
Packit 2fc92b
	      }
Packit 2fc92b
Packit 2fc92b
	      if (!validate_name(printer))
Packit 2fc92b
	      {
Packit 2fc92b
		_cupsLangPuts(stderr, _("lpadmin: Printer name can only contain printable characters."));
Packit 2fc92b
		return (1);
Packit 2fc92b
	      }
Packit 2fc92b
Packit 2fc92b
	      if (delete_printer(http, printer))
Packit 2fc92b
		return (1);
Packit 2fc92b
Packit 2fc92b
	      i = argc;
Packit 2fc92b
	      break;
Packit 2fc92b
Packit 2fc92b
	  case 'D' : /* Set the printer-info attribute */
Packit 2fc92b
	      if (opt[1] != '\0')
Packit 2fc92b
	      {
Packit 2fc92b
		num_options = cupsAddOption("printer-info", opt + 1, num_options, &options);
Packit 2fc92b
		opt += strlen(opt) - 1;
Packit 2fc92b
	      }
Packit 2fc92b
	      else
Packit 2fc92b
	      {
Packit 2fc92b
		i ++;
Packit 2fc92b
Packit 2fc92b
		if (i >= argc)
Packit 2fc92b
		{
Packit 2fc92b
		  _cupsLangPuts(stderr, _("lpadmin: Expected description after \"-D\" option."));
Packit 2fc92b
		  return (1);
Packit 2fc92b
		}
Packit 2fc92b
Packit 2fc92b
		num_options = cupsAddOption("printer-info", argv[i], num_options, &options);
Packit 2fc92b
	      }
Packit 2fc92b
	      break;
Packit 2fc92b
Packit 2fc92b
	  case 'I' : /* Set the supported file types (ignored) */
Packit 2fc92b
	      i ++;
Packit 2fc92b
Packit 2fc92b
	      if (i >= argc)
Packit 2fc92b
	      {
Packit 2fc92b
		_cupsLangPuts(stderr, _("lpadmin: Expected file type(s) after \"-I\" option."));
Packit 2fc92b
		return (1);
Packit 2fc92b
	      }
Packit 2fc92b
Packit 2fc92b
	      _cupsLangPuts(stderr, _("lpadmin: Warning - content type list ignored."));
Packit 2fc92b
	      break;
Packit 2fc92b
Packit 2fc92b
	  case 'L' : /* Set the printer-location attribute */
Packit 2fc92b
	      if (opt[1] != '\0')
Packit 2fc92b
	      {
Packit 2fc92b
		num_options = cupsAddOption("printer-location", opt + 1, num_options, &options);
Packit 2fc92b
		opt += strlen(opt) - 1;
Packit 2fc92b
	      }
Packit 2fc92b
	      else
Packit 2fc92b
	      {
Packit 2fc92b
		i ++;
Packit 2fc92b
Packit 2fc92b
		if (i >= argc)
Packit 2fc92b
		{
Packit 2fc92b
		  _cupsLangPuts(stderr, _("lpadmin: Expected location after \"-L\" option."));
Packit 2fc92b
		  return (1);
Packit 2fc92b
		}
Packit 2fc92b
Packit 2fc92b
		num_options = cupsAddOption("printer-location", argv[i], num_options, &options);
Packit 2fc92b
	      }
Packit 2fc92b
	      break;
Packit 2fc92b
Packit 2fc92b
	  default :
Packit 2fc92b
	      _cupsLangPrintf(stderr, _("lpadmin: Unknown option \"%c\"."), *opt);
Packit 2fc92b
	      return (1);
Packit 2fc92b
	}
Packit 2fc92b
      }
Packit 2fc92b
    }
Packit 2fc92b
    else
Packit 2fc92b
    {
Packit 2fc92b
      _cupsLangPrintf(stderr, _("lpadmin: Unknown argument \"%s\"."), argv[i]);
Packit 2fc92b
      return (1);
Packit 2fc92b
    }
Packit 2fc92b
  }
Packit 2fc92b
Packit 2fc92b
 /*
Packit 2fc92b
  * Set options as needed...
Packit 2fc92b
  */
Packit 2fc92b
Packit 2fc92b
  if ((ppd_name = cupsGetOption("ppd-name", num_options, options)) != NULL && !strcmp(ppd_name, "everywhere") && (device_uri = cupsGetOption("device-uri", num_options, options)) != NULL)
Packit 2fc92b
  {
Packit 2fc92b
    if ((file = get_printer_ppd(device_uri, evefile, sizeof(evefile))) == NULL)
Packit 2fc92b
      return (1);
Packit 2fc92b
Packit 2fc92b
    num_options = cupsRemoveOption("ppd-name", num_options, &options);
Packit 2fc92b
  }
Packit 2fc92b
Packit 2fc92b
  if (num_options || file)
Packit 2fc92b
  {
Packit 2fc92b
    if (printer == NULL)
Packit 2fc92b
    {
Packit 2fc92b
      _cupsLangPuts(stderr,
Packit 2fc92b
                    _("lpadmin: Unable to set the printer options:\n"
Packit 2fc92b
                      "         You must specify a printer name first."));
Packit 2fc92b
      return (1);
Packit 2fc92b
    }
Packit 2fc92b
Packit 2fc92b
    if (!http)
Packit 2fc92b
    {
Packit 2fc92b
      http = httpConnect2(cupsServer(), ippPort(), NULL, AF_UNSPEC,
Packit 2fc92b
                          cupsEncryption(), 1, 30000, NULL);
Packit 2fc92b
Packit 2fc92b
      if (http == NULL) {
Packit 2fc92b
        _cupsLangPrintf(stderr, _("lpadmin: Unable to connect to server: %s"),
Packit 2fc92b
                        strerror(errno));
Packit 2fc92b
        return (1);
Packit 2fc92b
      }
Packit 2fc92b
    }
Packit 2fc92b
Packit 2fc92b
    if (set_printer_options(http, printer, num_options, options, file))
Packit 2fc92b
      return (1);
Packit 2fc92b
  }
Packit 2fc92b
Packit 2fc92b
  if (evefile[0])
Packit 2fc92b
    unlink(evefile);
Packit 2fc92b
Packit 2fc92b
  if (printer == NULL)
Packit 2fc92b
  {
Packit 2fc92b
    _cupsLangPuts(stdout,
Packit 2fc92b
	          _("Usage:\n"
Packit 2fc92b
		    "\n"
Packit 2fc92b
		    "    lpadmin [-h server] -d destination\n"
Packit 2fc92b
		    "    lpadmin [-h server] -x destination\n"
Packit 2fc92b
		    "    lpadmin [-h server] -p printer [-c add-class] "
Packit 2fc92b
		    "[-i interface] [-m model]\n"
Packit 2fc92b
		    "                       [-r remove-class] [-v device] "
Packit 2fc92b
		    "[-D description]\n"
Packit 2fc92b
		    "                       [-P ppd-file] [-o name=value]\n"
Packit 2fc92b
		    "                       [-u allow:user,user] "
Packit 2fc92b
		    "[-u deny:user,user]"));
Packit 2fc92b
  }
Packit 2fc92b
Packit 2fc92b
  if (http)
Packit 2fc92b
    httpClose(http);
Packit 2fc92b
Packit 2fc92b
  return (0);
Packit 2fc92b
}
Packit 2fc92b
Packit 2fc92b
Packit 2fc92b
/*
Packit 2fc92b
 * 'add_printer_to_class()' - Add a printer to a class.
Packit 2fc92b
 */
Packit 2fc92b
Packit 2fc92b
static int				/* O - 0 on success, 1 on fail */
Packit 2fc92b
add_printer_to_class(http_t *http,	/* I - Server connection */
Packit 2fc92b
                     char   *printer,	/* I - Printer to add */
Packit 2fc92b
		     char   *pclass)	/* I - Class to add to */
Packit 2fc92b
{
Packit 2fc92b
  int		i;			/* Looping var */
Packit 2fc92b
  ipp_t		*request,		/* IPP Request */
Packit 2fc92b
		*response;		/* IPP Response */
Packit 2fc92b
  ipp_attribute_t *attr,		/* Current attribute */
Packit 2fc92b
		*members;		/* Members in class */
Packit 2fc92b
  char		uri[HTTP_MAX_URI];	/* URI for printer/class */
Packit 2fc92b
Packit 2fc92b
Packit 2fc92b
  DEBUG_printf(("add_printer_to_class(%p, \"%s\", \"%s\")\n", http,
Packit 2fc92b
                printer, pclass));
Packit 2fc92b
Packit 2fc92b
 /*
Packit 2fc92b
  * Build an IPP_OP_GET_PRINTER_ATTRIBUTES request, which requires the following
Packit 2fc92b
  * attributes:
Packit 2fc92b
  *
Packit 2fc92b
  *    attributes-charset
Packit 2fc92b
  *    attributes-natural-language
Packit 2fc92b
  *    printer-uri
Packit 2fc92b
  *    requesting-user-name
Packit 2fc92b
  */
Packit 2fc92b
Packit 2fc92b
  request = ippNewRequest(IPP_OP_GET_PRINTER_ATTRIBUTES);
Packit 2fc92b
Packit 2fc92b
  httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
Packit 2fc92b
                   "localhost", 0, "/classes/%s", pclass);
Packit 2fc92b
  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
Packit 2fc92b
               "printer-uri", NULL, uri);
Packit 2fc92b
  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
Packit 2fc92b
               NULL, cupsUser());
Packit 2fc92b
Packit 2fc92b
 /*
Packit 2fc92b
  * Do the request and get back a response...
Packit 2fc92b
  */
Packit 2fc92b
Packit 2fc92b
  response = cupsDoRequest(http, request, "/");
Packit 2fc92b
Packit 2fc92b
 /*
Packit 2fc92b
  * Build a CUPS-Add-Modify-Class request, which requires the following
Packit 2fc92b
  * attributes:
Packit 2fc92b
  *
Packit 2fc92b
  *    attributes-charset
Packit 2fc92b
  *    attributes-natural-language
Packit 2fc92b
  *    printer-uri
Packit 2fc92b
  *    requesting-user-name
Packit 2fc92b
  *    member-uris
Packit 2fc92b
  */
Packit 2fc92b
Packit 2fc92b
  request = ippNewRequest(IPP_OP_CUPS_ADD_MODIFY_CLASS);
Packit 2fc92b
Packit 2fc92b
  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
Packit 2fc92b
               "printer-uri", NULL, uri);
Packit 2fc92b
  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
Packit 2fc92b
               NULL, cupsUser());
Packit 2fc92b
Packit 2fc92b
 /*
Packit 2fc92b
  * See if the printer is already in the class...
Packit 2fc92b
  */
Packit 2fc92b
Packit 2fc92b
  if (response != NULL &&
Packit 2fc92b
      (members = ippFindAttribute(response, "member-names",
Packit 2fc92b
                                  IPP_TAG_NAME)) != NULL)
Packit 2fc92b
    for (i = 0; i < members->num_values; i ++)
Packit 2fc92b
      if (_cups_strcasecmp(printer, members->values[i].string.text) == 0)
Packit 2fc92b
      {
Packit 2fc92b
        _cupsLangPrintf(stderr,
Packit 2fc92b
	                _("lpadmin: Printer %s is already a member of class "
Packit 2fc92b
			  "%s."), printer, pclass);
Packit 2fc92b
        ippDelete(request);
Packit 2fc92b
	ippDelete(response);
Packit 2fc92b
	return (0);
Packit 2fc92b
      }
Packit 2fc92b
Packit 2fc92b
 /*
Packit 2fc92b
  * OK, the printer isn't part of the class, so add it...
Packit 2fc92b
  */
Packit 2fc92b
Packit 2fc92b
  httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
Packit 2fc92b
                   "localhost", 0, "/printers/%s", printer);
Packit 2fc92b
Packit 2fc92b
  if (response != NULL &&
Packit 2fc92b
      (members = ippFindAttribute(response, "member-uris",
Packit 2fc92b
                                  IPP_TAG_URI)) != NULL)
Packit 2fc92b
  {
Packit 2fc92b
   /*
Packit 2fc92b
    * Add the printer to the existing list...
Packit 2fc92b
    */
Packit 2fc92b
Packit 2fc92b
    attr = ippAddStrings(request, IPP_TAG_PRINTER, IPP_TAG_URI,
Packit 2fc92b
                         "member-uris", members->num_values + 1, NULL, NULL);
Packit 2fc92b
    for (i = 0; i < members->num_values; i ++)
Packit 2fc92b
      attr->values[i].string.text =
Packit 2fc92b
          _cupsStrAlloc(members->values[i].string.text);
Packit 2fc92b
Packit 2fc92b
    attr->values[i].string.text = _cupsStrAlloc(uri);
Packit 2fc92b
  }
Packit 2fc92b
  else
Packit 2fc92b
    ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_URI, "member-uris", NULL,
Packit 2fc92b
                 uri);
Packit 2fc92b
Packit 2fc92b
 /*
Packit 2fc92b
  * Then send the request...
Packit 2fc92b
  */
Packit 2fc92b
Packit 2fc92b
  ippDelete(response);
Packit 2fc92b
Packit 2fc92b
  ippDelete(cupsDoRequest(http, request, "/admin/"));
Packit 2fc92b
  if (cupsLastError() > IPP_STATUS_OK_CONFLICTING)
Packit 2fc92b
  {
Packit 2fc92b
    _cupsLangPrintf(stderr, _("%s: %s"), "lpadmin", cupsLastErrorString());
Packit 2fc92b
Packit 2fc92b
    return (1);
Packit 2fc92b
  }
Packit 2fc92b
  else
Packit 2fc92b
    return (0);
Packit 2fc92b
}
Packit 2fc92b
Packit 2fc92b
Packit 2fc92b
/*
Packit 2fc92b
 * 'default_printer()' - Set the default printing destination.
Packit 2fc92b
 */
Packit 2fc92b
Packit 2fc92b
static int				/* O - 0 on success, 1 on fail */
Packit 2fc92b
default_printer(http_t *http,		/* I - Server connection */
Packit 2fc92b
                char   *printer)	/* I - Printer name */
Packit 2fc92b
{
Packit 2fc92b
  ipp_t		*request;		/* IPP Request */
Packit 2fc92b
  char		uri[HTTP_MAX_URI];	/* URI for printer/class */
Packit 2fc92b
Packit 2fc92b
Packit 2fc92b
  DEBUG_printf(("default_printer(%p, \"%s\")\n", http, printer));
Packit 2fc92b
Packit 2fc92b
 /*
Packit 2fc92b
  * Build a CUPS-Set-Default request, which requires the following
Packit 2fc92b
  * attributes:
Packit 2fc92b
  *
Packit 2fc92b
  *    attributes-charset
Packit 2fc92b
  *    attributes-natural-language
Packit 2fc92b
  *    printer-uri
Packit 2fc92b
  *    requesting-user-name
Packit 2fc92b
  */
Packit 2fc92b
Packit 2fc92b
  httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
Packit 2fc92b
                   "localhost", 0, "/printers/%s", printer);
Packit 2fc92b
Packit 2fc92b
  request = ippNewRequest(IPP_OP_CUPS_SET_DEFAULT);
Packit 2fc92b
Packit 2fc92b
  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
Packit 2fc92b
               "printer-uri", NULL, uri);
Packit 2fc92b
  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
Packit 2fc92b
               NULL, cupsUser());
Packit 2fc92b
Packit 2fc92b
 /*
Packit 2fc92b
  * Do the request and get back a response...
Packit 2fc92b
  */
Packit 2fc92b
Packit 2fc92b
  ippDelete(cupsDoRequest(http, request, "/admin/"));
Packit 2fc92b
Packit 2fc92b
  if (cupsLastError() > IPP_STATUS_OK_CONFLICTING)
Packit 2fc92b
  {
Packit 2fc92b
    _cupsLangPrintf(stderr, _("%s: %s"), "lpadmin", cupsLastErrorString());
Packit 2fc92b
Packit 2fc92b
    return (1);
Packit 2fc92b
  }
Packit 2fc92b
  else
Packit 2fc92b
    return (0);
Packit 2fc92b
}
Packit 2fc92b
Packit 2fc92b
Packit 2fc92b
/*
Packit 2fc92b
 * 'delete_printer()' - Delete a printer from the system...
Packit 2fc92b
 */
Packit 2fc92b
Packit 2fc92b
static int				/* O - 0 on success, 1 on fail */
Packit 2fc92b
delete_printer(http_t *http,		/* I - Server connection */
Packit 2fc92b
               char   *printer)		/* I - Printer to delete */
Packit 2fc92b
{
Packit 2fc92b
  ipp_t		*request;		/* IPP Request */
Packit 2fc92b
  char		uri[HTTP_MAX_URI];	/* URI for printer/class */
Packit 2fc92b
Packit 2fc92b
Packit 2fc92b
  DEBUG_printf(("delete_printer(%p, \"%s\")\n", http, printer));
Packit 2fc92b
Packit 2fc92b
 /*
Packit 2fc92b
  * Build a CUPS-Delete-Printer request, which requires the following
Packit 2fc92b
  * attributes:
Packit 2fc92b
  *
Packit 2fc92b
  *    attributes-charset
Packit 2fc92b
  *    attributes-natural-language
Packit 2fc92b
  *    printer-uri
Packit 2fc92b
  *    requesting-user-name
Packit 2fc92b
  */
Packit 2fc92b
Packit 2fc92b
  request = ippNewRequest(IPP_OP_CUPS_DELETE_PRINTER);
Packit 2fc92b
Packit 2fc92b
  httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
Packit 2fc92b
                   "localhost", 0, "/printers/%s", printer);
Packit 2fc92b
  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
Packit 2fc92b
               "printer-uri", NULL, uri);
Packit 2fc92b
  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
Packit 2fc92b
               NULL, cupsUser());
Packit 2fc92b
Packit 2fc92b
 /*
Packit 2fc92b
  * Do the request and get back a response...
Packit 2fc92b
  */
Packit 2fc92b
Packit 2fc92b
  ippDelete(cupsDoRequest(http, request, "/admin/"));
Packit 2fc92b
Packit 2fc92b
  if (cupsLastError() > IPP_STATUS_OK_CONFLICTING)
Packit 2fc92b
  {
Packit 2fc92b
    _cupsLangPrintf(stderr, _("%s: %s"), "lpadmin", cupsLastErrorString());
Packit 2fc92b
Packit 2fc92b
    return (1);
Packit 2fc92b
  }
Packit 2fc92b
  else
Packit 2fc92b
    return (0);
Packit 2fc92b
}
Packit 2fc92b
Packit 2fc92b
Packit 2fc92b
/*
Packit 2fc92b
 * 'delete_printer_from_class()' - Delete a printer from a class.
Packit 2fc92b
 */
Packit 2fc92b
Packit 2fc92b
static int				/* O - 0 on success, 1 on fail */
Packit 2fc92b
delete_printer_from_class(
Packit 2fc92b
    http_t *http,			/* I - Server connection */
Packit 2fc92b
    char   *printer,			/* I - Printer to remove */
Packit 2fc92b
    char   *pclass)	  		/* I - Class to remove from */
Packit 2fc92b
{
Packit 2fc92b
  int		i, j, k;		/* Looping vars */
Packit 2fc92b
  ipp_t		*request,		/* IPP Request */
Packit 2fc92b
		*response;		/* IPP Response */
Packit 2fc92b
  ipp_attribute_t *attr,		/* Current attribute */
Packit 2fc92b
		*members;		/* Members in class */
Packit 2fc92b
  char		uri[HTTP_MAX_URI];	/* URI for printer/class */
Packit 2fc92b
Packit 2fc92b
Packit 2fc92b
  DEBUG_printf(("delete_printer_from_class(%p, \"%s\", \"%s\")\n", http,
Packit 2fc92b
                printer, pclass));
Packit 2fc92b
Packit 2fc92b
 /*
Packit 2fc92b
  * Build an IPP_OP_GET_PRINTER_ATTRIBUTES request, which requires the following
Packit 2fc92b
  * attributes:
Packit 2fc92b
  *
Packit 2fc92b
  *    attributes-charset
Packit 2fc92b
  *    attributes-natural-language
Packit 2fc92b
  *    printer-uri
Packit 2fc92b
  *    requesting-user-name
Packit 2fc92b
  */
Packit 2fc92b
Packit 2fc92b
  request = ippNewRequest(IPP_OP_GET_PRINTER_ATTRIBUTES);
Packit 2fc92b
Packit 2fc92b
  httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
Packit 2fc92b
                   "localhost", 0, "/classes/%s", pclass);
Packit 2fc92b
  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
Packit 2fc92b
               "printer-uri", NULL, uri);
Packit 2fc92b
  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
Packit 2fc92b
               NULL, cupsUser());
Packit 2fc92b
Packit 2fc92b
 /*
Packit 2fc92b
  * Do the request and get back a response...
Packit 2fc92b
  */
Packit 2fc92b
Packit 2fc92b
  if ((response = cupsDoRequest(http, request, "/classes/")) == NULL ||
Packit 2fc92b
      response->request.status.status_code == IPP_STATUS_ERROR_NOT_FOUND)
Packit 2fc92b
  {
Packit 2fc92b
    _cupsLangPrintf(stderr, _("%s: %s"), "lpadmin", cupsLastErrorString());
Packit 2fc92b
Packit 2fc92b
    ippDelete(response);
Packit 2fc92b
Packit 2fc92b
    return (1);
Packit 2fc92b
  }
Packit 2fc92b
Packit 2fc92b
 /*
Packit 2fc92b
  * See if the printer is already in the class...
Packit 2fc92b
  */
Packit 2fc92b
Packit 2fc92b
  if ((members = ippFindAttribute(response, "member-names", IPP_TAG_NAME)) == NULL)
Packit 2fc92b
  {
Packit 2fc92b
    _cupsLangPuts(stderr, _("lpadmin: No member names were seen."));
Packit 2fc92b
Packit 2fc92b
    ippDelete(response);
Packit 2fc92b
Packit 2fc92b
    return (1);
Packit 2fc92b
  }
Packit 2fc92b
Packit 2fc92b
  for (i = 0; i < members->num_values; i ++)
Packit 2fc92b
    if (!_cups_strcasecmp(printer, members->values[i].string.text))
Packit 2fc92b
      break;
Packit 2fc92b
Packit 2fc92b
  if (i >= members->num_values)
Packit 2fc92b
  {
Packit 2fc92b
    _cupsLangPrintf(stderr,
Packit 2fc92b
                    _("lpadmin: Printer %s is not a member of class %s."),
Packit 2fc92b
	            printer, pclass);
Packit 2fc92b
Packit 2fc92b
    ippDelete(response);
Packit 2fc92b
Packit 2fc92b
    return (1);
Packit 2fc92b
  }
Packit 2fc92b
Packit 2fc92b
  if (members->num_values == 1)
Packit 2fc92b
  {
Packit 2fc92b
   /*
Packit 2fc92b
    * Build a CUPS-Delete-Class request, which requires the following
Packit 2fc92b
    * attributes:
Packit 2fc92b
    *
Packit 2fc92b
    *    attributes-charset
Packit 2fc92b
    *    attributes-natural-language
Packit 2fc92b
    *    printer-uri
Packit 2fc92b
    *    requesting-user-name
Packit 2fc92b
    */
Packit 2fc92b
Packit 2fc92b
    request = ippNewRequest(IPP_OP_CUPS_DELETE_CLASS);
Packit 2fc92b
Packit 2fc92b
    ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
Packit 2fc92b
        	 "printer-uri", NULL, uri);
Packit 2fc92b
    ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
Packit 2fc92b
                 "requesting-user-name", NULL, cupsUser());
Packit 2fc92b
  }
Packit 2fc92b
  else
Packit 2fc92b
  {
Packit 2fc92b
   /*
Packit 2fc92b
    * Build a IPP_OP_CUPS_ADD_MODIFY_CLASS request, which requires the following
Packit 2fc92b
    * attributes:
Packit 2fc92b
    *
Packit 2fc92b
    *    attributes-charset
Packit 2fc92b
    *    attributes-natural-language
Packit 2fc92b
    *    printer-uri
Packit 2fc92b
    *    requesting-user-name
Packit 2fc92b
    *    member-uris
Packit 2fc92b
    */
Packit 2fc92b
Packit 2fc92b
    request = ippNewRequest(IPP_OP_CUPS_ADD_MODIFY_CLASS);
Packit 2fc92b
Packit 2fc92b
    ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
Packit 2fc92b
        	 "printer-uri", NULL, uri);
Packit 2fc92b
    ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
Packit 2fc92b
                 "requesting-user-name", NULL, cupsUser());
Packit 2fc92b
Packit 2fc92b
   /*
Packit 2fc92b
    * Delete the printer from the class...
Packit 2fc92b
    */
Packit 2fc92b
Packit 2fc92b
    members = ippFindAttribute(response, "member-uris", IPP_TAG_URI);
Packit 2fc92b
    attr = ippAddStrings(request, IPP_TAG_PRINTER, IPP_TAG_URI,
Packit 2fc92b
                         "member-uris", members->num_values - 1, NULL, NULL);
Packit 2fc92b
Packit 2fc92b
    for (j = 0, k = 0; j < members->num_values; j ++)
Packit 2fc92b
      if (j != i)
Packit 2fc92b
        attr->values[k ++].string.text =
Packit 2fc92b
	    _cupsStrAlloc(members->values[j].string.text);
Packit 2fc92b
  }
Packit 2fc92b
Packit 2fc92b
 /*
Packit 2fc92b
  * Then send the request...
Packit 2fc92b
  */
Packit 2fc92b
Packit 2fc92b
  ippDelete(response);
Packit 2fc92b
Packit 2fc92b
  ippDelete(cupsDoRequest(http, request, "/admin/"));
Packit 2fc92b
Packit 2fc92b
  if (cupsLastError() > IPP_STATUS_OK_CONFLICTING)
Packit 2fc92b
  {
Packit 2fc92b
    _cupsLangPrintf(stderr, _("%s: %s"), "lpadmin", cupsLastErrorString());
Packit 2fc92b
Packit 2fc92b
    return (1);
Packit 2fc92b
  }
Packit 2fc92b
  else
Packit 2fc92b
    return (0);
Packit 2fc92b
}
Packit 2fc92b
Packit 2fc92b
Packit 2fc92b
/*
Packit 2fc92b
 * 'delete_printer_option()' - Delete a printer option.
Packit 2fc92b
 */
Packit 2fc92b
Packit 2fc92b
static int				/* O - 0 on success, 1 on fail */
Packit 2fc92b
delete_printer_option(http_t *http,	/* I - Server connection */
Packit 2fc92b
                      char   *printer,	/* I - Printer */
Packit 2fc92b
		      char   *option)	/* I - Option to delete */
Packit 2fc92b
{
Packit 2fc92b
  ipp_t		*request;		/* IPP request */
Packit 2fc92b
  char		uri[HTTP_MAX_URI];	/* URI for printer/class */
Packit 2fc92b
Packit 2fc92b
Packit 2fc92b
 /*
Packit 2fc92b
  * Build a IPP_OP_CUPS_ADD_MODIFY_PRINTER or IPP_OP_CUPS_ADD_MODIFY_CLASS request, which
Packit 2fc92b
  * requires the following attributes:
Packit 2fc92b
  *
Packit 2fc92b
  *    attributes-charset
Packit 2fc92b
  *    attributes-natural-language
Packit 2fc92b
  *    printer-uri
Packit 2fc92b
  *    requesting-user-name
Packit 2fc92b
  *    option with deleteAttr tag
Packit 2fc92b
  */
Packit 2fc92b
Packit 2fc92b
  if (get_printer_type(http, printer, uri, sizeof(uri)) & CUPS_PRINTER_CLASS)
Packit 2fc92b
    request = ippNewRequest(IPP_OP_CUPS_ADD_MODIFY_CLASS);
Packit 2fc92b
  else
Packit 2fc92b
    request = ippNewRequest(IPP_OP_CUPS_ADD_MODIFY_PRINTER);
Packit 2fc92b
Packit 2fc92b
  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
Packit 2fc92b
               "printer-uri", NULL, uri);
Packit 2fc92b
  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
Packit 2fc92b
               "requesting-user-name", NULL, cupsUser());
Packit 2fc92b
  ippAddInteger(request, IPP_TAG_PRINTER, IPP_TAG_DELETEATTR, option, 0);
Packit 2fc92b
Packit 2fc92b
 /*
Packit 2fc92b
  * Do the request and get back a response...
Packit 2fc92b
  */
Packit 2fc92b
Packit 2fc92b
  ippDelete(cupsDoRequest(http, request, "/admin/"));
Packit 2fc92b
Packit 2fc92b
  if (cupsLastError() > IPP_STATUS_OK_CONFLICTING)
Packit 2fc92b
  {
Packit 2fc92b
    _cupsLangPrintf(stderr, _("%s: %s"), "lpadmin", cupsLastErrorString());
Packit 2fc92b
Packit 2fc92b
    return (1);
Packit 2fc92b
  }
Packit 2fc92b
  else
Packit 2fc92b
    return (0);
Packit 2fc92b
}
Packit 2fc92b
Packit 2fc92b
Packit 2fc92b
/*
Packit 2fc92b
 * 'enable_printer()' - Enable a printer...
Packit 2fc92b
 */
Packit 2fc92b
Packit 2fc92b
static int				/* O - 0 on success, 1 on fail */
Packit 2fc92b
enable_printer(http_t *http,		/* I - Server connection */
Packit 2fc92b
               char   *printer)		/* I - Printer to enable */
Packit 2fc92b
{
Packit 2fc92b
  ipp_t		*request;		/* IPP Request */
Packit 2fc92b
  char		uri[HTTP_MAX_URI];	/* URI for printer/class */
Packit 2fc92b
Packit 2fc92b
Packit 2fc92b
  DEBUG_printf(("enable_printer(%p, \"%s\")\n", http, printer));
Packit 2fc92b
Packit 2fc92b
 /*
Packit 2fc92b
  * Build a IPP_OP_CUPS_ADD_MODIFY_PRINTER or IPP_OP_CUPS_ADD_MODIFY_CLASS request, which
Packit 2fc92b
  * require the following attributes:
Packit 2fc92b
  *
Packit 2fc92b
  *    attributes-charset
Packit 2fc92b
  *    attributes-natural-language
Packit 2fc92b
  *    printer-uri
Packit 2fc92b
  *    requesting-user-name
Packit 2fc92b
  *    printer-state
Packit 2fc92b
  *    printer-is-accepting-jobs
Packit 2fc92b
  */
Packit 2fc92b
Packit 2fc92b
  if (get_printer_type(http, printer, uri, sizeof(uri)) & CUPS_PRINTER_CLASS)
Packit 2fc92b
    request = ippNewRequest(IPP_OP_CUPS_ADD_MODIFY_CLASS);
Packit 2fc92b
  else
Packit 2fc92b
    request = ippNewRequest(IPP_OP_CUPS_ADD_MODIFY_PRINTER);
Packit 2fc92b
Packit 2fc92b
  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
Packit 2fc92b
               "printer-uri", NULL, uri);
Packit 2fc92b
  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
Packit 2fc92b
               "requesting-user-name", NULL, cupsUser());
Packit 2fc92b
  ippAddInteger(request, IPP_TAG_PRINTER, IPP_TAG_ENUM, "printer-state",
Packit 2fc92b
                IPP_PSTATE_IDLE);
Packit 2fc92b
  ippAddBoolean(request, IPP_TAG_PRINTER, "printer-is-accepting-jobs", 1);
Packit 2fc92b
Packit 2fc92b
 /*
Packit 2fc92b
  * Do the request and get back a response...
Packit 2fc92b
  */
Packit 2fc92b
Packit 2fc92b
  ippDelete(cupsDoRequest(http, request, "/admin/"));
Packit 2fc92b
Packit 2fc92b
  if (cupsLastError() > IPP_STATUS_OK_CONFLICTING)
Packit 2fc92b
  {
Packit 2fc92b
    _cupsLangPrintf(stderr, _("%s: %s"), "lpadmin", cupsLastErrorString());
Packit 2fc92b
Packit 2fc92b
    return (1);
Packit 2fc92b
  }
Packit 2fc92b
  else
Packit 2fc92b
    return (0);
Packit 2fc92b
}
Packit 2fc92b
Packit 2fc92b
Packit 2fc92b
/*
Packit 2fc92b
 * 'get_printer_ppd()' - Get an IPP Everywhere PPD file for the given URI.
Packit 2fc92b
 */
Packit 2fc92b
Packit 2fc92b
static char *				/* O - Filename or NULL */
Packit 2fc92b
get_printer_ppd(const char *uri,	/* I - Printer URI */
Packit 2fc92b
                char       *buffer,	/* I - Filename buffer */
Packit 2fc92b
		size_t     bufsize)	/* I - Size of filename buffer */
Packit 2fc92b
{
Packit 2fc92b
  http_t	*http;			/* Connection to printer */
Packit 2fc92b
  ipp_t		*request,		/* Get-Printer-Attributes request */
Packit 2fc92b
		*response;		/* Get-Printer-Attributes response */
Packit 2fc92b
  char		resolved[1024],		/* Resolved URI */
Packit 2fc92b
		scheme[32],		/* URI scheme */
Packit 2fc92b
		userpass[256],		/* Username:password */
Packit 2fc92b
		host[256],		/* Hostname */
Packit 2fc92b
		resource[256];		/* Resource path */
Packit 2fc92b
  int		port;			/* Port number */
Packit 2fc92b
Packit 2fc92b
Packit 2fc92b
 /*
Packit 2fc92b
  * Connect to the printer...
Packit 2fc92b
  */
Packit 2fc92b
Packit 2fc92b
  if (strstr(uri, "._tcp"))
Packit 2fc92b
  {
Packit 2fc92b
   /*
Packit 2fc92b
    * Resolve URI...
Packit 2fc92b
    */
Packit 2fc92b
Packit 2fc92b
    if (!_httpResolveURI(uri, resolved, sizeof(resolved), _HTTP_RESOLVE_DEFAULT, NULL, NULL))
Packit 2fc92b
    {
Packit 2fc92b
      _cupsLangPrintf(stderr, _("%s: Unable to resolve \"%s\"."), "lpadmin", uri);
Packit 2fc92b
      return (NULL);
Packit 2fc92b
    }
Packit 2fc92b
Packit 2fc92b
    uri = resolved;
Packit 2fc92b
  }
Packit 2fc92b
Packit 2fc92b
  if (httpSeparateURI(HTTP_URI_CODING_ALL, uri, scheme, sizeof(scheme), userpass, sizeof(userpass), host, sizeof(host), &port, resource, sizeof(resource)) < HTTP_URI_STATUS_OK)
Packit 2fc92b
  {
Packit 2fc92b
    _cupsLangPrintf(stderr, _("%s: Bad printer URI \"%s\"."), "lpadmin", uri);
Packit 2fc92b
    return (NULL);
Packit 2fc92b
  }
Packit 2fc92b
Packit 2fc92b
  http = httpConnect2(host, port, NULL, AF_UNSPEC, !strcmp(scheme, "ipps") ? HTTP_ENCRYPTION_ALWAYS : HTTP_ENCRYPTION_IF_REQUESTED, 1, 30000, NULL);
Packit 2fc92b
  if (!http)
Packit 2fc92b
  {
Packit 2fc92b
    _cupsLangPrintf(stderr, _("%s: Unable to connect to \"%s:%d\": %s"), "lpadmin", host, port, cupsLastErrorString());
Packit 2fc92b
    return (NULL);
Packit 2fc92b
  }
Packit 2fc92b
Packit 2fc92b
 /*
Packit 2fc92b
  * Send a Get-Printer-Attributes request...
Packit 2fc92b
  */
Packit 2fc92b
Packit 2fc92b
  request = ippNewRequest(IPP_OP_GET_PRINTER_ATTRIBUTES);
Packit 2fc92b
  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri);
Packit 2fc92b
  response = cupsDoRequest(http, request, resource);
Packit 2fc92b
Packit 2fc92b
  if (!_ppdCreateFromIPP(buffer, bufsize, response))
Packit 2fc92b
    _cupsLangPrintf(stderr, _("%s: Unable to create PPD file: %s"), "lpadmin", strerror(errno));
Packit 2fc92b
Packit 2fc92b
  ippDelete(response);
Packit 2fc92b
  httpClose(http);
Packit 2fc92b
Packit 2fc92b
  if (buffer[0])
Packit 2fc92b
    return (buffer);
Packit 2fc92b
  else
Packit 2fc92b
    return (NULL);
Packit 2fc92b
}
Packit 2fc92b
Packit 2fc92b
Packit 2fc92b
/*
Packit 2fc92b
 * 'get_printer_type()' - Determine the printer type and URI.
Packit 2fc92b
 */
Packit 2fc92b
Packit 2fc92b
static cups_ptype_t			/* O - printer-type value */
Packit 2fc92b
get_printer_type(http_t *http,		/* I - Server connection */
Packit 2fc92b
                 char   *printer,	/* I - Printer name */
Packit 2fc92b
		 char   *uri,		/* I - URI buffer */
Packit 2fc92b
                 size_t urisize)	/* I - Size of URI buffer */
Packit 2fc92b
{
Packit 2fc92b
  ipp_t			*request,	/* IPP request */
Packit 2fc92b
			*response;	/* IPP response */
Packit 2fc92b
  ipp_attribute_t	*attr;		/* printer-type attribute */
Packit 2fc92b
  cups_ptype_t		type;		/* printer-type value */
Packit 2fc92b
Packit 2fc92b
Packit 2fc92b
 /*
Packit 2fc92b
  * Build a GET_PRINTER_ATTRIBUTES request, which requires the following
Packit 2fc92b
  * attributes:
Packit 2fc92b
  *
Packit 2fc92b
  *    attributes-charset
Packit 2fc92b
  *    attributes-natural-language
Packit 2fc92b
  *    printer-uri
Packit 2fc92b
  *    requested-attributes
Packit 2fc92b
  *    requesting-user-name
Packit 2fc92b
  */
Packit 2fc92b
Packit 2fc92b
  httpAssembleURIf(HTTP_URI_CODING_ALL, uri, (int)urisize, "ipp", NULL, "localhost", ippPort(), "/printers/%s", printer);
Packit 2fc92b
Packit 2fc92b
  request = ippNewRequest(IPP_OP_GET_PRINTER_ATTRIBUTES);
Packit 2fc92b
  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
Packit 2fc92b
               "printer-uri", NULL, uri);
Packit 2fc92b
  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
Packit 2fc92b
               "requested-attributes", NULL, "printer-type");
Packit 2fc92b
  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
Packit 2fc92b
               "requesting-user-name", NULL, cupsUser());
Packit 2fc92b
Packit 2fc92b
 /*
Packit 2fc92b
  * Do the request...
Packit 2fc92b
  */
Packit 2fc92b
Packit 2fc92b
  response = cupsDoRequest(http, request, "/");
Packit 2fc92b
  if ((attr = ippFindAttribute(response, "printer-type",
Packit 2fc92b
                               IPP_TAG_ENUM)) != NULL)
Packit 2fc92b
  {
Packit 2fc92b
    type = (cups_ptype_t)attr->values[0].integer;
Packit 2fc92b
Packit 2fc92b
    if (type & CUPS_PRINTER_CLASS)
Packit 2fc92b
      httpAssembleURIf(HTTP_URI_CODING_ALL, uri, (int)urisize, "ipp", NULL, "localhost", ippPort(), "/classes/%s", printer);
Packit 2fc92b
  }
Packit 2fc92b
  else
Packit 2fc92b
    type = CUPS_PRINTER_LOCAL;
Packit 2fc92b
Packit 2fc92b
  ippDelete(response);
Packit 2fc92b
Packit 2fc92b
  return (type);
Packit 2fc92b
}
Packit 2fc92b
Packit 2fc92b
Packit 2fc92b
/*
Packit 2fc92b
 * 'set_printer_options()' - Set the printer options.
Packit 2fc92b
 */
Packit 2fc92b
Packit 2fc92b
static int				/* O - 0 on success, 1 on fail */
Packit 2fc92b
set_printer_options(
Packit 2fc92b
    http_t        *http,		/* I - Server connection */
Packit 2fc92b
    char          *printer,		/* I - Printer */
Packit 2fc92b
    int           num_options,		/* I - Number of options */
Packit 2fc92b
    cups_option_t *options,		/* I - Options */
Packit 2fc92b
    char          *file)		/* I - PPD file/interface script */
Packit 2fc92b
{
Packit 2fc92b
  ipp_t		*request;		/* IPP Request */
Packit 2fc92b
  const char	*ppdfile;		/* PPD filename */
Packit 2fc92b
  int		ppdchanged = 0;		/* PPD changed? */
Packit 2fc92b
  ppd_file_t	*ppd;			/* PPD file */
Packit 2fc92b
  ppd_choice_t	*choice;		/* Marked choice */
Packit 2fc92b
  char		uri[HTTP_MAX_URI],	/* URI for printer/class */
Packit 2fc92b
		line[1024],		/* Line from PPD file */
Packit 2fc92b
		keyword[1024],		/* Keyword from Default line */
Packit 2fc92b
		*keyptr,		/* Pointer into keyword... */
Packit 2fc92b
		tempfile[1024];		/* Temporary filename */
Packit 2fc92b
  cups_file_t	*in,			/* PPD file */
Packit 2fc92b
		*out;			/* Temporary file */
Packit 2fc92b
  const char	*ppdname,		/* ppd-name value */
Packit 2fc92b
		*protocol,		/* Old protocol option */
Packit 2fc92b
		*customval,		/* Custom option value */
Packit 2fc92b
		*boolval;		/* Boolean value */
Packit 2fc92b
  int		wrote_ipp_supplies = 0,	/* Wrote cupsIPPSupplies keyword? */
Packit 2fc92b
		wrote_snmp_supplies = 0,/* Wrote cupsSNMPSupplies keyword? */
Packit 2fc92b
		copied_options = 0;	/* Copied options? */
Packit 2fc92b
Packit 2fc92b
Packit 2fc92b
  DEBUG_printf(("set_printer_options(http=%p, printer=\"%s\", num_options=%d, "
Packit 2fc92b
                "options=%p, file=\"%s\")\n", http, printer, num_options,
Packit 2fc92b
		options, file));
Packit 2fc92b
Packit 2fc92b
 /*
Packit 2fc92b
  * Build a CUPS-Add-Modify-Printer or CUPS-Add-Modify-Class request,
Packit 2fc92b
  * which requires the following attributes:
Packit 2fc92b
  *
Packit 2fc92b
  *    attributes-charset
Packit 2fc92b
  *    attributes-natural-language
Packit 2fc92b
  *    printer-uri
Packit 2fc92b
  *    requesting-user-name
Packit 2fc92b
  *    other options
Packit 2fc92b
  */
Packit 2fc92b
Packit 2fc92b
  if (get_printer_type(http, printer, uri, sizeof(uri)) & CUPS_PRINTER_CLASS)
Packit 2fc92b
    request = ippNewRequest(IPP_OP_CUPS_ADD_MODIFY_CLASS);
Packit 2fc92b
  else
Packit 2fc92b
    request = ippNewRequest(IPP_OP_CUPS_ADD_MODIFY_PRINTER);
Packit 2fc92b
Packit 2fc92b
  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri);
Packit 2fc92b
  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsUser());
Packit 2fc92b
Packit 2fc92b
 /*
Packit 2fc92b
  * Add the options...
Packit 2fc92b
  */
Packit 2fc92b
Packit 2fc92b
  if (file)
Packit 2fc92b
    ppdfile = file;
Packit 2fc92b
  else if ((ppdname = cupsGetOption("ppd-name", num_options, options)) != NULL && strcmp(ppdname, "raw") && num_options > 1)
Packit 2fc92b
  {
Packit 2fc92b
    if ((ppdfile = cupsGetServerPPD(http, ppdname)) != NULL)
Packit 2fc92b
    {
Packit 2fc92b
     /*
Packit 2fc92b
      * Copy options array and remove ppd-name from it...
Packit 2fc92b
      */
Packit 2fc92b
Packit 2fc92b
      cups_option_t *temp = NULL, *optr;
Packit 2fc92b
      int i, num_temp = 0;
Packit 2fc92b
      for (i = num_options, optr = options; i > 0; i --, optr ++)
Packit 2fc92b
        if (strcmp(optr->name, "ppd-name"))
Packit 2fc92b
	  num_temp = cupsAddOption(optr->name, optr->value, num_temp, &temp);
Packit 2fc92b
Packit 2fc92b
      copied_options = 1;
Packit 2fc92b
      ppdchanged     = 1;
Packit 2fc92b
      num_options    = num_temp;
Packit 2fc92b
      options        = temp;
Packit 2fc92b
    }
Packit 2fc92b
  }
Packit 2fc92b
  else if (request->request.op.operation_id == IPP_OP_CUPS_ADD_MODIFY_PRINTER)
Packit 2fc92b
    ppdfile = cupsGetPPD(printer);
Packit 2fc92b
  else
Packit 2fc92b
    ppdfile = NULL;
Packit 2fc92b
Packit 2fc92b
  cupsEncodeOptions2(request, num_options, options, IPP_TAG_OPERATION);
Packit 2fc92b
  cupsEncodeOptions2(request, num_options, options, IPP_TAG_PRINTER);
Packit 2fc92b
Packit 2fc92b
  if ((protocol = cupsGetOption("protocol", num_options, options)) != NULL)
Packit 2fc92b
  {
Packit 2fc92b
    if (!_cups_strcasecmp(protocol, "bcp"))
Packit 2fc92b
      ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_NAME, "port-monitor",
Packit 2fc92b
                   NULL, "bcp");
Packit 2fc92b
    else if (!_cups_strcasecmp(protocol, "tbcp"))
Packit 2fc92b
      ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_NAME, "port-monitor",
Packit 2fc92b
                   NULL, "tbcp");
Packit 2fc92b
  }
Packit 2fc92b
Packit 2fc92b
  if (ppdfile)
Packit 2fc92b
  {
Packit 2fc92b
   /*
Packit 2fc92b
    * Set default options in the PPD file...
Packit 2fc92b
    */
Packit 2fc92b
Packit 2fc92b
    if ((ppd = ppdOpenFile(ppdfile)) == NULL)
Packit 2fc92b
    {
Packit 2fc92b
      int		linenum;	/* Line number of error */
Packit 2fc92b
      ppd_status_t	status = ppdLastError(&linenum);
Packit 2fc92b
					/* Status code */
Packit 2fc92b
Packit 2fc92b
      _cupsLangPrintf(stderr, _("lpadmin: Unable to open PPD \"%s\": %s on line %d."), ppdfile, ppdErrorString(status), linenum);
Packit 2fc92b
    }
Packit 2fc92b
Packit 2fc92b
    ppdMarkDefaults(ppd);
Packit 2fc92b
    cupsMarkOptions(ppd, num_options, options);
Packit 2fc92b
Packit 2fc92b
    if ((out = cupsTempFile2(tempfile, sizeof(tempfile))) == NULL)
Packit 2fc92b
    {
Packit 2fc92b
      _cupsLangPrintError(NULL, _("lpadmin: Unable to create temporary file"));
Packit 2fc92b
      ippDelete(request);
Packit 2fc92b
      if (ppdfile != file)
Packit 2fc92b
        unlink(ppdfile);
Packit 2fc92b
      if (copied_options)
Packit 2fc92b
        cupsFreeOptions(num_options, options);
Packit 2fc92b
      return (1);
Packit 2fc92b
    }
Packit 2fc92b
Packit 2fc92b
    if ((in = cupsFileOpen(ppdfile, "r")) == NULL)
Packit 2fc92b
    {
Packit 2fc92b
      _cupsLangPrintf(stderr,
Packit 2fc92b
                      _("lpadmin: Unable to open PPD file \"%s\" - %s"),
Packit 2fc92b
        	      ppdfile, strerror(errno));
Packit 2fc92b
      ippDelete(request);
Packit 2fc92b
      if (ppdfile != file)
Packit 2fc92b
	unlink(ppdfile);
Packit 2fc92b
      if (copied_options)
Packit 2fc92b
        cupsFreeOptions(num_options, options);
Packit 2fc92b
      cupsFileClose(out);
Packit 2fc92b
      unlink(tempfile);
Packit 2fc92b
      return (1);
Packit 2fc92b
    }
Packit 2fc92b
Packit 2fc92b
    while (cupsFileGets(in, line, sizeof(line)))
Packit 2fc92b
    {
Packit 2fc92b
      if (!strncmp(line, "*cupsIPPSupplies:", 17) &&
Packit 2fc92b
	  (boolval = cupsGetOption("cupsIPPSupplies", num_options,
Packit 2fc92b
	                           options)) != NULL)
Packit 2fc92b
      {
Packit 2fc92b
        wrote_ipp_supplies = 1;
Packit 2fc92b
        cupsFilePrintf(out, "*cupsIPPSupplies: %s\n",
Packit 2fc92b
	               (!_cups_strcasecmp(boolval, "true") ||
Packit 2fc92b
		        !_cups_strcasecmp(boolval, "yes") ||
Packit 2fc92b
		        !_cups_strcasecmp(boolval, "on")) ? "True" : "False");
Packit 2fc92b
      }
Packit 2fc92b
      else if (!strncmp(line, "*cupsSNMPSupplies:", 18) &&
Packit 2fc92b
	       (boolval = cupsGetOption("cupsSNMPSupplies", num_options,
Packit 2fc92b
	                                options)) != NULL)
Packit 2fc92b
      {
Packit 2fc92b
        wrote_snmp_supplies = 1;
Packit 2fc92b
        cupsFilePrintf(out, "*cupsSNMPSupplies: %s\n",
Packit 2fc92b
	               (!_cups_strcasecmp(boolval, "true") ||
Packit 2fc92b
		        !_cups_strcasecmp(boolval, "yes") ||
Packit 2fc92b
		        !_cups_strcasecmp(boolval, "on")) ? "True" : "False");
Packit 2fc92b
      }
Packit 2fc92b
      else if (strncmp(line, "*Default", 8))
Packit 2fc92b
        cupsFilePrintf(out, "%s\n", line);
Packit 2fc92b
      else
Packit 2fc92b
      {
Packit 2fc92b
       /*
Packit 2fc92b
        * Get default option name...
Packit 2fc92b
	*/
Packit 2fc92b
Packit 2fc92b
        strlcpy(keyword, line + 8, sizeof(keyword));
Packit 2fc92b
Packit 2fc92b
	for (keyptr = keyword; *keyptr; keyptr ++)
Packit 2fc92b
	  if (*keyptr == ':' || isspace(*keyptr & 255))
Packit 2fc92b
	    break;
Packit 2fc92b
Packit 2fc92b
        *keyptr++ = '\0';
Packit 2fc92b
        while (isspace(*keyptr & 255))
Packit 2fc92b
	  keyptr ++;
Packit 2fc92b
Packit 2fc92b
        if (!strcmp(keyword, "PageRegion") ||
Packit 2fc92b
	    !strcmp(keyword, "PageSize") ||
Packit 2fc92b
	    !strcmp(keyword, "PaperDimension") ||
Packit 2fc92b
	    !strcmp(keyword, "ImageableArea"))
Packit 2fc92b
	{
Packit 2fc92b
	  if ((choice = ppdFindMarkedChoice(ppd, "PageSize")) == NULL)
Packit 2fc92b
	    choice = ppdFindMarkedChoice(ppd, "PageRegion");
Packit 2fc92b
        }
Packit 2fc92b
	else
Packit 2fc92b
	  choice = ppdFindMarkedChoice(ppd, keyword);
Packit 2fc92b
Packit 2fc92b
        if (choice && strcmp(choice->choice, keyptr))
Packit 2fc92b
	{
Packit 2fc92b
	  if (strcmp(choice->choice, "Custom"))
Packit 2fc92b
	  {
Packit 2fc92b
	    cupsFilePrintf(out, "*Default%s: %s\n", keyword, choice->choice);
Packit 2fc92b
	    ppdchanged = 1;
Packit 2fc92b
	  }
Packit 2fc92b
	  else if ((customval = cupsGetOption(keyword, num_options,
Packit 2fc92b
	                                      options)) != NULL)
Packit 2fc92b
	  {
Packit 2fc92b
	    cupsFilePrintf(out, "*Default%s: %s\n", keyword, customval);
Packit 2fc92b
	    ppdchanged = 1;
Packit 2fc92b
	  }
Packit 2fc92b
	  else
Packit 2fc92b
	    cupsFilePrintf(out, "%s\n", line);
Packit 2fc92b
	}
Packit 2fc92b
	else
Packit 2fc92b
	  cupsFilePrintf(out, "%s\n", line);
Packit 2fc92b
      }
Packit 2fc92b
    }
Packit 2fc92b
Packit 2fc92b
    if (!wrote_ipp_supplies &&
Packit 2fc92b
	(boolval = cupsGetOption("cupsIPPSupplies", num_options,
Packit 2fc92b
				 options)) != NULL)
Packit 2fc92b
    {
Packit 2fc92b
      cupsFilePrintf(out, "*cupsIPPSupplies: %s\n",
Packit 2fc92b
		     (!_cups_strcasecmp(boolval, "true") ||
Packit 2fc92b
		      !_cups_strcasecmp(boolval, "yes") ||
Packit 2fc92b
		      !_cups_strcasecmp(boolval, "on")) ? "True" : "False");
Packit 2fc92b
    }
Packit 2fc92b
Packit 2fc92b
    if (!wrote_snmp_supplies &&
Packit 2fc92b
        (boolval = cupsGetOption("cupsSNMPSupplies", num_options,
Packit 2fc92b
			         options)) != NULL)
Packit 2fc92b
    {
Packit 2fc92b
      cupsFilePrintf(out, "*cupsSNMPSupplies: %s\n",
Packit 2fc92b
		     (!_cups_strcasecmp(boolval, "true") ||
Packit 2fc92b
		      !_cups_strcasecmp(boolval, "yes") ||
Packit 2fc92b
		      !_cups_strcasecmp(boolval, "on")) ? "True" : "False");
Packit 2fc92b
    }
Packit 2fc92b
Packit 2fc92b
    cupsFileClose(in);
Packit 2fc92b
    cupsFileClose(out);
Packit 2fc92b
    ppdClose(ppd);
Packit 2fc92b
Packit 2fc92b
   /*
Packit 2fc92b
    * Do the request...
Packit 2fc92b
    */
Packit 2fc92b
Packit 2fc92b
    ippDelete(cupsDoFileRequest(http, request, "/admin/",
Packit 2fc92b
                                ppdchanged ? tempfile : file));
Packit 2fc92b
Packit 2fc92b
   /*
Packit 2fc92b
    * Clean up temp files... (TODO: catch signals in case we CTRL-C during
Packit 2fc92b
    * lpadmin)
Packit 2fc92b
    */
Packit 2fc92b
Packit 2fc92b
    if (ppdfile != file)
Packit 2fc92b
      unlink(ppdfile);
Packit 2fc92b
    unlink(tempfile);
Packit 2fc92b
  }
Packit 2fc92b
  else
Packit 2fc92b
  {
Packit 2fc92b
   /*
Packit 2fc92b
    * No PPD file - just set the options...
Packit 2fc92b
    */
Packit 2fc92b
Packit 2fc92b
    ippDelete(cupsDoRequest(http, request, "/admin/"));
Packit 2fc92b
  }
Packit 2fc92b
Packit 2fc92b
  if (copied_options)
Packit 2fc92b
    cupsFreeOptions(num_options, options);
Packit 2fc92b
Packit 2fc92b
 /*
Packit 2fc92b
  * Check the response...
Packit 2fc92b
  */
Packit 2fc92b
Packit 2fc92b
  if (cupsLastError() > IPP_STATUS_OK_CONFLICTING)
Packit 2fc92b
  {
Packit 2fc92b
    _cupsLangPrintf(stderr, _("%s: %s"), "lpadmin", cupsLastErrorString());
Packit 2fc92b
Packit 2fc92b
    return (1);
Packit 2fc92b
  }
Packit 2fc92b
  else
Packit 2fc92b
    return (0);
Packit 2fc92b
}
Packit 2fc92b
Packit 2fc92b
Packit 2fc92b
/*
Packit 2fc92b
 * 'validate_name()' - Make sure the printer name only contains valid chars.
Packit 2fc92b
 */
Packit 2fc92b
Packit 2fc92b
static int				/* O - 0 if name is no good, 1 if name is good */
Packit 2fc92b
validate_name(const char *name)		/* I - Name to check */
Packit 2fc92b
{
Packit 2fc92b
  const char	*ptr;			/* Pointer into name */
Packit 2fc92b
Packit 2fc92b
Packit 2fc92b
 /*
Packit 2fc92b
  * Scan the whole name...
Packit 2fc92b
  */
Packit 2fc92b
Packit 2fc92b
  for (ptr = name; *ptr; ptr ++)
Packit 2fc92b
    if (*ptr == '@')
Packit 2fc92b
      break;
Packit 2fc92b
    else if ((*ptr >= 0 && *ptr <= ' ') || *ptr == 127 || *ptr == '/' ||
Packit 2fc92b
             *ptr == '#')
Packit 2fc92b
      return (0);
Packit 2fc92b
Packit 2fc92b
 /*
Packit 2fc92b
  * All the characters are good; validate the length, too...
Packit 2fc92b
  */
Packit 2fc92b
Packit 2fc92b
  return ((ptr - name) < 128);
Packit 2fc92b
}