]> andersk Git - moira.git/blob - gen/cups-print.pc
Samba queues, browsing changes.
[moira.git] / gen / cups-print.pc
1 /* $Id$
2  *
3  * This generates printcaps and other files for Athena print servers
4  *
5  * Copyright (C) 1992-1998 by the Massachusetts Institute of Technology.
6  * For copying and distribution information, please see the file
7  * <mit-copyright.h>.
8  */
9
10 #include <mit-copyright.h>
11 #include <moira.h>
12 #include <moira_site.h>
13
14 #include <sys/stat.h>
15 #include <sys/types.h>
16
17 #include <ctype.h>
18 #include <stdio.h>
19 #include <string.h>
20
21 #include <time.h>
22 #ifdef HAVE_KRB4
23 #include <krb.h>
24 #endif
25 #include <krb5.h>
26
27 #include "util.h"
28
29 EXEC SQL INCLUDE sqlca;
30
31 RCSID("$Header$");
32
33 char *whoami = "cups-print.gen";
34 char *db = "moira/moira";
35
36 /* OMG, I hate this, but it's cleaner, I guess? */
37
38 const char *alterjob = "<Limit Hold-Job Release-Job\
39  Restart-Job Purge-Jobs Reprocess-Job Set-Job-Attributes\
40  Cancel-Current-Job Suspend-Current-Job Resume-Job CUPS-Move-Job>";
41 const char *submitjob = "<Limit Create-Job Print-Job Print-URI Send-Document\
42  Set-Job-Attributes Send-URI Create-Job-Subscription Renew-Subscription\
43  Cancel-Subscription Get-Notifications CUPS-Move-Job>";
44 const char *alterpntr = "<Limit CUPS-Add-Modify-Printer CUPS-Delete-Printer\
45  CUPS-Add-Modify-Class CUPS-Delete-Class CUPS-Set-Default>";
46 const char *lpcpntr = "<Limit Pause-Printer Resume-Printer Enable-Printer\
47  Disable-Printer Pause-Printer-After-Current-Job Hold-New-Jobs\
48  Release-Held-New-Jobs Deactivate-Printer Activate-Printer Restart-Printer\
49  Shutdown-Printer Startup-Printer Promote-Job Schedule-Job-After\
50  CUPS-Accept-Jobs CUPS-Reject-Jobs>";
51 const char *canceljob = "<Limit Cancel-Job CUPS-Authenticate-Job>";
52 const char *catchall = "<Limit All>";
53
54 void do_host(char *host);
55 void sqlerr(void);
56 #ifndef MAX
57 #define MAX(a, b) ( (a) > (b) ? (a) : (b) )
58 #endif
59
60 int main(int argc, char **argv)
61 {
62   EXEC SQL BEGIN DECLARE SECTION;
63   char name[MACHINE_NAME_SIZE];
64   EXEC SQL END DECLARE SECTION;
65
66   init_acls();
67
68   EXEC SQL CONNECT :db;
69
70   EXEC SQL WHENEVER SQLERROR DO sqlerr();
71
72   EXEC SQL DECLARE csr_hosts CURSOR FOR
73     SELECT m.name FROM machine m, serverhosts sh
74     WHERE m.mach_id = sh.mach_id AND sh.service = 'CUPS-PRINT' AND sh.enable = 1;
75   EXEC SQL OPEN csr_hosts;
76   while (1)
77     {
78       EXEC SQL FETCH csr_hosts INTO :name;
79       if (sqlca.sqlcode)
80         break;
81
82       strtrim(name);
83       do_host(name);
84     }
85   EXEC SQL CLOSE csr_hosts;
86
87   exit(MR_SUCCESS);
88 }
89
90 void printer_user_list(FILE *out, char *type, int id, char *str)
91 {
92   struct save_queue *sq;
93   struct imember *m;
94
95   sq = get_acl(type, id, NULL);
96   while (sq_remove_data(sq, &m))
97     {
98       if (m->type == 'U')
99         fprintf(out, "%s %s\n", str, m->name);
100       freeimember(m);
101     }
102   sq_destroy(sq);
103 }
104
105
106
107 void do_host(char *host)
108 {
109   EXEC SQL BEGIN DECLARE SECTION;
110   char rp[PRINTERS_RP_SIZE], name[PRINTERS_NAME_SIZE];
111   char duplexname[PRINTERS_DUPLEXNAME_SIZE], location[PRINTERS_LOCATION_SIZE];
112   char hwtype[PRINTERS_HWTYPE_SIZE], lowerhwtype[PRINTERS_HWTYPE_SIZE];
113   char modtime[PRINTERS_MODTIME_SIZE], lmodtime[LIST_MODTIME_SIZE];
114   char contact[PRINTERS_CONTACT_SIZE], hostname[MACHINE_NAME_SIZE];
115   char cupshosts[MACHINE_NAME_SIZE], prtype [PRINTERS_TYPE_SIZE];
116   char *spoolhost = host, *unixtime_fmt = UNIXTIME_FMT, *p;
117   char *lhost;
118   int ka, pc, ac, lpc_acl, top_lpc_acl, banner, rm;
119   EXEC SQL END DECLARE SECTION;
120   TARFILE *tf;
121   FILE *out;
122   char filename[MAXPATHLEN], *duptc;
123   time_t mtime, now = time(NULL);
124
125   lhost = (char *) strdup (host);
126   for (p = lhost; *p; p++)
127      *p = tolower(*p);
128
129   EXEC SQL SELECT mach_id INTO :rm FROM machine
130     WHERE name = :spoolhost;
131
132   sprintf(filename, "%s/cups-print/%s", DCM_DIR, host);
133   tf = tarfile_open(filename);
134
135   /* printers.conf */
136   out = tarfile_start(tf, "/etc/cups/printers.conf", 0644, 0, 0,
137                       "root", "lp", now);
138
139   EXEC SQL DECLARE csr_printers CURSOR FOR
140     SELECT pr.rp, pr.name, pr.duplexname, pr.hwtype,
141     m.name, pr.banner, pr.location, pr.contact, pr.ka,
142     pr.ac
143     FROM printers pr, machine m
144     WHERE pr.rm = :rm AND m.mach_id = pr.mach_id
145     AND pr.type != 'ALIAS';
146   EXEC SQL OPEN csr_printers;
147   while (1)
148     {
149       EXEC SQL FETCH csr_printers INTO :rp, :name, :duplexname,
150         :hwtype, :hostname, :banner, :location, :contact, :ka, :ac;
151       if (sqlca.sqlcode)
152         break;
153
154       strtrim(rp);
155       strtrim(name);
156       strtrim(duplexname);
157       strtrim(hwtype);
158       strtrim(hostname);
159       strtrim(location);
160       strtrim(contact);
161       strcpy(lowerhwtype, hwtype);
162       for (p = lowerhwtype; *p; p++)
163         *p = tolower(*p);
164
165       fprintf(out, "<Printer %s>\n",rp);
166       fprintf(out, "Info %s:%s\n", rp, hwtype);
167       /* Note the use of "beh" to keep the CUPS from disabling print queues
168        * should they not respond versus discarding the job.  
169        * See the "beh" page for details.  
170        * The 1/0/60 says "don't disable/try 20 times/try every 60s */
171       if (!strncmp(hwtype, "HP", 2)) 
172           fprintf(out, "DeviceURI beh:/1/20/60/socket://%s:9100\n", hostname);
173       else
174           fprintf(out, "DeviceURI beh:/1/20/60/socket://%s\n", hostname);
175       fprintf(out, "State Idle\n");     // Always with the Idle
176       fprintf(out, "StateTime %ld\n", (long)time(NULL));
177       fprintf(out, "Accepting Yes\n");
178       fprintf(out, "Shared Yes\n");
179       fprintf(out, "QuotaPeriod 0\n");
180       fprintf(out, "PageLimit 0\n");
181       fprintf(out, "Klimit 0\n");
182       fprintf(out, "Option sides one-sided\n");
183       if (location[0])
184         fprintf(out, "Location %s\n", location);
185       fprintf(out, "ErrorPolicy abort-job\n");
186       if (! ka || ! lpc_acl)
187         fprintf(out, "OpPolicy default\n");
188       else
189         fprintf(out, "OpPolicy %s-policy\n", rp);
190
191       /* Access-control list. */
192       if (ac)
193         {
194           if (ka)
195             fprintf(out, "AuthType Negotiate\n");
196           else
197             fprintf(out, "AuthType Negotiate\n");
198           printer_user_list(out, "LIST", ac, "AllowUser");
199         }
200
201       if (banner == PRN_BANNER_NONE)
202         fprintf(out, "JobSheets none none\n");
203       else 
204         fprintf(out, "JobSheets athena none\n");
205       fprintf(out, "</Printer>\n");
206
207     }
208   EXEC SQL CLOSE csr_printers;
209   tarfile_end(tf);
210
211
212   /* aliases are in classes.conf */
213   out = tarfile_start(tf, "/etc/cups/classes.conf", 0644, 0, 0,
214                       "root", "root", now);
215   EXEC SQL DECLARE csr_duplexqs CURSOR FOR
216     SELECT pr.rp, pr.name, pr.duplexname, pr.hwtype,
217     m.name, pr.banner, pr.location, pr.contact, pr.ka, 
218     pr.type as prtype, pr.ac
219     FROM printers pr, machine m
220     WHERE pr.rm = :rm AND m.mach_id = pr.mach_id;
221   EXEC SQL OPEN csr_duplexqs;
222   while (1)
223     {
224       EXEC SQL FETCH csr_duplexqs INTO :rp, :name, :duplexname,
225         :hwtype, :hostname, :banner, :location, :contact, :ka, :prtype, :ac;
226       if (sqlca.sqlcode)
227         break;
228
229       strtrim(hwtype);
230       strtrim(rp);
231       strtrim(location);
232       strtrim(contact);
233       strtrim(prtype);
234
235       /* Define alias queues as classes to the regular queues for
236        * accounting reasons.  Annoyingly, classes don't always inherit
237        * their printer definitions.
238       */
239       if (!strcmp(prtype,"ALIAS")) 
240         {
241           strtrim(name);
242           fprintf(out, "<Class %s>\n",name);
243           fprintf(out, "Info Alias Queue to %s:%s\n", rp, hwtype);
244           fprintf(out, "Printer %s\n", rp);
245           fprintf(out, "Option sides one-sided\n");
246           fprintf(out, "State Idle\n");     // Always with the Idle
247           fprintf(out, "StateTime %ld\n", (long)time(NULL));
248           fprintf(out, "Accepting Yes\n");
249           fprintf(out, "Shared Yes\n");
250           fprintf(out, "QuotaPeriod 0\n");
251           fprintf(out, "PageLimit 0\n");
252           if (location[0])
253             fprintf(out, "Location %s\n", location);
254           fprintf(out, "ErrorPolicy abort-job\n");
255           if (! ka || ! lpc_acl)
256             fprintf(out, "OpPolicy default\n");
257           else
258             fprintf(out, "OpPolicy %s-policy\n", rp);
259     
260           /* Access-control list. */
261           if (ac)
262             {
263               if (ka)
264                 fprintf(out, "AuthType Negotiate\n");
265               else
266                 fprintf(out, "AuthType Negotiate\n");
267               printer_user_list(out, "LIST", ac, "AllowUser");
268             }
269     
270           if (banner == PRN_BANNER_NONE)
271             fprintf(out, "JobSheets none none\n");
272           else 
273             fprintf(out, "JobSheets athena none\n");
274           fprintf(out, "</Class>\n");
275       }
276
277       /* Define duplex queues as aliases to the regular queues for
278        * accounting reasons.  Annoyingly, classes don't always inherit
279        * their printer definitions.
280       */
281       if (*duplexname)
282         {
283           strtrim(duplexname);
284           fprintf(out, "<Class %s>\n",duplexname);
285           if (!strcmp(prtype,"ALIAS")) 
286             fprintf(out, "Info Duplex Alias Queue to %s:%s\n", rp, hwtype);
287           else
288             fprintf(out, "Info Duplex Queue for %s:%s\n", rp, hwtype);
289           fprintf(out, "Option sides two-sided-long-edge\n");   // duplex
290           fprintf(out, "Printer %s\n", rp);
291           fprintf(out, "State Idle\n");     // Always with the Idle
292           fprintf(out, "StateTime %ld\n", (long)time(NULL));
293           fprintf(out, "Accepting Yes\n");
294           fprintf(out, "Shared Yes\n");
295           fprintf(out, "QuotaPeriod 0\n");
296           fprintf(out, "PageLimit 0\n");
297           if (location[0])
298             fprintf(out, "Location %s\n", location);
299           fprintf(out, "ErrorPolicy abort-job\n");
300           if (! ka || ! lpc_acl)
301             fprintf(out, "OpPolicy default\n");
302           else
303             fprintf(out, "OpPolicy %s-policy\n", rp);
304     
305           /* Access-control list. */
306           if (ac)
307             {
308               if (ka)
309                 fprintf(out, "AuthType Negotiate\n");
310               else
311                 fprintf(out, "AuthType Negotiate\n");
312               printer_user_list(out, "LIST", ac, "AllowUser");
313             }
314     
315           if (banner == PRN_BANNER_NONE)
316             fprintf(out, "JobSheets none none\n");
317           else if (banner == PRN_BANNER_LAST)
318             fprintf(out, "JobSheets athena none\n");
319           fprintf(out, "</Class>\n");
320         }
321     }
322   EXEC SQL CLOSE csr_duplexqs;
323   tarfile_end(tf);
324
325   /* cups.conf */
326   out = tarfile_start(tf, "/etc/cups/cupsd.conf", 0755, 1, 1,
327                       "root", "lp", now);
328
329   fprintf(out, "LogLevel info\n");
330   fprintf(out, "SystemGroup sys root ops-group\n");
331   fprintf(out, "Port 631\n");
332   fprintf(out, "Listen /var/run/cups/cups.sock\n");
333   fprintf(out, "Browsing On\n");
334   fprintf(out, "BrowseOrder allow,deny\n");
335   fprintf(out, "BrowseAllow all\n");
336   fprintf(out, "BrowseAddress @LOCAL\n");
337   fprintf(out, "DefaultAuthType Negotiate\n");
338   fprintf(out, "ServerCertificate /etc/cups/ssl/%s-ipp-crt.pem\n", lhost);
339   fprintf(out, "ServerKey /etc/cups/ssl/%s-ipp-key.pem\n", lhost);
340   fprintf(out, "ServerName %s\n", lhost);
341   fprintf(out, "Krb5Keytab /etc/krb5-ipp.keytab\n");
342   /* fprintf(out, "Browsing On\n"); */
343   /* fprintf(out, "BrowseProtocols cups\n"); */
344
345   /* The other CUPS servers should be aware of the other hosts'
346      queues, so we'll let them browse each other. */
347   fprintf(out, "Include cups.local.conf\n");
348   fprintf(out, "Include cups.hosts.conf\n");
349   fprintf(out, "Include cups.locations.conf\n");
350   fprintf(out, "Include cups.policies.conf\n");
351   tarfile_end(tf);
352
353   /* cups.hosts.conf */
354   out = tarfile_start(tf, "/etc/cups/cups.hosts.conf", 0755, 1, 1,
355                       "root", "lp", now);
356   EXEC SQL DECLARE csr_cupshosts CURSOR FOR
357     SELECT m.name AS cupshosts FROM machine m, printservers ps
358     WHERE m.mach_id = ps.mach_id AND ps.kind = 'CUPS';
359   EXEC SQL OPEN csr_cupshosts;
360   while (1)
361     {
362       EXEC SQL FETCH csr_cupshosts INTO :cupshosts;
363       if (sqlca.sqlcode)
364         break;
365
366       strtrim(cupshosts);
367
368       /* Don't poll yourself looking for answers! */
369       if (strcmp(cupshosts,host))
370          fprintf(out, "BrowsePoll %s\n", cupshosts);
371     }
372   EXEC SQL CLOSE csr_cupshosts;
373
374   tarfile_end(tf);
375
376   /* cups.policies.conf */
377   out = tarfile_start(tf, "/etc/cups/cups.policies.conf", 0755, 1, 1,
378                       "root", "lp", now);
379   fprintf(out, "# Printer-specific LPC and LPR ACLs\n");
380   /* lpcaccess.top */
381   EXEC SQL SELECT ps.lpc_acl INTO :top_lpc_acl
382     FROM printservers ps, machine m
383     WHERE m.name = :spoolhost AND m.mach_id = ps.mach_id;
384   if (!sqlca.sqlcode && lpc_acl)
385     {
386       fprintf (out, "<Policy default>\n");
387       fprintf (out, "%s\n", alterjob);
388       fprintf (out, "AuthType Default\n");
389       fprintf (out, "Require user @OWNER @SYSTEM\n");
390       printer_user_list(out, "LIST", top_lpc_acl, "Require user");
391       fprintf (out, "Order deny,allow\n");
392       fprintf (out, "</Limit>\n");
393       fprintf (out, "%s\n", submitjob);
394       fprintf (out, "AuthType None\n");
395       fprintf (out, "Order deny,allow\n");
396       fprintf (out, "Allow from all\n");
397       fprintf (out, "</Limit>\n");
398       fprintf (out, "%s\n", alterpntr);
399       fprintf (out, "AuthType Default\n");
400       fprintf (out, "Require user @SYSTEM\n");
401       fprintf (out, "Order deny,allow\n");
402       fprintf (out, "</Limit>\n");
403       fprintf (out, "%s\n", lpcpntr);
404       fprintf (out, "AuthType Default\n");
405       fprintf (out, "Require user @SYSTEM\n");
406       printer_user_list(out, "LIST", top_lpc_acl, "Require user");
407       fprintf (out, "Order deny,allow\n");
408       fprintf (out, "</Limit>\n");
409       fprintf (out, "%s\n", canceljob);
410       fprintf (out, "AuthType Default\n");
411       fprintf (out, "Require user @OWNER @SYSTEM\n");
412       printer_user_list(out, "LIST", top_lpc_acl, "Require user");
413       fprintf (out, "Order deny,allow\n");
414       fprintf (out, "Allow from all\n");
415       fprintf (out, "</Limit>\n");
416       fprintf (out, "%s\n", catchall);
417       fprintf (out, "AuthType None\n");
418       fprintf (out, "Order deny,allow\n");
419       fprintf (out, "Allow from all\n");
420       fprintf (out, "</Limit>\n");
421       fprintf (out, "</Policy>\n");
422     }
423
424   /* restrict lists and lpcaccess policies.  Sadly, we have to put the
425      top level for each new policy since CUPS doesn't have a way of 
426      doing it otherwise (well, Unix groups, but not moira) */
427   EXEC SQL DECLARE csr_lpc CURSOR FOR
428     SELECT UNIQUE rp, ka, ac, lpc_acl
429     FROM printers
430     WHERE rm = :rm AND ( ac != 0 OR lpc_acl != 0);
431   EXEC SQL OPEN csr_lpc;
432   while (1)
433     {
434       EXEC SQL FETCH csr_lpc INTO :name, :ka, :ac, :lpc_acl;
435       if (sqlca.sqlcode)
436         break;
437
438       strtrim(name);
439
440       fprintf (out, "<Policy %s-policy>\n", name);
441       fprintf (out, "%s\n", alterjob);
442       fprintf (out, "AuthType Default\n");
443       fprintf (out, "Require user @OWNER @SYSTEM\n");
444       printer_user_list(out, "LIST", lpc_acl, "Require user");
445       fprintf (out, "Order deny,allow\n");
446       fprintf (out, "Allow from all\n");
447       fprintf (out, "</Limit>\n");
448       fprintf (out, "%s\n", submitjob);
449       /* If the printer is Kerberized? */
450       if (ka)
451         fprintf (out, "AuthType Negotiate\n");
452       else
453         fprintf (out, "AuthType None\n");
454       /* Access-control list. */
455       if (ac)
456         printer_user_list(out, "LIST", ac, "Require user");
457       else if (ka)
458         fprintf (out, "Require valid-user\n");
459       fprintf (out, "Order deny,allow\n");
460       fprintf (out, "Allow from all\n");
461       fprintf (out, "</Limit>\n");
462       fprintf (out, "%s\n", alterpntr);
463       fprintf (out, "AuthType Default\n");
464       fprintf (out, "Require user @SYSTEM\n");
465       fprintf (out, "Order deny,allow\n");
466       fprintf (out, "</Limit>\n");
467       fprintf (out, "%s\n", lpcpntr);
468       fprintf (out, "AuthType Default\n");
469       fprintf (out, "Require user @SYSTEM\n");
470       /* printer-specific lpc access. */
471       if (lpc_acl)
472           printer_user_list(out, "LIST", lpc_acl, "Require user");
473       printer_user_list(out, "LIST", top_lpc_acl, "Require user");
474       fprintf (out, "Order deny,allow\n");
475       fprintf (out, "</Limit>\n");
476       fprintf (out, "%s\n", canceljob);
477       fprintf (out, "AuthType Default\n");
478       fprintf (out, "Require user @OWNER @SYSTEM\n");
479       printer_user_list(out, "LIST", lpc_acl, "Require user");
480       printer_user_list(out, "LIST", top_lpc_acl, "Require user");
481       fprintf (out, "Order deny,allow\n");
482       fprintf (out, "Allow from all\n");
483       fprintf (out, "</Limit>\n");
484       fprintf (out, "%s\n", catchall);
485       fprintf (out, "AuthType None\n");
486       fprintf (out, "Order deny,allow\n");
487       fprintf (out, "Allow from all\n");
488       fprintf (out, "</Limit>\n");
489       fprintf (out, "</Policy>\n");
490     }
491   EXEC SQL CLOSE csr_lpc;
492   fprintf(out, "\n");
493   tarfile_end(tf);
494   tarfile_close(tf);
495 }
496
497 void sqlerr(void)
498 {
499   db_error(sqlca.sqlcode);
500 }
This page took 0.075959 seconds and 5 git commands to generate.