1 /* spooler.c
2 *
3 * Copyright (C) 2008 Till Kamppeter <till.kamppeter@gmail.com>
4 * Copyright (C) 2008 Lars Karlitski (formerly Uebernickel) <lars@karlitski.net>
5 *
6 * This file is part of foomatic-rip.
7 *
8 * Foomatic-rip is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * Foomatic-rip is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the
20 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 * Boston, MA 02111-1307, USA.
22 */
23
24 #include "spooler.h"
25 #include "foomaticrip.h"
26 #include "util.h"
27 #include "options.h"
28 #include <stdlib.h>
29 #include <unistd.h>
30 #include <limits.h>
31
spooler_name(int spooler)32 const char *spooler_name(int spooler)
33 {
34 switch (spooler) {
35 case SPOOLER_CUPS: return "cups";
36 case SPOOLER_DIRECT: return "direct";
37 };
38 return "<unknown>";
39 }
40
init_cups(list_t * arglist,dstr_t * filelist,jobparams_t * job)41 void init_cups(list_t *arglist, dstr_t *filelist, jobparams_t *job)
42 {
43 char path [PATH_MAX] = "";
44 char cups_jobid [128];
45 char cups_user [128];
46 char cups_jobtitle [2048];
47 char cups_copies [128];
48 int cups_options_len;
49 char *cups_options;
50 const char *pname;
51 char cups_filename [256];
52
53 if (getenv("CUPS_FONTPATH"))
54 strncpy(path, getenv("CUPS_FONTPATH"), PATH_MAX - 1);
55 else if (getenv("CUPS_DATADIR")) {
56 strncpy(path, getenv("CUPS_DATADIR"), PATH_MAX - 1);
57 strncat(path, "/fonts", PATH_MAX - strlen(path) - 1);
58 }
59 if (getenv("GS_LIB")) {
60 strncat(path, ":", PATH_MAX - strlen(path) - 1);
61 strncat(path, getenv("GS_LIB"), PATH_MAX - strlen(path) - 1);
62 }
63 setenv("GS_LIB", path, 1);
64
65 /* Get all command line parameters */
66 strncpy_omit(cups_jobid, arglist_get(arglist, 0), 128, omit_shellescapes);
67 strncpy_omit(cups_user, arglist_get(arglist, 1), 128, omit_shellescapes);
68 strncpy_omit(cups_jobtitle, arglist_get(arglist, 2), 2048,
69 omit_shellescapes);
70 strncpy_omit(cups_copies, arglist_get(arglist, 3), 128, omit_shellescapes);
71
72 cups_options_len = strlen(arglist_get(arglist, 4));
73 cups_options = malloc(cups_options_len + 1);
74 strncpy_omit(cups_options, arglist_get(arglist, 4), cups_options_len + 1,
75 omit_shellescapes);
76
77 /* Common job parameters */
78 strcpy(job->id, cups_jobid);
79 strcpy(job->title, cups_jobtitle);
80 strcpy(job->user, cups_user);
81 strcpy(job->copies, cups_copies);
82 dstrcatf(job->optstr, " %s", cups_options);
83
84 /* Check for and handle inputfile vs stdin */
85 if (list_item_count(arglist) > 4) {
86 strncpy_omit(cups_filename, arglist_get(arglist, 5), 256, omit_shellescapes);
87 if (cups_filename[0] != '-') {
88 /* We get input from a file */
89 dstrcatf(filelist, "%s ", cups_filename);
90 _log("Getting input from file %s\n", cups_filename);
91 }
92 }
93
94 /* On which queue are we printing?
95 CUPS puts the print queue name into the PRINTER environment variable
96 when calling filters. */
97 pname = getenv("PRINTER");
98 if (pname == NULL)
99 pname = "unknown";
100 strncpy(job->printer, pname, 256);
101 job->printer[255] = '\0';
102
103 free(cups_options);
104 }
105
106 /* used by init_direct to find a ppd file */
find_ppdfile(const char * user_default_path,jobparams_t * job)107 int find_ppdfile(const char *user_default_path, jobparams_t *job)
108 {
109 /* Search also common spooler-specific locations, this way a printer
110 configured under a certain spooler can also be used without spooler */
111
112 strcpy(job->ppdfile, job->printer);
113 if (access(job->ppdfile, R_OK) == 0)
114 return 1;
115
116 snprintf(job->ppdfile, 2048, "%s.ppd", job->printer); /* current dir */
117 if (access(job->ppdfile, R_OK) == 0)
118 return 1;
119 snprintf(job->ppdfile, 2048, "%s/%s.ppd", user_default_path, job->printer); /* user dir */
120 if (access(job->ppdfile, R_OK) == 0)
121 return 1;
122 snprintf(job->ppdfile, 2048, "%s/direct/%s.ppd", CONFIG_PATH, job->printer); /* system dir */
123 if (access(job->ppdfile, R_OK) == 0)
124 return 1;
125 snprintf(job->ppdfile, 2048, "%s/%s.ppd", CONFIG_PATH, job->printer); /* system dir */
126 if (access(job->ppdfile, R_OK) == 0)
127 return 1;
128 snprintf(job->ppdfile, 2048, "/etc/cups/ppd/%s.ppd", job->printer); /* CUPS config dir */
129 if (access(job->ppdfile, R_OK) == 0)
130 return 1;
131 snprintf(job->ppdfile, 2048, "/usr/local/etc/cups/ppd/%s.ppd", job->printer); /* CUPS config dir */
132 if (access(job->ppdfile, R_OK) == 0)
133 return 1;
134
135 /* nothing found */
136 job->ppdfile[0] = '\0';
137 return 0;
138 }
139
140 /* search 'configfile' for 'key', copy value into dest, return success */
configfile_find_option(const char * configfile,const char * key,char * dest,size_t destsize)141 int configfile_find_option(const char *configfile, const char *key, char *dest, size_t destsize)
142 {
143 FILE *fh;
144 char line [1024];
145 char *p;
146
147 dest[0] = '\0';
148
149 if (!(fh = fopen(configfile, "r")))
150 return 0;
151
152 while (fgets(line, 1024, fh)) {
153 if (!prefixcmp(line, "default")) {
154 p = strchr(line, ':');
155 if (p) {
156 strncpy_omit(dest, p + 1, destsize, omit_whitespace_newline);
157 if (dest[0])
158 break;
159 }
160 }
161 }
162 fclose(fh);
163 return dest[0] != '\0';
164 }
165
166 /* tries to find a default printer name in various config files and copies the
167 * result into the global var 'printer'. Returns success */
find_default_printer(const char * user_default_path,jobparams_t * job)168 int find_default_printer(const char *user_default_path, jobparams_t *job)
169 {
170 char configfile [1024];
171 char *key = "default";
172
173 if (configfile_find_option("./.directconfig", key, job->printer, 256))
174 return 1;
175 if (configfile_find_option("./directconfig", key, job->printer, 256))
176 return 1;
177 if (configfile_find_option("./.config", key, job->printer, 256))
178 return 1;
179 strlcpy(configfile, user_default_path, 1024);
180 strlcat(configfile, "/direct/.config", 1024);
181 if (configfile_find_option(configfile, key, job->printer, 256))
182 return 1;
183 strlcpy(configfile, user_default_path, 1024);
184 strlcat(configfile, "/direct.conf", 1024);
185 if (configfile_find_option(configfile, key, job->printer, 256))
186 return 1;
187 if (configfile_find_option(CONFIG_PATH "/direct/.config", key, job->printer, 256))
188 return 1;
189 if (configfile_find_option(CONFIG_PATH "/direct.conf", key, job->printer, 256))
190 return 1;
191
192 return 0;
193 }
194
init_direct(list_t * arglist,dstr_t * filelist,jobparams_t * job)195 void init_direct(list_t *arglist, dstr_t *filelist, jobparams_t *job)
196 {
197 char tmp [1024];
198 listitem_t *i;
199 char user_default_path [PATH_MAX];
200
201 strlcpy(user_default_path, getenv("HOME"), 256);
202 strlcat(user_default_path, "/.foomatic/", 256);
203
204 /* Which files do we want to print? */
205 for (i = arglist->first; i; i = i->next) {
206 strncpy_omit(tmp, (char*)i->data, 1024, omit_shellescapes);
207 dstrcatf(filelist, "%s ", tmp);
208 }
209
210 if (job->ppdfile[0] == '\0') {
211 if (job->printer[0] == '\0') {
212 /* No printer definition file selected, check whether we have a
213 default printer defined */
214 find_default_printer(user_default_path, job);
215 }
216
217 /* Neither in a config file nor on the command line a printer was selected */
218 if (!job->printer[0]) {
219 _log("No printer definition (option \"-P <name>\") specified!\n");
220 exit(EXIT_PRNERR_NORETRY_BAD_SETTINGS);
221 }
222
223 /* Search for the PPD file */
224 if (!find_ppdfile(user_default_path, job)) {
225 _log("There is no readable PPD file for the printer %s, is it configured?\n", job->printer);
226 exit(EXIT_PRNERR_NORETRY_BAD_SETTINGS);
227 }
228 }
229 }
230
231