-/* $Id$\r
- *\r
- * This generates printcaps and other files for Athena print servers\r
- *\r
- * Copyright (C) 1992-1998 by the Massachusetts Institute of Technology.\r
- * For copying and distribution information, please see the file\r
- * <mit-copyright.h>.\r
- */\r
-\r
-#include <mit-copyright.h>\r
-#include <moira.h>\r
-#include <moira_site.h>\r
-\r
-#include <sys/stat.h>\r
-#include <sys/types.h>\r
-\r
-#include <ctype.h>\r
-#include <stdio.h>\r
-#include <string.h>\r
-\r
-#include <time.h>\r
-#ifdef HAVE_KRB4\r
-#include <krb.h>\r
-#endif\r
-#include <krb5.h>\r
-\r
-#include "util.h"\r
-\r
-EXEC SQL INCLUDE sqlca;\r
-\r
-RCSID("$Header$");\r
-\r
-char *whoami = "cups-print.gen";\r
-char *db = "moira/moira";\r
-\r
-const int krbvers = 5; /* use Kerberos 5 */\r
-\r
-/* OMG, I hate this, but it's cleaner, I guess? */\r
-\r
-const char *alterjob = "<Limit Hold-Job Release-Job\\r
- Restart-Job Purge-Jobs Reprocess-Job Set-Job-Attributes\\r
- Cancel-Current-Job Suspend-Current-Job Resume-Job CUPS-Move-Job>";\r
-const char *submitjob = "<Limit Create-Job Print-Job Print-URI Send-Document\\r
- Set-Job-Attributes Send-URI Create-Job-Subscription Renew-Subscription\\r
- Cancel-Subscription Get-Notifications CUPS-Move-Job>";\r
-const char *alterpntr = "<Limit CUPS-Add-Modify-Printer CUPS-Delete-Printer\\r
- CUPS-Add-Modify-Class CUPS-Delete-Class CUPS-Set-Default>";\r
-const char *lpcpntr = "<Limit Pause-Printer Resume-Printer Enable-Printer\\r
- Disable-Printer Pause-Printer-After-Current-Job Hold-New-Jobs\\r
- Release-Held-New-Jobs Deactivate-Printer Activate-Printer Restart-Printer\\r
- Shutdown-Printer Startup-Printer Promote-Job Schedule-Job-After\\r
- CUPS-Accept-Jobs CUPS-Reject-Jobs>";\r
-const char *canceljob = "<Limit Cancel-Job CUPS-Authenticate-Job>";\r
-const char *catchall = "<Limit All>";\r
-const char *phost = "printers.MIT.EDU";\r
-\r
-void do_host(char *host);\r
-void sqlerr(void);\r
-#ifndef MAX\r
-#define MAX(a, b) ( (a) > (b) ? (a) : (b) )\r
-#endif\r
-\r
-int main(int argc, char **argv)\r
-{\r
- EXEC SQL BEGIN DECLARE SECTION;\r
- char name[MACHINE_NAME_SIZE];\r
- EXEC SQL END DECLARE SECTION;\r
-\r
- init_acls();\r
-\r
- EXEC SQL CONNECT :db;\r
-\r
- EXEC SQL WHENEVER SQLERROR DO sqlerr();\r
-\r
- EXEC SQL DECLARE csr_hosts CURSOR FOR\r
- SELECT m.name FROM machine m, serverhosts sh\r
- WHERE m.mach_id = sh.mach_id AND sh.service = 'CUPS-CLUSTER' AND sh.enable = 1;\r
- EXEC SQL OPEN csr_hosts;\r
- while (1)\r
- {\r
- EXEC SQL FETCH csr_hosts INTO :name;\r
- if (sqlca.sqlcode)\r
- break;\r
-\r
- strtrim(name);\r
- do_host(name);\r
- }\r
- EXEC SQL CLOSE csr_hosts;\r
-\r
- exit(MR_SUCCESS);\r
-}\r
-\r
-void printer_user_list(FILE *out, char *type, int id, char *str)\r
-{\r
- struct save_queue *sq;\r
- struct imember *m;\r
- char kbuf[MAX_K_NAME_SZ];\r
- char *cp;\r
-\r
- sq = get_acl(type, id, NULL);\r
- while (sq_remove_data(sq, &m))\r
- {\r
- if (m->type != 'S' && m->type != NULL) {\r
- /* CUPS wants mmanley/root, not mmanley.root@ATHENA.MIT.EDU */\r
- canon_krb(m, krbvers, kbuf, sizeof(kbuf));\r
-\r
- /* now, take out all the @realm */\r
- for (cp=kbuf; *cp; cp++) {\r
- if (*cp == '@') *cp = '\0';\r
- }\r
- fprintf(out, "%s %s\n", str, kbuf);\r
- }\r
- freeimember(m);\r
- }\r
- sq_destroy(sq);\r
-}\r
-\r
-\r
-\r
-void do_host(char *host)\r
-{\r
- EXEC SQL BEGIN DECLARE SECTION;\r
- char rp[PRINTERS_RP_SIZE], name[PRINTERS_NAME_SIZE];\r
- char duplexname[PRINTERS_DUPLEXNAME_SIZE], location[PRINTERS_LOCATION_SIZE];\r
- char hwtype[PRINTERS_HWTYPE_SIZE], lowerhwtype[PRINTERS_HWTYPE_SIZE];\r
- char modtime[PRINTERS_MODTIME_SIZE], lmodtime[LIST_MODTIME_SIZE];\r
- char contact[PRINTERS_CONTACT_SIZE], hostname[MACHINE_NAME_SIZE];\r
- char cupshosts[MACHINE_NAME_SIZE], prtype [PRINTERS_TYPE_SIZE];\r
- char *spoolhost = host, *unixtime_fmt = UNIXTIME_FMT, *p;\r
- char *lhost;\r
- int ka, pc, ac, lpc_acl, top_lpc_acl, banner, rm;\r
- EXEC SQL END DECLARE SECTION;\r
- TARFILE *tf;\r
- FILE *out;\r
- char filename[MAXPATHLEN], *duptc;\r
- time_t mtime, now = time(NULL);\r
-\r
- lhost = (char *) strdup (host);\r
- for (p = lhost; *p; p++)\r
- *p = tolower(*p);\r
-\r
- EXEC SQL SELECT mach_id INTO :rm FROM machine\r
- WHERE name = :spoolhost;\r
-\r
- sprintf(filename, "%s/cups-cluster/%s", DCM_DIR, host);\r
- tf = tarfile_open(filename);\r
-\r
- /* printers.conf entries for locally run queues */\r
- out = tarfile_start(tf, "/etc/cups/printers.conf", 0644, 0, 0,\r
- "lp", "lp", now);\r
-\r
- EXEC SQL DECLARE csr_printers CURSOR FOR\r
- SELECT pr.rp, pr.name, pr.duplexname, pr.hwtype,\r
- m.name, pr.banner, pr.location, pr.contact, pr.ka,\r
- pr.ac, pr.lpc_acl\r
- FROM printers pr, machine m\r
- WHERE pr.rm = :rm AND m.mach_id = pr.mach_id\r
- AND (pr.type = 'DORM' or pr.type = 'CLUSTER');\r
- EXEC SQL OPEN csr_printers;\r
- while (1)\r
- {\r
- EXEC SQL FETCH csr_printers INTO :rp, :name, :duplexname,\r
- :hwtype, :hostname, :banner, :location, :contact, :ka, :ac, :lpc_acl;\r
- if (sqlca.sqlcode)\r
- break;\r
-\r
- strtrim(rp);\r
- strtrim(name);\r
- strtrim(duplexname);\r
- strtrim(hwtype);\r
- strtrim(hostname);\r
- strtrim(location);\r
- strtrim(contact);\r
- strcpy(lowerhwtype, hwtype);\r
- for (p = rp; *p; p++) /* Because uppercased printer names suck */\r
- *p = tolower(*p);\r
- for (p = lowerhwtype; *p; p++)\r
- *p = tolower(*p);\r
-\r
- fprintf(out, "<Printer %s>\n",rp);\r
- fprintf(out, "Info %s:%s\n", rp, hwtype);\r
- /* Note the use of "beh" to keep the CUPS from disabling print queues\r
- * should they not respond versus discarding the job. \r
- * See the "beh" page for details. \r
- * The 1/0/60 says "don't disable/try 20 times/try every 60s */\r
- if (!strncmp(hwtype, "HP", 2)) \r
- fprintf(out, "DeviceURI beh:/1/20/60/socket://%s:9100\n", hostname);\r
- else\r
- fprintf(out, "DeviceURI beh:/1/20/60/socket://%s\n", hostname);\r
- fprintf(out, "State Idle\n"); // Always with the Idle\r
- fprintf(out, "StateTime %ld\n", (long)time(NULL));\r
- fprintf(out, "Accepting Yes\n");\r
- fprintf(out, "Shared Yes\n");\r
- fprintf(out, "QuotaPeriod 0\n");\r
- fprintf(out, "PageLimit 0\n");\r
- fprintf(out, "Klimit 0\n");\r
- fprintf(out, "Option sides one-sided\n");\r
- fprintf(out, "Filter application/vnd.cups-raw 0 -\n");\r
- fprintf(out, "Filter application/vnd.cups-postscript 100 foomatic-rip\n");\r
- fprintf(out, "Filter application/vnd.cups-pdf 0 foomatic-rip\n");\r
- fprintf(out, "Filter application/vnd.apple-pdf 25 foomatic-rip\n");\r
- fprintf(out, "Filter application/vnd.cups-command 0 commandtops\n");\r
- if (location[0])\r
- fprintf(out, "Location %s\n", location);\r
- fprintf(out, "ErrorPolicy abort-job\n");\r
- if (ka || lpc_acl)\r
- fprintf(out, "OpPolicy %s-policy\n", rp);\r
- else\r
- fprintf(out, "OpPolicy default\n");\r
-\r
- /* Access-control list. */\r
- if (ac)\r
- {\r
- if (ka)\r
- fprintf(out, "AuthType Negotiate\n");\r
- else\r
- fprintf(out, "AuthType Default\n");\r
- printer_user_list(out, "LIST", ac, "AllowUser");\r
- }\r
-\r
- if (banner == PRN_BANNER_NONE)\r
- fprintf(out, "JobSheets none none\n");\r
- else \r
- fprintf(out, "JobSheets athena none\n");\r
- fprintf(out, "</Printer>\n");\r
-\r
- }\r
- EXEC SQL CLOSE csr_printers;\r
-\r
- /* printers.conf entries for non-local CUPS queues */\r
- EXEC SQL DECLARE csr_remote_printers CURSOR FOR\r
- SELECT pr.rp, pr.name, pr.duplexname, pr.hwtype,\r
- m.name, pr.banner, pr.location, pr.contact, pr.ka,\r
- pr.ac, pr.lpc_acl, m.name as cupshosts\r
- FROM printers pr, machine m, serverhosts sh\r
- WHERE pr.rm = m.mach_id \r
- AND (pr.type = 'CLUSTER' or pr.type = 'DORM') AND m.name <> :spoolhost AND\r
- m.mach_id = sh.mach_id AND sh.service = 'CUPS-PRINT' AND \r
- sh.enable = 1 AND m.mach_id = sh.mach_id;\r
-\r
- EXEC SQL OPEN csr_remote_printers;\r
- while (1)\r
- {\r
- EXEC SQL FETCH csr_remote_printers INTO :rp, :name, :duplexname,\r
- :hwtype, :hostname, :banner, :location, :contact, :ka, :ac, :lpc_acl, :cupshosts;\r
- if (sqlca.sqlcode)\r
- break;\r
-\r
- strtrim(rp);\r
- strtrim(name);\r
- strtrim(duplexname);\r
- strtrim(hwtype);\r
- strtrim(hostname);\r
- strtrim(location);\r
- strtrim(contact);\r
- strtrim(cupshosts);\r
- strcpy(lowerhwtype, hwtype);\r
- for (p = rp; *p; p++) /* Because uppercased printer names suck */\r
- *p = tolower(*p);\r
- for (p = lowerhwtype; *p; p++)\r
- *p = tolower(*p);\r
-\r
- fprintf(out, "<Printer %s>\n",rp);\r
- fprintf(out, "Info %s:%s\n", rp, hwtype);\r
- fprintf(out, "DeviceURI ipp://%s:631/printers/%s\n", cupshosts, rp);\r
- fprintf(out, "State Idle\n"); // Always with the Idle\r
- fprintf(out, "StateTime %ld\n", (long)time(NULL));\r
- fprintf(out, "Accepting Yes\n");\r
- fprintf(out, "Shared Yes\n");\r
- fprintf(out, "QuotaPeriod 0\n");\r
- fprintf(out, "PageLimit 0\n");\r
- fprintf(out, "Klimit 0\n");\r
- fprintf(out, "Option sides one-sided\n");\r
- fprintf(out, "Filter application/vnd.cups-raw 0 -\n");\r
- fprintf(out, "Filter application/vnd.cups-postscript 100 foomatic-rip\n");\r
- fprintf(out, "Filter application/vnd.cups-pdf 0 foomatic-rip\n");\r
- fprintf(out, "Filter application/vnd.apple-pdf 25 foomatic-rip\n");\r
- fprintf(out, "Filter application/vnd.cups-command 0 commandtops\n");\r
- if (location[0])\r
- fprintf(out, "Location %s\n", location);\r
- fprintf(out, "ErrorPolicy abort-job\n");\r
- if (ka || lpc_acl)\r
- fprintf(out, "OpPolicy %s-policy\n", rp);\r
- else\r
- fprintf(out, "OpPolicy default\n");\r
-\r
- /* Access-control list. */\r
- if (ac)\r
- {\r
- if (ka)\r
- fprintf(out, "AuthType Negotiate\n");\r
- else\r
- fprintf(out, "AuthType Default\n");\r
- printer_user_list(out, "LIST", ac, "AllowUser");\r
- }\r
-\r
- if (banner == PRN_BANNER_NONE)\r
- fprintf(out, "JobSheets none none\n");\r
- else \r
- fprintf(out, "JobSheets athena none\n");\r
- fprintf(out, "</Printer>\n");\r
-\r
- }\r
- EXEC SQL CLOSE csr_remote_printers;\r
-\r
- /* printers.conf entries for non-local LPRng queues */\r
- EXEC SQL DECLARE csr_lprng_printers CURSOR FOR\r
- SELECT pr.rp, pr.name, pr.duplexname, pr.hwtype,\r
- m.name, pr.banner, pr.location, pr.contact, pr.ka,\r
- pr.ac, pr.lpc_acl, m.name as cupshosts\r
- FROM printers pr, machine m, serverhosts sh\r
- WHERE pr.rm = m.mach_id \r
- AND (pr.type = 'DORM' or pr.type = 'CLUSTER') AND m.name <> :spoolhost AND\r
- m.mach_id = sh.mach_id AND sh.service = 'PRINT' AND \r
- sh.enable = 1;\r
-\r
- EXEC SQL OPEN csr_lprng_printers;\r
- while (1)\r
- {\r
- EXEC SQL FETCH csr_lprng_printers INTO :rp, :name, :duplexname,\r
- :hwtype, :hostname, :banner, :location, :contact, :ka, :ac, :lpc_acl, :cupshosts;\r
- if (sqlca.sqlcode)\r
- break;\r
-\r
- strtrim(rp);\r
- strtrim(name);\r
- strtrim(duplexname);\r
- strtrim(hwtype);\r
- strtrim(hostname);\r
- strtrim(location);\r
- strtrim(contact);\r
- strtrim(cupshosts);\r
- strcpy(lowerhwtype, hwtype);\r
- for (p = rp; *p; p++) /* Because uppercased printer names suck */\r
- *p = tolower(*p);\r
- for (p = lowerhwtype; *p; p++)\r
- *p = tolower(*p);\r
-\r
- fprintf(out, "<Printer %s>\n",rp);\r
- fprintf(out, "Info %s:LPRng Queue on %s\n", rp, cupshosts);\r
- fprintf(out, "DeviceURI lpd://%s/%s\n", cupshosts, rp);\r
- fprintf(out, "State Idle\n"); // Always with the Idle\r
- fprintf(out, "StateTime %ld\n", (long)time(NULL));\r
- fprintf(out, "Accepting Yes\n");\r
- fprintf(out, "Shared Yes\n");\r
- fprintf(out, "QuotaPeriod 0\n");\r
- fprintf(out, "PageLimit 0\n");\r
- fprintf(out, "Klimit 0\n");\r
- fprintf(out, "Option sides one-sided\n");\r
- fprintf(out, "Filter application/vnd.cups-raw 0 -\n");\r
- fprintf(out, "Filter application/vnd.cups-postscript 100 foomatic-rip\n");\r
- fprintf(out, "Filter application/vnd.cups-pdf 0 foomatic-rip\n");\r
- fprintf(out, "Filter application/vnd.apple-pdf 25 foomatic-rip\n");\r
- fprintf(out, "Filter application/vnd.cups-command 0 commandtops\n");\r
- if (location[0])\r
- fprintf(out, "Location %s\n", location);\r
- fprintf(out, "ErrorPolicy abort-job\n");\r
- fprintf(out, "OpPolicy default\n");\r
- fprintf(out, "JobSheets none none\n");\r
- fprintf(out, "</Printer>\n");\r
-\r
- }\r
- EXEC SQL CLOSE csr_lprng_printers;\r
- tarfile_end(tf);\r
-\r
-\r
- /* aliases are in classes.conf */\r
- out = tarfile_start(tf, "/etc/cups/classes.conf", 0644, 0, 0,\r
- "lp", "lp", now);\r
- EXEC SQL DECLARE csr_duplexqs CURSOR FOR\r
- SELECT pr.rp, pr.name, pr.duplexname, pr.hwtype,\r
- m.name, pr.banner, pr.location, pr.contact, pr.ka, \r
- pr.type as prtype, pr.ac\r
- FROM printers pr, machine m, serverhosts sh\r
- WHERE pr.rm = m.mach_id \r
- AND m.mach_id = sh.mach_id AND sh.enable = 1 \r
- AND (pr.type = 'DORM' or pr.type = 'CLUSTER')\r
- AND (sh.service = 'CUPS-PRINT' OR sh.service = 'PRINT');\r
- EXEC SQL OPEN csr_duplexqs;\r
- while (1)\r
- {\r
- EXEC SQL FETCH csr_duplexqs INTO :rp, :name, :duplexname,\r
- :hwtype, :hostname, :banner, :location, :contact, :ka, :prtype, :ac;\r
- if (sqlca.sqlcode)\r
- break;\r
-\r
- strtrim(hwtype);\r
- strtrim(rp);\r
- strtrim(location);\r
- strtrim(contact);\r
- strtrim(prtype);\r
-\r
- /* Define alias queues as classes to the regular queues for\r
- * accounting reasons. Annoyingly, classes don't always inherit\r
- * their printer definitions.\r
- */\r
- if (!strcmp(prtype,"ALIAS")) \r
- {\r
- strtrim(name);\r
- fprintf(out, "<Class %s>\n",name);\r
- fprintf(out, "Info Alias Queue to %s:%s\n", rp, hwtype);\r
- fprintf(out, "Printer %s\n", rp);\r
- fprintf(out, "Option sides one-sided\n");\r
- fprintf(out, "State Idle\n"); // Always with the Idle\r
- fprintf(out, "StateTime %ld\n", (long)time(NULL));\r
- fprintf(out, "Accepting Yes\n");\r
- fprintf(out, "Shared Yes\n");\r
- fprintf(out, "QuotaPeriod 0\n");\r
- fprintf(out, "PageLimit 0\n");\r
- if (location[0])\r
- fprintf(out, "Location %s\n", location);\r
- /* fprintf(out, "ErrorPolicy abort-job\n"); */\r
- if (ka || lpc_acl)\r
- fprintf(out, "OpPolicy %s-policy\n", rp);\r
- else\r
- fprintf(out, "OpPolicy default\n");\r
- \r
- /* Access-control list. */\r
- if (ac)\r
- {\r
- if (ka)\r
- fprintf(out, "AuthType Negotiate\n");\r
- else\r
- fprintf(out, "AuthType Default\n");\r
- printer_user_list(out, "LIST", ac, "AllowUser");\r
- }\r
- \r
- if (banner == PRN_BANNER_NONE)\r
- fprintf(out, "JobSheets none none\n");\r
- else \r
- fprintf(out, "JobSheets athena none\n");\r
- fprintf(out, "</Class>\n");\r
- }\r
-\r
- /* Define duplex queues as aliases to the regular queues for\r
- * accounting reasons. Annoyingly, classes don't always inherit\r
- * their printer definitions.\r
- */\r
- if (*duplexname)\r
- {\r
- strtrim(duplexname);\r
- fprintf(out, "<Class %s>\n",duplexname);\r
- if (!strcmp(prtype,"ALIAS")) \r
- fprintf(out, "Info Duplex Alias Queue to %s:%s\n", rp, hwtype);\r
- else\r
- fprintf(out, "Info Duplex Queue for %s:%s\n", rp, hwtype);\r
- fprintf(out, "Option sides two-sided-long-edge\n"); // duplex\r
- fprintf(out, "Printer %s\n", rp);\r
- fprintf(out, "State Idle\n"); // Always with the Idle\r
- fprintf(out, "StateTime %ld\n", (long)time(NULL));\r
- fprintf(out, "Accepting Yes\n");\r
- fprintf(out, "Shared Yes\n");\r
- fprintf(out, "QuotaPeriod 0\n");\r
- fprintf(out, "PageLimit 0\n");\r
- if (location[0])\r
- fprintf(out, "Location %s\n", location);\r
- fprintf(out, "ErrorPolicy abort-job\n");\r
- if (ka || lpc_acl)\r
- fprintf(out, "OpPolicy %s-policy\n", rp);\r
- else\r
- fprintf(out, "OpPolicy default\n");\r
- \r
- /* Access-control list. */\r
- if (ac)\r
- {\r
- if (ka)\r
- fprintf(out, "AuthType Negotiate\n");\r
- else\r
- fprintf(out, "AuthType Default\n");\r
- printer_user_list(out, "LIST", ac, "AllowUser");\r
- }\r
- \r
- if (banner == PRN_BANNER_NONE)\r
- fprintf(out, "JobSheets none none\n");\r
- else if (banner == PRN_BANNER_LAST)\r
- fprintf(out, "JobSheets athena none\n");\r
- fprintf(out, "</Class>\n");\r
- }\r
- }\r
- EXEC SQL CLOSE csr_duplexqs;\r
- tarfile_end(tf);\r
-\r
- /* cups.conf */\r
- out = tarfile_start(tf, "/etc/cups/cupsd.conf", 0755, 1, 1,\r
- "root", "lp", now);\r
-\r
- fprintf(out, "LogLevel info\n");\r
- fprintf(out, "SystemGroup sys root ops-group\n");\r
- fprintf(out, "Port 631\n");\r
- fprintf(out, "Listen /var/run/cups/cups.sock\n");\r
- fprintf(out, "Browsing On\n");\r
- fprintf(out, "BrowseOrder allow,deny\n");\r
- fprintf(out, "BrowseAllow all\n");\r
- fprintf(out, "BrowseAddress @LOCAL\n");\r
- fprintf(out, "DefaultAuthType Negotiate\n");\r
- fprintf(out, "ServerCertificate /etc/cups/ssl/%s-ipp-crt.pem\n", lhost);\r
- fprintf(out, "ServerKey /etc/cups/ssl/%s-ipp-key.pem\n", lhost);\r
- fprintf(out, "ServerName %s\n", lhost);\r
- fprintf(out, "ServerAlias %s\n", phost);\r
- fprintf(out, "Krb5Keytab /etc/krb5-ipp.keytab\n");\r
-\r
- /* The other CUPS servers should be aware of the other hosts'\r
- queues, so we'll let them browse each other. */\r
- fprintf(out, "Include cups.local.conf\n");\r
- fprintf(out, "Include cups.locations.conf\n");\r
- fprintf(out, "Include cups.policies.conf\n");\r
- tarfile_end(tf);\r
-\r
- /* cups.hosts.conf */\r
- out = tarfile_start(tf, "/etc/cups/cups.hosts.conf", 0755, 1, 1,\r
- "root", "lp", now);\r
- EXEC SQL DECLARE csr_cupshosts CURSOR FOR\r
- SELECT m.name AS cupshosts FROM machine m, printservers ps\r
- WHERE m.mach_id = ps.mach_id AND ps.kind = 'CUPS';\r
- EXEC SQL OPEN csr_cupshosts;\r
- while (1)\r
- {\r
- EXEC SQL FETCH csr_cupshosts INTO :cupshosts;\r
- if (sqlca.sqlcode)\r
- break;\r
-\r
- strtrim(cupshosts);\r
-\r
- /* Don't poll yourself looking for answers! */\r
- if (strcmp(cupshosts,host))\r
- fprintf(out, "BrowsePoll %s\n", cupshosts);\r
- }\r
- EXEC SQL CLOSE csr_cupshosts;\r
-\r
- tarfile_end(tf);\r
-\r
- /* cups.policies.conf */\r
- out = tarfile_start(tf, "/etc/cups/cups.policies.conf", 0755, 1, 1,\r
- "root", "lp", now);\r
- fprintf(out, "# Printer-specific LPC and LPR ACLs\n");\r
- /* lpcaccess.top */\r
- EXEC SQL SELECT ps.lpc_acl INTO :top_lpc_acl\r
- FROM printservers ps, machine m\r
- WHERE m.name = :spoolhost AND m.mach_id = ps.mach_id;\r
- if (!sqlca.sqlcode && lpc_acl)\r
- {\r
- fprintf (out, "<Policy default>\n");\r
- fprintf (out, "%s\n", alterjob);\r
- fprintf (out, "AuthType Default\n");\r
- fprintf (out, "Require user @OWNER @SYSTEM\n");\r
- printer_user_list(out, "LIST", top_lpc_acl, "Require user");\r
- fprintf (out, "Order deny,allow\n");\r
- fprintf (out, "</Limit>\n");\r
- fprintf (out, "%s\n", submitjob);\r
- fprintf (out, "AuthType None\n");\r
- fprintf (out, "Order deny,allow\n");\r
- fprintf (out, "Allow from all\n");\r
- fprintf (out, "</Limit>\n");\r
- fprintf (out, "%s\n", alterpntr);\r
- fprintf (out, "AuthType Default\n");\r
- fprintf (out, "Require user @SYSTEM\n");\r
- fprintf (out, "Order deny,allow\n");\r
- fprintf (out, "</Limit>\n");\r
- fprintf (out, "%s\n", lpcpntr);\r
- fprintf (out, "AuthType Default\n");\r
- fprintf (out, "Require user @SYSTEM\n");\r
- printer_user_list(out, "LIST", top_lpc_acl, "Require user");\r
- fprintf (out, "Order deny,allow\n");\r
- fprintf (out, "</Limit>\n");\r
- fprintf (out, "%s\n", canceljob);\r
- fprintf (out, "AuthType Default\n");\r
- fprintf (out, "Require user @OWNER @SYSTEM\n");\r
- printer_user_list(out, "LIST", top_lpc_acl, "Require user");\r
- fprintf (out, "Order deny,allow\n");\r
- fprintf (out, "Allow from all\n");\r
- fprintf (out, "</Limit>\n");\r
- fprintf (out, "%s\n", catchall);\r
- fprintf (out, "AuthType None\n");\r
- fprintf (out, "Order deny,allow\n");\r
- fprintf (out, "Allow from all\n");\r
- fprintf (out, "</Limit>\n");\r
- fprintf (out, "</Policy>\n");\r
- }\r
-\r
- /* restrict lists and lpcaccess policies. Sadly, we have to put the\r
- top level for each new policy since CUPS doesn't have a way of \r
- doing it otherwise (well, Unix groups, but not moira) */\r
- EXEC SQL DECLARE csr_lpc CURSOR FOR\r
- SELECT UNIQUE rp, ka, ac, lpc_acl\r
- FROM printers\r
- WHERE (ac != 0 OR lpc_acl != 0) AND rm in (SELECT m.mach_id FROM machine m, serverhosts sh\r
- WHERE m.mach_id = sh.mach_id AND sh.service = 'CUPS-PRINT' AND sh.enable = 1);\r
- EXEC SQL OPEN csr_lpc;\r
- while (1)\r
- {\r
- EXEC SQL FETCH csr_lpc INTO :name, :ka, :ac, :lpc_acl;\r
- if (sqlca.sqlcode)\r
- break;\r
-\r
- strtrim(name);\r
-\r
- fprintf (out, "<Policy %s-policy>\n", name);\r
- fprintf (out, "%s\n", alterjob);\r
- fprintf (out, "AuthType Default\n");\r
- fprintf (out, "Require user @OWNER @SYSTEM\n");\r
- printer_user_list(out, "LIST", lpc_acl, "Require user");\r
- fprintf (out, "Order deny,allow\n");\r
- fprintf (out, "Allow from all\n");\r
- fprintf (out, "</Limit>\n");\r
- fprintf (out, "%s\n", submitjob);\r
- /* If the printer is Kerberized? */\r
- if (ka)\r
- fprintf (out, "AuthType Negotiate\n");\r
- else\r
- fprintf (out, "AuthType None\n");\r
- /* Access-control list. */\r
- if (ac)\r
- printer_user_list(out, "LIST", ac, "Require user");\r
- else if (ka)\r
- fprintf (out, "Require valid-user\n");\r
- fprintf (out, "Order deny,allow\n");\r
- fprintf (out, "Allow from all\n");\r
- fprintf (out, "</Limit>\n");\r
- fprintf (out, "%s\n", alterpntr);\r
- fprintf (out, "AuthType Default\n");\r
- fprintf (out, "Require user @SYSTEM\n");\r
- fprintf (out, "Order deny,allow\n");\r
- fprintf (out, "</Limit>\n");\r
- fprintf (out, "%s\n", lpcpntr);\r
- fprintf (out, "AuthType Default\n");\r
- fprintf (out, "Require user @SYSTEM\n");\r
- /* printer-specific lpc access. */\r
- if (lpc_acl)\r
- printer_user_list(out, "LIST", lpc_acl, "Require user");\r
- printer_user_list(out, "LIST", top_lpc_acl, "Require user");\r
- fprintf (out, "Order deny,allow\n");\r
- fprintf (out, "</Limit>\n");\r
- fprintf (out, "%s\n", canceljob);\r
- fprintf (out, "AuthType Default\n");\r
- fprintf (out, "Require user @OWNER @SYSTEM\n");\r
- printer_user_list(out, "LIST", lpc_acl, "Require user");\r
- printer_user_list(out, "LIST", top_lpc_acl, "Require user");\r
- fprintf (out, "Order deny,allow\n");\r
- fprintf (out, "Allow from all\n");\r
- fprintf (out, "</Limit>\n");\r
- fprintf (out, "%s\n", catchall);\r
- fprintf (out, "AuthType None\n");\r
- fprintf (out, "Order deny,allow\n");\r
- fprintf (out, "Allow from all\n");\r
- fprintf (out, "</Limit>\n");\r
- fprintf (out, "</Policy>\n");\r
- }\r
- EXEC SQL CLOSE csr_lpc;\r
- fprintf(out, "\n");\r
- tarfile_end(tf);\r
- tarfile_close(tf);\r
-}\r
-\r
-void sqlerr(void)\r
-{\r
- db_error(sqlca.sqlcode);\r
-}\r
+/* $Id$
+ *
+ * This generates printcaps and other files for Athena print servers
+ *
+ * Copyright (C) 1992-1998 by the Massachusetts Institute of Technology.
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ */
+
+#include <mit-copyright.h>
+#include <moira.h>
+#include <moira_site.h>
+
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <ctype.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <time.h>
+#ifdef HAVE_KRB4
+#include <krb.h>
+#endif
+#include <krb5.h>
+
+#include "util.h"
+
+EXEC SQL INCLUDE sqlca;
+
+RCSID("$Header$");
+
+char *whoami = "cups-print.gen";
+char *db = "moira/moira";
+
+const int krbvers = 5; /* use Kerberos 5 */
+
+/* OMG, I hate this, but it's cleaner, I guess? */
+
+const char *alterjob = "<Limit Hold-Job Release-Job\
+ Restart-Job Purge-Jobs Reprocess-Job Set-Job-Attributes\
+ Cancel-Current-Job Suspend-Current-Job Resume-Job CUPS-Move-Job>";
+const char *submitjob = "<Limit Create-Job Print-Job Print-URI Send-Document\
+ Set-Job-Attributes Send-URI Create-Job-Subscription Renew-Subscription\
+ Cancel-Subscription Get-Notifications CUPS-Move-Job>";
+const char *alterpntr = "<Limit CUPS-Add-Modify-Printer CUPS-Delete-Printer\
+ CUPS-Add-Modify-Class CUPS-Delete-Class CUPS-Set-Default>";
+const char *lpcpntr = "<Limit Pause-Printer Resume-Printer Enable-Printer\
+ Disable-Printer Pause-Printer-After-Current-Job Hold-New-Jobs\
+ Release-Held-New-Jobs Deactivate-Printer Activate-Printer Restart-Printer\
+ Shutdown-Printer Startup-Printer Promote-Job Schedule-Job-After\
+ CUPS-Accept-Jobs CUPS-Reject-Jobs>";
+const char *canceljob = "<Limit Cancel-Job CUPS-Authenticate-Job>";
+const char *catchall = "<Limit All>";
+const char *phost = "printers.MIT.EDU";
+
+void do_host(char *host);
+void sqlerr(void);
+#ifndef MAX
+#define MAX(a, b) ( (a) > (b) ? (a) : (b) )
+#endif
+
+int main(int argc, char **argv)
+{
+ EXEC SQL BEGIN DECLARE SECTION;
+ char name[MACHINE_NAME_SIZE];
+ EXEC SQL END DECLARE SECTION;
+
+ init_acls();
+
+ EXEC SQL CONNECT :db;
+
+ EXEC SQL WHENEVER SQLERROR DO sqlerr();
+
+ EXEC SQL DECLARE csr_hosts CURSOR FOR
+ SELECT m.name FROM machine m, serverhosts sh
+ WHERE m.mach_id = sh.mach_id AND sh.service = 'CUPS-CLUSTER' AND sh.enable = 1;
+ EXEC SQL OPEN csr_hosts;
+ while (1)
+ {
+ EXEC SQL FETCH csr_hosts INTO :name;
+ if (sqlca.sqlcode)
+ break;
+
+ strtrim(name);
+ do_host(name);
+ }
+ EXEC SQL CLOSE csr_hosts;
+
+ exit(MR_SUCCESS);
+}
+
+void printer_user_list(FILE *out, char *type, int id, char *str)
+{
+ struct save_queue *sq;
+ struct imember *m;
+ char kbuf[MAX_K_NAME_SZ];
+ char *cp;
+
+ sq = get_acl(type, id, NULL);
+ while (sq_remove_data(sq, &m))
+ {
+ if (m->type != 'S' && m->type != NULL) {
+ /* CUPS wants mmanley/root, not mmanley.root@ATHENA.MIT.EDU */
+ canon_krb(m, krbvers, kbuf, sizeof(kbuf));
+
+ /* now, take out all the @realm */
+ for (cp=kbuf; *cp; cp++) {
+ if (*cp == '@') *cp = '\0';
+ }
+ fprintf(out, "%s %s\n", str, kbuf);
+ }
+ freeimember(m);
+ }
+ sq_destroy(sq);
+}
+
+
+
+void do_host(char *host)
+{
+ EXEC SQL BEGIN DECLARE SECTION;
+ char rp[PRINTERS_RP_SIZE], name[PRINTERS_NAME_SIZE];
+ char duplexname[PRINTERS_DUPLEXNAME_SIZE], location[PRINTERS_LOCATION_SIZE];
+ char hwtype[PRINTERS_HWTYPE_SIZE], lowerhwtype[PRINTERS_HWTYPE_SIZE];
+ char modtime[PRINTERS_MODTIME_SIZE], lmodtime[LIST_MODTIME_SIZE];
+ char contact[PRINTERS_CONTACT_SIZE], hostname[MACHINE_NAME_SIZE];
+ char cupshosts[MACHINE_NAME_SIZE], prtype [PRINTERS_TYPE_SIZE];
+ char *spoolhost = host, *unixtime_fmt = UNIXTIME_FMT, *p;
+ char *lhost;
+ int ka, pc, ac, lpc_acl, top_lpc_acl, banner, rm;
+ EXEC SQL END DECLARE SECTION;
+ TARFILE *tf;
+ FILE *out;
+ char filename[MAXPATHLEN], *duptc;
+ time_t mtime, now = time(NULL);
+
+ lhost = (char *) strdup (host);
+ for (p = lhost; *p; p++)
+ *p = tolower(*p);
+
+ EXEC SQL SELECT mach_id INTO :rm FROM machine
+ WHERE name = :spoolhost;
+
+ sprintf(filename, "%s/cups-cluster/%s", DCM_DIR, host);
+ tf = tarfile_open(filename);
+
+ /* printers.conf entries for locally run queues */
+ out = tarfile_start(tf, "/etc/cups/printers.conf", 0644, 0, 0,
+ "lp", "lp", now);
+
+ EXEC SQL DECLARE csr_printers CURSOR FOR
+ SELECT pr.rp, pr.name, pr.duplexname, pr.hwtype,
+ m.name, pr.banner, pr.location, pr.contact, pr.ka,
+ pr.ac, pr.lpc_acl
+ FROM printers pr, machine m
+ WHERE pr.rm = :rm AND m.mach_id = pr.mach_id
+ AND (pr.type = 'DORM' or pr.type = 'CLUSTER');
+ EXEC SQL OPEN csr_printers;
+ while (1)
+ {
+ EXEC SQL FETCH csr_printers INTO :rp, :name, :duplexname,
+ :hwtype, :hostname, :banner, :location, :contact, :ka, :ac, :lpc_acl;
+ if (sqlca.sqlcode)
+ break;
+
+ strtrim(rp);
+ strtrim(name);
+ strtrim(duplexname);
+ strtrim(hwtype);
+ strtrim(hostname);
+ strtrim(location);
+ strtrim(contact);
+ strcpy(lowerhwtype, hwtype);
+ for (p = rp; *p; p++) /* Because uppercased printer names suck */
+ *p = tolower(*p);
+ for (p = lowerhwtype; *p; p++)
+ *p = tolower(*p);
+
+ fprintf(out, "<Printer %s>\n",rp);
+ fprintf(out, "Info %s:%s\n", rp, hwtype);
+ /* Note the use of "beh" to keep the CUPS from disabling print queues
+ * should they not respond versus discarding the job.
+ * See the "beh" page for details.
+ * The 1/0/60 says "don't disable/try 20 times/try every 60s */
+ if (!strncmp(hwtype, "HP", 2))
+ fprintf(out, "DeviceURI beh:/1/20/60/socket://%s:9100\n", hostname);
+ else
+ fprintf(out, "DeviceURI beh:/1/20/60/socket://%s\n", hostname);
+ fprintf(out, "State Idle\n"); // Always with the Idle
+ fprintf(out, "StateTime %ld\n", (long)time(NULL));
+ fprintf(out, "Accepting Yes\n");
+ fprintf(out, "Shared Yes\n");
+ fprintf(out, "QuotaPeriod 0\n");
+ fprintf(out, "PageLimit 0\n");
+ fprintf(out, "Klimit 0\n");
+ fprintf(out, "Option sides one-sided\n");
+ fprintf(out, "Filter application/vnd.cups-raw 0 -\n");
+ fprintf(out, "Filter application/vnd.cups-postscript 100 foomatic-rip\n");
+ fprintf(out, "Filter application/vnd.cups-pdf 0 foomatic-rip\n");
+ fprintf(out, "Filter application/vnd.apple-pdf 25 foomatic-rip\n");
+ fprintf(out, "Filter application/vnd.cups-command 0 commandtops\n");
+ if (location[0])
+ fprintf(out, "Location %s\n", location);
+ fprintf(out, "ErrorPolicy abort-job\n");
+ if (ka || lpc_acl)
+ fprintf(out, "OpPolicy %s-policy\n", rp);
+ else
+ fprintf(out, "OpPolicy default\n");
+
+ /* Access-control list. */
+ if (ac)
+ {
+ if (ka)
+ fprintf(out, "AuthType Negotiate\n");
+ else
+ fprintf(out, "AuthType Default\n");
+ printer_user_list(out, "LIST", ac, "AllowUser");
+ }
+
+ if (banner == PRN_BANNER_NONE)
+ fprintf(out, "JobSheets none none\n");
+ else
+ fprintf(out, "JobSheets athena none\n");
+ fprintf(out, "</Printer>\n");
+
+ }
+ EXEC SQL CLOSE csr_printers;
+
+ /* printers.conf entries for non-local CUPS queues */
+ EXEC SQL DECLARE csr_remote_printers CURSOR FOR
+ SELECT pr.rp, pr.name, pr.duplexname, pr.hwtype,
+ m.name, pr.banner, pr.location, pr.contact, pr.ka,
+ pr.ac, pr.lpc_acl, m.name as cupshosts
+ FROM printers pr, machine m, serverhosts sh
+ WHERE pr.rm = m.mach_id
+ AND (pr.type = 'CLUSTER' or pr.type = 'DORM') AND m.name <> :spoolhost AND
+ m.mach_id = sh.mach_id AND sh.service = 'CUPS-PRINT' AND
+ sh.enable = 1 AND m.mach_id = sh.mach_id;
+
+ EXEC SQL OPEN csr_remote_printers;
+ while (1)
+ {
+ EXEC SQL FETCH csr_remote_printers INTO :rp, :name, :duplexname,
+ :hwtype, :hostname, :banner, :location, :contact, :ka, :ac, :lpc_acl, :cupshosts;
+ if (sqlca.sqlcode)
+ break;
+
+ strtrim(rp);
+ strtrim(name);
+ strtrim(duplexname);
+ strtrim(hwtype);
+ strtrim(hostname);
+ strtrim(location);
+ strtrim(contact);
+ strtrim(cupshosts);
+ strcpy(lowerhwtype, hwtype);
+ for (p = rp; *p; p++) /* Because uppercased printer names suck */
+ *p = tolower(*p);
+ for (p = lowerhwtype; *p; p++)
+ *p = tolower(*p);
+
+ fprintf(out, "<Printer %s>\n",rp);
+ fprintf(out, "Info %s:%s\n", rp, hwtype);
+ fprintf(out, "DeviceURI ipp://%s:631/printers/%s\n", cupshosts, rp);
+ fprintf(out, "State Idle\n"); // Always with the Idle
+ fprintf(out, "StateTime %ld\n", (long)time(NULL));
+ fprintf(out, "Accepting Yes\n");
+ fprintf(out, "Shared Yes\n");
+ fprintf(out, "QuotaPeriod 0\n");
+ fprintf(out, "PageLimit 0\n");
+ fprintf(out, "Klimit 0\n");
+ fprintf(out, "Option sides one-sided\n");
+ fprintf(out, "Filter application/vnd.cups-raw 0 -\n");
+ fprintf(out, "Filter application/vnd.cups-postscript 100 foomatic-rip\n");
+ fprintf(out, "Filter application/vnd.cups-pdf 0 foomatic-rip\n");
+ fprintf(out, "Filter application/vnd.apple-pdf 25 foomatic-rip\n");
+ fprintf(out, "Filter application/vnd.cups-command 0 commandtops\n");
+ if (location[0])
+ fprintf(out, "Location %s\n", location);
+ fprintf(out, "ErrorPolicy abort-job\n");
+ if (ka || lpc_acl)
+ fprintf(out, "OpPolicy %s-policy\n", rp);
+ else
+ fprintf(out, "OpPolicy default\n");
+
+ /* Access-control list. */
+ if (ac)
+ {
+ if (ka)
+ fprintf(out, "AuthType Negotiate\n");
+ else
+ fprintf(out, "AuthType Default\n");
+ printer_user_list(out, "LIST", ac, "AllowUser");
+ }
+
+ if (banner == PRN_BANNER_NONE)
+ fprintf(out, "JobSheets none none\n");
+ else
+ fprintf(out, "JobSheets athena none\n");
+ fprintf(out, "</Printer>\n");
+
+ }
+ EXEC SQL CLOSE csr_remote_printers;
+
+ /* printers.conf entries for non-local LPRng queues */
+ EXEC SQL DECLARE csr_lprng_printers CURSOR FOR
+ SELECT pr.rp, pr.name, pr.duplexname, pr.hwtype,
+ m.name, pr.banner, pr.location, pr.contact, pr.ka,
+ pr.ac, pr.lpc_acl, m.name as cupshosts
+ FROM printers pr, machine m, serverhosts sh
+ WHERE pr.rm = m.mach_id
+ AND (pr.type = 'DORM' or pr.type = 'CLUSTER') AND m.name <> :spoolhost AND
+ m.mach_id = sh.mach_id AND sh.service = 'PRINT' AND
+ sh.enable = 1;
+
+ EXEC SQL OPEN csr_lprng_printers;
+ while (1)
+ {
+ EXEC SQL FETCH csr_lprng_printers INTO :rp, :name, :duplexname,
+ :hwtype, :hostname, :banner, :location, :contact, :ka, :ac, :lpc_acl, :cupshosts;
+ if (sqlca.sqlcode)
+ break;
+
+ strtrim(rp);
+ strtrim(name);
+ strtrim(duplexname);
+ strtrim(hwtype);
+ strtrim(hostname);
+ strtrim(location);
+ strtrim(contact);
+ strtrim(cupshosts);
+ strcpy(lowerhwtype, hwtype);
+ for (p = rp; *p; p++) /* Because uppercased printer names suck */
+ *p = tolower(*p);
+ for (p = lowerhwtype; *p; p++)
+ *p = tolower(*p);
+
+ fprintf(out, "<Printer %s>\n",rp);
+ fprintf(out, "Info %s:LPRng Queue on %s\n", rp, cupshosts);
+ fprintf(out, "DeviceURI lpd://%s/%s\n", cupshosts, rp);
+ fprintf(out, "State Idle\n"); // Always with the Idle
+ fprintf(out, "StateTime %ld\n", (long)time(NULL));
+ fprintf(out, "Accepting Yes\n");
+ fprintf(out, "Shared Yes\n");
+ fprintf(out, "QuotaPeriod 0\n");
+ fprintf(out, "PageLimit 0\n");
+ fprintf(out, "Klimit 0\n");
+ fprintf(out, "Option sides one-sided\n");
+ fprintf(out, "Filter application/vnd.cups-raw 0 -\n");
+ fprintf(out, "Filter application/vnd.cups-postscript 100 foomatic-rip\n");
+ fprintf(out, "Filter application/vnd.cups-pdf 0 foomatic-rip\n");
+ fprintf(out, "Filter application/vnd.apple-pdf 25 foomatic-rip\n");
+ fprintf(out, "Filter application/vnd.cups-command 0 commandtops\n");
+ if (location[0])
+ fprintf(out, "Location %s\n", location);
+ fprintf(out, "ErrorPolicy abort-job\n");
+ fprintf(out, "OpPolicy default\n");
+ fprintf(out, "JobSheets none none\n");
+ fprintf(out, "</Printer>\n");
+
+ }
+ EXEC SQL CLOSE csr_lprng_printers;
+ tarfile_end(tf);
+
+
+ /* aliases are in classes.conf */
+ out = tarfile_start(tf, "/etc/cups/classes.conf", 0644, 0, 0,
+ "lp", "lp", now);
+ EXEC SQL DECLARE csr_duplexqs CURSOR FOR
+ SELECT pr.rp, pr.name, pr.duplexname, pr.hwtype,
+ m.name, pr.banner, pr.location, pr.contact, pr.ka,
+ pr.type as prtype, pr.ac
+ FROM printers pr, machine m, serverhosts sh
+ WHERE pr.rm = m.mach_id
+ AND m.mach_id = sh.mach_id AND sh.enable = 1
+ AND (pr.type = 'DORM' or pr.type = 'CLUSTER')
+ AND (sh.service = 'CUPS-PRINT' OR sh.service = 'PRINT');
+ EXEC SQL OPEN csr_duplexqs;
+ while (1)
+ {
+ EXEC SQL FETCH csr_duplexqs INTO :rp, :name, :duplexname,
+ :hwtype, :hostname, :banner, :location, :contact, :ka, :prtype, :ac;
+ if (sqlca.sqlcode)
+ break;
+
+ strtrim(hwtype);
+ strtrim(rp);
+ strtrim(location);
+ strtrim(contact);
+ strtrim(prtype);
+
+ /* Define alias queues as classes to the regular queues for
+ * accounting reasons. Annoyingly, classes don't always inherit
+ * their printer definitions.
+ */
+ if (!strcmp(prtype,"ALIAS"))
+ {
+ strtrim(name);
+ fprintf(out, "<Class %s>\n",name);
+ fprintf(out, "Info Alias Queue to %s:%s\n", rp, hwtype);
+ fprintf(out, "Printer %s\n", rp);
+ fprintf(out, "Option sides one-sided\n");
+ fprintf(out, "State Idle\n"); // Always with the Idle
+ fprintf(out, "StateTime %ld\n", (long)time(NULL));
+ fprintf(out, "Accepting Yes\n");
+ fprintf(out, "Shared Yes\n");
+ fprintf(out, "QuotaPeriod 0\n");
+ fprintf(out, "PageLimit 0\n");
+ if (location[0])
+ fprintf(out, "Location %s\n", location);
+ /* fprintf(out, "ErrorPolicy abort-job\n"); */
+ if (ka || lpc_acl)
+ fprintf(out, "OpPolicy %s-policy\n", rp);
+ else
+ fprintf(out, "OpPolicy default\n");
+
+ /* Access-control list. */
+ if (ac)
+ {
+ if (ka)
+ fprintf(out, "AuthType Negotiate\n");
+ else
+ fprintf(out, "AuthType Default\n");
+ printer_user_list(out, "LIST", ac, "AllowUser");
+ }
+
+ if (banner == PRN_BANNER_NONE)
+ fprintf(out, "JobSheets none none\n");
+ else
+ fprintf(out, "JobSheets athena none\n");
+ fprintf(out, "</Class>\n");
+ }
+
+ /* Define duplex queues as aliases to the regular queues for
+ * accounting reasons. Annoyingly, classes don't always inherit
+ * their printer definitions.
+ */
+ if (*duplexname)
+ {
+ strtrim(duplexname);
+ fprintf(out, "<Class %s>\n",duplexname);
+ if (!strcmp(prtype,"ALIAS"))
+ fprintf(out, "Info Duplex Alias Queue to %s:%s\n", rp, hwtype);
+ else
+ fprintf(out, "Info Duplex Queue for %s:%s\n", rp, hwtype);
+ fprintf(out, "Option sides two-sided-long-edge\n"); // duplex
+ fprintf(out, "Printer %s\n", rp);
+ fprintf(out, "State Idle\n"); // Always with the Idle
+ fprintf(out, "StateTime %ld\n", (long)time(NULL));
+ fprintf(out, "Accepting Yes\n");
+ fprintf(out, "Shared Yes\n");
+ fprintf(out, "QuotaPeriod 0\n");
+ fprintf(out, "PageLimit 0\n");
+ if (location[0])
+ fprintf(out, "Location %s\n", location);
+ fprintf(out, "ErrorPolicy abort-job\n");
+ if (ka || lpc_acl)
+ fprintf(out, "OpPolicy %s-policy\n", rp);
+ else
+ fprintf(out, "OpPolicy default\n");
+
+ /* Access-control list. */
+ if (ac)
+ {
+ if (ka)
+ fprintf(out, "AuthType Negotiate\n");
+ else
+ fprintf(out, "AuthType Default\n");
+ printer_user_list(out, "LIST", ac, "AllowUser");
+ }
+
+ if (banner == PRN_BANNER_NONE)
+ fprintf(out, "JobSheets none none\n");
+ else if (banner == PRN_BANNER_LAST)
+ fprintf(out, "JobSheets athena none\n");
+ fprintf(out, "</Class>\n");
+ }
+ }
+ EXEC SQL CLOSE csr_duplexqs;
+ tarfile_end(tf);
+
+ /* cups.conf */
+ out = tarfile_start(tf, "/etc/cups/cupsd.conf", 0755, 1, 1,
+ "root", "lp", now);
+
+ fprintf(out, "LogLevel info\n");
+ fprintf(out, "SystemGroup sys root ops-group\n");
+ fprintf(out, "Port 631\n");
+ fprintf(out, "Listen /var/run/cups/cups.sock\n");
+ fprintf(out, "Browsing On\n");
+ fprintf(out, "BrowseOrder allow,deny\n");
+ fprintf(out, "BrowseAllow all\n");
+ fprintf(out, "BrowseAddress @LOCAL\n");
+ fprintf(out, "DefaultAuthType Negotiate\n");
+ fprintf(out, "ServerCertificate /etc/cups/ssl/%s-ipp-crt.pem\n", lhost);
+ fprintf(out, "ServerKey /etc/cups/ssl/%s-ipp-key.pem\n", lhost);
+ fprintf(out, "ServerName %s\n", lhost);
+ fprintf(out, "ServerAlias %s\n", phost);
+ fprintf(out, "Krb5Keytab /etc/krb5-ipp.keytab\n");
+
+ /* The other CUPS servers should be aware of the other hosts'
+ queues, so we'll let them browse each other. */
+ fprintf(out, "Include cups.local.conf\n");
+ fprintf(out, "Include cups.locations.conf\n");
+ fprintf(out, "Include cups.policies.conf\n");
+ tarfile_end(tf);
+
+ /* cups.hosts.conf */
+ out = tarfile_start(tf, "/etc/cups/cups.hosts.conf", 0755, 1, 1,
+ "root", "lp", now);
+ EXEC SQL DECLARE csr_cupshosts CURSOR FOR
+ SELECT m.name AS cupshosts FROM machine m, printservers ps
+ WHERE m.mach_id = ps.mach_id AND ps.kind = 'CUPS';
+ EXEC SQL OPEN csr_cupshosts;
+ while (1)
+ {
+ EXEC SQL FETCH csr_cupshosts INTO :cupshosts;
+ if (sqlca.sqlcode)
+ break;
+
+ strtrim(cupshosts);
+
+ /* Don't poll yourself looking for answers! */
+ if (strcmp(cupshosts,host))
+ fprintf(out, "BrowsePoll %s\n", cupshosts);
+ }
+ EXEC SQL CLOSE csr_cupshosts;
+
+ tarfile_end(tf);
+
+ /* cups.policies.conf */
+ out = tarfile_start(tf, "/etc/cups/cups.policies.conf", 0755, 1, 1,
+ "root", "lp", now);
+ fprintf(out, "# Printer-specific LPC and LPR ACLs\n");
+ /* lpcaccess.top */
+ EXEC SQL SELECT ps.lpc_acl INTO :top_lpc_acl
+ FROM printservers ps, machine m
+ WHERE m.name = :spoolhost AND m.mach_id = ps.mach_id;
+ if (!sqlca.sqlcode && lpc_acl)
+ {
+ fprintf (out, "<Policy default>\n");
+ fprintf (out, "%s\n", alterjob);
+ fprintf (out, "AuthType Default\n");
+ fprintf (out, "Require user @OWNER @SYSTEM\n");
+ printer_user_list(out, "LIST", top_lpc_acl, "Require user");
+ fprintf (out, "Order deny,allow\n");
+ fprintf (out, "</Limit>\n");
+ fprintf (out, "%s\n", submitjob);
+ fprintf (out, "AuthType None\n");
+ fprintf (out, "Order deny,allow\n");
+ fprintf (out, "Allow from all\n");
+ fprintf (out, "</Limit>\n");
+ fprintf (out, "%s\n", alterpntr);
+ fprintf (out, "AuthType Default\n");
+ fprintf (out, "Require user @SYSTEM\n");
+ fprintf (out, "Order deny,allow\n");
+ fprintf (out, "</Limit>\n");
+ fprintf (out, "%s\n", lpcpntr);
+ fprintf (out, "AuthType Default\n");
+ fprintf (out, "Require user @SYSTEM\n");
+ printer_user_list(out, "LIST", top_lpc_acl, "Require user");
+ fprintf (out, "Order deny,allow\n");
+ fprintf (out, "</Limit>\n");
+ fprintf (out, "%s\n", canceljob);
+ fprintf (out, "AuthType Default\n");
+ fprintf (out, "Require user @OWNER @SYSTEM\n");
+ printer_user_list(out, "LIST", top_lpc_acl, "Require user");
+ fprintf (out, "Order deny,allow\n");
+ fprintf (out, "Allow from all\n");
+ fprintf (out, "</Limit>\n");
+ fprintf (out, "%s\n", catchall);
+ fprintf (out, "AuthType None\n");
+ fprintf (out, "Order deny,allow\n");
+ fprintf (out, "Allow from all\n");
+ fprintf (out, "</Limit>\n");
+ fprintf (out, "</Policy>\n");
+ }
+
+ /* restrict lists and lpcaccess policies. Sadly, we have to put the
+ top level for each new policy since CUPS doesn't have a way of
+ doing it otherwise (well, Unix groups, but not moira) */
+ EXEC SQL DECLARE csr_lpc CURSOR FOR
+ SELECT UNIQUE rp, ka, ac, lpc_acl
+ FROM printers
+ WHERE (ac != 0 OR lpc_acl != 0) AND rm in (SELECT m.mach_id FROM machine m, serverhosts sh
+ WHERE m.mach_id = sh.mach_id AND sh.service = 'CUPS-PRINT' AND sh.enable = 1);
+ EXEC SQL OPEN csr_lpc;
+ while (1)
+ {
+ EXEC SQL FETCH csr_lpc INTO :name, :ka, :ac, :lpc_acl;
+ if (sqlca.sqlcode)
+ break;
+
+ strtrim(name);
+
+ fprintf (out, "<Policy %s-policy>\n", name);
+ fprintf (out, "%s\n", alterjob);
+ fprintf (out, "AuthType Default\n");
+ fprintf (out, "Require user @OWNER @SYSTEM\n");
+ printer_user_list(out, "LIST", lpc_acl, "Require user");
+ fprintf (out, "Order deny,allow\n");
+ fprintf (out, "Allow from all\n");
+ fprintf (out, "</Limit>\n");
+ fprintf (out, "%s\n", submitjob);
+ /* If the printer is Kerberized? */
+ if (ka)
+ fprintf (out, "AuthType Negotiate\n");
+ else
+ fprintf (out, "AuthType None\n");
+ /* Access-control list. */
+ if (ac)
+ printer_user_list(out, "LIST", ac, "Require user");
+ else if (ka)
+ fprintf (out, "Require valid-user\n");
+ fprintf (out, "Order deny,allow\n");
+ fprintf (out, "Allow from all\n");
+ fprintf (out, "</Limit>\n");
+ fprintf (out, "%s\n", alterpntr);
+ fprintf (out, "AuthType Default\n");
+ fprintf (out, "Require user @SYSTEM\n");
+ fprintf (out, "Order deny,allow\n");
+ fprintf (out, "</Limit>\n");
+ fprintf (out, "%s\n", lpcpntr);
+ fprintf (out, "AuthType Default\n");
+ fprintf (out, "Require user @SYSTEM\n");
+ /* printer-specific lpc access. */
+ if (lpc_acl)
+ printer_user_list(out, "LIST", lpc_acl, "Require user");
+ printer_user_list(out, "LIST", top_lpc_acl, "Require user");
+ fprintf (out, "Order deny,allow\n");
+ fprintf (out, "</Limit>\n");
+ fprintf (out, "%s\n", canceljob);
+ fprintf (out, "AuthType Default\n");
+ fprintf (out, "Require user @OWNER @SYSTEM\n");
+ printer_user_list(out, "LIST", lpc_acl, "Require user");
+ printer_user_list(out, "LIST", top_lpc_acl, "Require user");
+ fprintf (out, "Order deny,allow\n");
+ fprintf (out, "Allow from all\n");
+ fprintf (out, "</Limit>\n");
+ fprintf (out, "%s\n", catchall);
+ fprintf (out, "AuthType None\n");
+ fprintf (out, "Order deny,allow\n");
+ fprintf (out, "Allow from all\n");
+ fprintf (out, "</Limit>\n");
+ fprintf (out, "</Policy>\n");
+ }
+ EXEC SQL CLOSE csr_lpc;
+ fprintf(out, "\n");
+ tarfile_end(tf);
+ tarfile_close(tf);
+}
+
+void sqlerr(void)
+{
+ db_error(sqlca.sqlcode);
+}