1 /*
2  * "lpmove" command for CUPS.
3  *
4  * Copyright © 2007-2018 by Apple Inc.
5  * Copyright © 1997-2006 by Easy Software Products.
6  *
7  * Licensed under Apache License v2.0.  See the file "LICENSE" for more
8  * information.
9  */
10 
11 /*
12  * Include necessary headers...
13  */
14 
15 #include <cups/cups-private.h>
16 
17 
18 /*
19  * Local functions...
20  */
21 
22 static int	move_job(http_t *http, const char *src, int jobid, const char *dest);
23 static void	usage(void) _CUPS_NORETURN;
24 
25 
26 /*
27  * 'main()' - Parse options and show status information.
28  */
29 
30 int
main(int argc,char * argv[])31 main(int  argc,				/* I - Number of command-line arguments */
32      char *argv[])			/* I - Command-line arguments */
33 {
34   int		i;			/* Looping var */
35   http_t	*http;			/* Connection to server */
36   const char	*opt,			/* Option pointer */
37 		*job;			/* Job name */
38   int		jobid;			/* Job ID */
39   int		num_dests;		/* Number of destinations */
40   cups_dest_t	*dests;			/* Destinations */
41   const char	*src,			/* Original queue */
42 		*dest;			/* New destination */
43 
44 
45   _cupsSetLocale(argv);
46 
47   dest      = NULL;
48   dests     = NULL;
49   job       = NULL;
50   jobid     = 0;
51   num_dests = 0;
52   src       = NULL;
53 
54   for (i = 1; i < argc; i ++)
55   {
56     if (!strcmp(argv[i], "--help"))
57       usage();
58     else if (argv[i][0] == '-')
59     {
60       for (opt = argv[i] + 1; *opt; opt ++)
61       {
62 	switch (*opt)
63 	{
64 	  case 'E' : /* Encrypt */
65 #ifdef HAVE_SSL
66 	      cupsSetEncryption(HTTP_ENCRYPT_REQUIRED);
67 
68 #else
69 	      _cupsLangPrintf(stderr, _("%s: Sorry, no encryption support."), argv[0]);
70 #endif /* HAVE_SSL */
71 	      break;
72 
73 	  case 'h' : /* Connect to host */
74 	      if (opt[1] != '\0')
75 	      {
76 		cupsSetServer(opt + 1);
77 		opt += strlen(opt) - 1;
78 	      }
79 	      else
80 	      {
81 		i ++;
82 
83 		if (i >= argc)
84 		{
85 		  _cupsLangPuts(stderr, _("Error: need hostname after \"-h\" option."));
86 		  usage();
87 		}
88 
89 		cupsSetServer(argv[i]);
90 	      }
91 	      break;
92 
93 	  default :
94 	      _cupsLangPrintf(stderr, _("%s: Unknown option \"%c\"."), argv[0], *opt);
95 	      usage();
96 	}
97       }
98     }
99     else if (!jobid && !src)
100     {
101       if (num_dests == 0)
102         num_dests = cupsGetDests(&dests);
103 
104       if ((job = strrchr(argv[i], '-')) != NULL &&
105           cupsGetDest(argv[i], NULL, num_dests, dests) == NULL)
106         jobid = atoi(job + 1);
107       else if (isdigit(argv[i][0] & 255) &&
108                !cupsGetDest(argv[i], NULL, num_dests, dests))
109         jobid = atoi(argv[i]);
110       else
111         src = argv[i];
112     }
113     else if (dest == NULL)
114       dest = argv[i];
115     else
116     {
117       _cupsLangPrintf(stderr, _("lpmove: Unknown argument \"%s\"."), argv[i]);
118       usage();
119     }
120   }
121 
122   if ((!jobid && !src) || !dest)
123     usage();
124 
125   http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption());
126 
127   if (http == NULL)
128   {
129     _cupsLangPrintf(stderr, _("lpmove: Unable to connect to server: %s"),
130 		    strerror(errno));
131     return (1);
132   }
133 
134   return (move_job(http, src, jobid, dest));
135 }
136 
137 
138 /*
139  * 'move_job()' - Move a job.
140  */
141 
142 static int				/* O - 0 on success, 1 on error */
move_job(http_t * http,const char * src,int jobid,const char * dest)143 move_job(http_t     *http,		/* I - HTTP connection to server */
144          const char *src,		/* I - Source queue */
145          int        jobid,		/* I - Job ID */
146 	 const char *dest)		/* I - Destination queue */
147 {
148   ipp_t	*request;			/* IPP Request */
149   char	job_uri[HTTP_MAX_URI],		/* job-uri */
150 	printer_uri[HTTP_MAX_URI];	/* job-printer-uri */
151 
152 
153   if (!http)
154     return (1);
155 
156  /*
157   * Build a CUPS_MOVE_JOB request, which requires the following
158   * attributes:
159   *
160   *    attributes-charset
161   *    attributes-natural-language
162   *    job-uri/printer-uri
163   *    job-printer-uri
164   *    requesting-user-name
165   */
166 
167   request = ippNewRequest(CUPS_MOVE_JOB);
168 
169   if (jobid)
170   {
171     snprintf(job_uri, sizeof(job_uri), "ipp://localhost/jobs/%d", jobid);
172     ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL,
173         	 job_uri);
174   }
175   else
176   {
177     httpAssembleURIf(HTTP_URI_CODING_ALL, job_uri, sizeof(job_uri), "ipp", NULL,
178                      "localhost", 0, "/printers/%s", src);
179     ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL,
180         	 job_uri);
181   }
182 
183   ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
184                NULL, cupsUser());
185 
186   httpAssembleURIf(HTTP_URI_CODING_ALL, printer_uri, sizeof(printer_uri),
187                    "ipp", NULL, "localhost", 0, "/printers/%s", dest);
188   ippAddString(request, IPP_TAG_JOB, IPP_TAG_URI, "job-printer-uri",
189                NULL, printer_uri);
190 
191  /*
192   * Do the request and get back a response...
193   */
194 
195   ippDelete(cupsDoRequest(http, request, "/jobs"));
196 
197   if (cupsLastError() > IPP_OK_CONFLICT)
198   {
199     _cupsLangPrintf(stderr, "lpmove: %s", cupsLastErrorString());
200     return (1);
201   }
202   else
203     return (0);
204 }
205 
206 
207 /*
208  * 'usage()' - Show program usage and exit.
209  */
210 
211 static void
usage(void)212 usage(void)
213 {
214   _cupsLangPuts(stdout, _("Usage: lpmove [options] job destination\n"
215                           "       lpmove [options] source-destination destination"));
216   _cupsLangPuts(stdout, _("Options:"));
217   _cupsLangPuts(stdout, _("-E                      Encrypt the connection to the server"));
218   _cupsLangPuts(stdout, _("-h server[:port]        Connect to the named server and port"));
219   _cupsLangPuts(stdout, _("-U username             Specify the username to use for authentication"));
220 
221   exit(1);
222 }
223