3 * This generates printcaps and other files for Athena print servers
5 * Copyright (C) 1992-1998 by the Massachusetts Institute of Technology.
6 * For copying and distribution information, please see the file
10 #include <mit-copyright.h>
12 #include <moira_site.h>
15 #include <sys/types.h>
29 EXEC SQL INCLUDE sqlca;
33 char *whoami = "cups-print.gen";
34 char *db = "moira/moira";
36 const int krbvers = 5; /* use Kerberos 5 */
38 /* OMG, I hate this, but it's cleaner, I guess? */
40 const char *alterjob = "<Limit Hold-Job Release-Job\
41 Restart-Job Purge-Jobs Reprocess-Job Set-Job-Attributes\
42 Cancel-Current-Job Suspend-Current-Job Resume-Job CUPS-Move-Job>";
43 const char *submitjob = "<Limit Create-Job Print-Job Print-URI Send-Document\
44 Set-Job-Attributes Send-URI Create-Job-Subscription Renew-Subscription\
45 Cancel-Subscription Get-Notifications CUPS-Move-Job>";
46 const char *alterpntr = "<Limit CUPS-Add-Modify-Printer CUPS-Delete-Printer\
47 CUPS-Add-Modify-Class CUPS-Delete-Class CUPS-Set-Default>";
48 const char *lpcpntr = "<Limit Pause-Printer Resume-Printer Enable-Printer\
49 Disable-Printer Pause-Printer-After-Current-Job Hold-New-Jobs\
50 Release-Held-New-Jobs Deactivate-Printer Activate-Printer Restart-Printer\
51 Shutdown-Printer Startup-Printer Promote-Job Schedule-Job-After\
52 CUPS-Accept-Jobs CUPS-Reject-Jobs>";
53 const char *canceljob = "<Limit Cancel-Job CUPS-Authenticate-Job>";
54 const char *catchall = "<Limit All>";
55 const char *phost = "printers.MIT.EDU";
57 void do_host(char *host);
60 #define MAX(a, b) ( (a) > (b) ? (a) : (b) )
63 int main(int argc, char **argv)
65 EXEC SQL BEGIN DECLARE SECTION;
66 char name[MACHINE_NAME_SIZE];
67 EXEC SQL END DECLARE SECTION;
73 EXEC SQL WHENEVER SQLERROR DO sqlerr();
75 EXEC SQL DECLARE csr_hosts CURSOR FOR
76 SELECT m.name FROM machine m, serverhosts sh
77 WHERE m.mach_id = sh.mach_id AND (sh.service = 'CUPS-PRINT' OR sh.service = 'CUPS-CLUSTER')
79 EXEC SQL OPEN csr_hosts;
82 EXEC SQL FETCH csr_hosts INTO :name;
89 EXEC SQL CLOSE csr_hosts;
94 void printer_user_list(FILE *out, char *type, int id, char *str)
96 struct save_queue *sq;
98 char kbuf[MAX_K_NAME_SZ];
101 sq = get_acl(type, id, NULL);
102 while (sq_remove_data(sq, &m))
104 if (m->type != 'S' && m->type != NULL) {
105 /* CUPS wants mmanley/root, not mmanley.root@ATHENA.MIT.EDU */
106 canon_krb(m, krbvers, kbuf, sizeof(kbuf));
108 /* now, take out all the @realm */
109 for (cp=kbuf; *cp; cp++) {
110 if (*cp == '@') *cp = '\0';
112 fprintf(out, "%s %s\n", str, kbuf);
121 void do_host(char *host)
123 EXEC SQL BEGIN DECLARE SECTION;
124 char rp[PRINTERS_RP_SIZE], name[PRINTERS_NAME_SIZE];
125 char duplexname[PRINTERS_DUPLEXNAME_SIZE], location[PRINTERS_LOCATION_SIZE];
126 char hwtype[PRINTERS_HWTYPE_SIZE], lowerhwtype[PRINTERS_HWTYPE_SIZE];
127 char modtime[PRINTERS_MODTIME_SIZE], lmodtime[LIST_MODTIME_SIZE];
128 char contact[PRINTERS_CONTACT_SIZE], hostname[MACHINE_NAME_SIZE];
129 char cupshosts[MACHINE_NAME_SIZE], prtype [PRINTERS_TYPE_SIZE];
130 char *spoolhost = host, *unixtime_fmt = UNIXTIME_FMT, *p;
132 int ka, pc, ac, lpc_acl, top_lpc_acl, banner, rm;
133 EXEC SQL END DECLARE SECTION;
136 char filename[MAXPATHLEN], *duptc;
137 time_t mtime, now = time(NULL);
139 lhost = (char *) strdup (host);
140 for (p = lhost; *p; p++)
143 EXEC SQL SELECT mach_id INTO :rm FROM machine
144 WHERE name = :spoolhost;
146 sprintf(filename, "%s/cups-print/%s", DCM_DIR, host);
147 tf = tarfile_open(filename);
149 /* printers.conf entries for locally run queues */
150 out = tarfile_start(tf, "/etc/cups/printers.conf", 0644, 0, 0,
153 EXEC SQL DECLARE csr_printers CURSOR FOR
154 SELECT pr.rp, pr.name, pr.duplexname, pr.hwtype,
155 m.name, pr.banner, pr.location, pr.contact, pr.ka,
157 FROM printers pr, machine m
158 WHERE pr.rm = :rm AND m.mach_id = pr.mach_id
159 AND pr.type != 'ALIAS';
160 EXEC SQL OPEN csr_printers;
163 EXEC SQL FETCH csr_printers INTO :rp, :name, :duplexname,
164 :hwtype, :hostname, :banner, :location, :contact, :ka, :ac, :lpc_acl;
175 strcpy(lowerhwtype, hwtype);
176 for (p = rp; *p; p++) /* Because uppercased printer names suck */
178 for (p = lowerhwtype; *p; p++)
181 fprintf(out, "<Printer %s>\n",rp);
182 fprintf(out, "Info %s:%s\n", rp, hwtype);
183 /* Note the use of "beh" to keep the CUPS from disabling print queues
184 * should they not respond versus discarding the job.
185 * See the "beh" page for details.
186 * The 1/0/60 says "don't disable/try 20 times/try every 60s */
187 if (!strncmp(hwtype, "HP", 2))
188 fprintf(out, "DeviceURI beh:/1/20/60/socket://%s:9100\n", hostname);
190 fprintf(out, "DeviceURI beh:/1/20/60/socket://%s\n", hostname);
191 fprintf(out, "State Idle\n"); // Always with the Idle
192 fprintf(out, "StateTime %ld\n", (long)time(NULL));
193 fprintf(out, "Accepting Yes\n");
194 fprintf(out, "Shared Yes\n");
195 fprintf(out, "QuotaPeriod 0\n");
196 fprintf(out, "PageLimit 0\n");
197 fprintf(out, "Klimit 0\n");
198 fprintf(out, "Option sides one-sided\n");
199 fprintf(out, "Filter application/vnd.cups-raw 0 -\n");
200 fprintf(out, "Filter application/vnd.cups-postscript 100 foomatic-rip\n");
201 fprintf(out, "Filter application/vnd.cups-pdf 0 foomatic-rip\n");
202 fprintf(out, "Filter application/vnd.apple-pdf 25 foomatic-rip\n");
203 fprintf(out, "Filter application/vnd.cups-command 0 commandtops\n");
205 fprintf(out, "Location %s\n", location);
206 fprintf(out, "ErrorPolicy abort-job\n");
208 fprintf(out, "OpPolicy %s-policy\n", rp);
210 fprintf(out, "OpPolicy default\n");
212 /* Access-control list. */
216 fprintf(out, "AuthType Negotiate\n");
218 fprintf(out, "AuthType Default\n");
219 printer_user_list(out, "LIST", ac, "AllowUser");
222 if (banner == PRN_BANNER_NONE)
223 fprintf(out, "JobSheets none none\n");
225 fprintf(out, "JobSheets athena none\n");
226 fprintf(out, "</Printer>\n");
229 EXEC SQL CLOSE csr_printers;
231 /* printers.conf entries for non-local CUPS queues */
232 EXEC SQL DECLARE csr_remote_printers CURSOR FOR
233 SELECT pr.rp, pr.name, pr.duplexname, pr.hwtype,
234 m.name, pr.banner, pr.location, pr.contact, pr.ka,
235 pr.ac, pr.lpc_acl, m.name as cupshosts
236 FROM printers pr, machine m, serverhosts sh
237 WHERE pr.rm = m.mach_id
238 AND pr.type != 'ALIAS' AND m.name <> :spoolhost AND
239 m.mach_id = sh.mach_id AND (sh.service = 'CUPS-PRINT' OR sh.service = 'CUPS-CLUSTER')
240 AND sh.enable = 1 AND m.mach_id = sh.mach_id;
242 EXEC SQL OPEN csr_remote_printers;
245 EXEC SQL FETCH csr_remote_printers INTO :rp, :name, :duplexname,
246 :hwtype, :hostname, :banner, :location, :contact, :ka, :ac, :lpc_acl, :cupshosts;
258 strcpy(lowerhwtype, hwtype);
259 for (p = rp; *p; p++) /* Because uppercased printer names suck */
261 for (p = lowerhwtype; *p; p++)
264 fprintf(out, "<Printer %s>\n",rp);
265 fprintf(out, "Info %s:%s\n", rp, hwtype);
266 fprintf(out, "DeviceURI ipp://%s:631/printers/%s\n", cupshosts, rp);
267 fprintf(out, "State Idle\n"); // Always with the Idle
268 fprintf(out, "StateTime %ld\n", (long)time(NULL));
269 fprintf(out, "Accepting Yes\n");
270 fprintf(out, "Shared Yes\n");
271 fprintf(out, "QuotaPeriod 0\n");
272 fprintf(out, "PageLimit 0\n");
273 fprintf(out, "Klimit 0\n");
274 fprintf(out, "Option sides one-sided\n");
275 fprintf(out, "Filter application/vnd.cups-raw 0 -\n");
276 fprintf(out, "Filter application/vnd.cups-postscript 100 foomatic-rip\n");
277 fprintf(out, "Filter application/vnd.cups-pdf 0 foomatic-rip\n");
278 fprintf(out, "Filter application/vnd.apple-pdf 25 foomatic-rip\n");
279 fprintf(out, "Filter application/vnd.cups-command 0 commandtops\n");
281 fprintf(out, "Location %s\n", location);
282 fprintf(out, "ErrorPolicy abort-job\n");
284 fprintf(out, "OpPolicy %s-policy\n", rp);
286 fprintf(out, "OpPolicy default\n");
288 /* Access-control list. */
292 fprintf(out, "AuthType Negotiate\n");
294 fprintf(out, "AuthType Default\n");
295 printer_user_list(out, "LIST", ac, "AllowUser");
298 if (banner == PRN_BANNER_NONE)
299 fprintf(out, "JobSheets none none\n");
301 fprintf(out, "JobSheets athena none\n");
302 fprintf(out, "</Printer>\n");
305 EXEC SQL CLOSE csr_remote_printers;
307 /* printers.conf entries for non-local LPRng queues */
308 EXEC SQL DECLARE csr_lprng_printers CURSOR FOR
309 SELECT pr.rp, pr.name, pr.duplexname, pr.hwtype,
310 m.name, pr.banner, pr.location, pr.contact, pr.ka,
311 pr.ac, pr.lpc_acl, m.name as cupshosts
312 FROM printers pr, machine m, serverhosts sh
313 WHERE pr.rm = m.mach_id
314 AND pr.type != 'ALIAS' AND m.name <> :spoolhost AND
315 m.mach_id = sh.mach_id AND sh.service = 'PRINT' AND
318 EXEC SQL OPEN csr_lprng_printers;
321 EXEC SQL FETCH csr_lprng_printers INTO :rp, :name, :duplexname,
322 :hwtype, :hostname, :banner, :location, :contact, :ka, :ac, :lpc_acl, :cupshosts;
334 strcpy(lowerhwtype, hwtype);
335 for (p = rp; *p; p++) /* Because uppercased printer names suck */
337 for (p = lowerhwtype; *p; p++)
340 fprintf(out, "<Printer %s>\n",rp);
341 fprintf(out, "Info %s:LPRng Queue on %s\n", rp, cupshosts);
342 fprintf(out, "DeviceURI lpd://%s/%s\n", cupshosts, rp);
343 fprintf(out, "State Idle\n"); // Always with the Idle
344 fprintf(out, "StateTime %ld\n", (long)time(NULL));
345 fprintf(out, "Accepting Yes\n");
346 fprintf(out, "Shared Yes\n");
347 fprintf(out, "QuotaPeriod 0\n");
348 fprintf(out, "PageLimit 0\n");
349 fprintf(out, "Klimit 0\n");
350 fprintf(out, "Option sides one-sided\n");
351 fprintf(out, "Filter application/vnd.cups-raw 0 -\n");
352 fprintf(out, "Filter application/vnd.cups-postscript 100 foomatic-rip\n");
353 fprintf(out, "Filter application/vnd.cups-pdf 0 foomatic-rip\n");
354 fprintf(out, "Filter application/vnd.apple-pdf 25 foomatic-rip\n");
355 fprintf(out, "Filter application/vnd.cups-command 0 commandtops\n");
357 fprintf(out, "Location %s\n", location);
358 fprintf(out, "ErrorPolicy abort-job\n");
359 fprintf(out, "OpPolicy default\n");
360 fprintf(out, "JobSheets none none\n");
361 fprintf(out, "</Printer>\n");
364 EXEC SQL CLOSE csr_lprng_printers;
368 /* aliases are in classes.conf */
369 out = tarfile_start(tf, "/etc/cups/classes.conf", 0644, 0, 0,
371 EXEC SQL DECLARE csr_duplexqs CURSOR FOR
372 SELECT pr.rp, pr.name, pr.duplexname, pr.hwtype,
373 m.name, pr.banner, pr.location, pr.contact, pr.ka,
374 pr.type as prtype, pr.ac
375 FROM printers pr, machine m, serverhosts sh
376 WHERE pr.rm = m.mach_id
377 AND m.mach_id = sh.mach_id AND sh.enable = 1
378 AND (sh.service = 'CUPS-PRINT' OR sh.service = 'PRINT' OR sh.service = 'CUPS-CLUSTER');
379 EXEC SQL OPEN csr_duplexqs;
382 EXEC SQL FETCH csr_duplexqs INTO :rp, :name, :duplexname,
383 :hwtype, :hostname, :banner, :location, :contact, :ka, :prtype, :ac;
393 /* Define alias queues as classes to the regular queues for
394 * accounting reasons. Annoyingly, classes don't always inherit
395 * their printer definitions.
397 if (!strcmp(prtype,"ALIAS"))
400 fprintf(out, "<Class %s>\n",name);
401 fprintf(out, "Info Alias Queue to %s:%s\n", rp, hwtype);
402 fprintf(out, "Printer %s\n", rp);
403 fprintf(out, "Option sides one-sided\n");
404 fprintf(out, "State Idle\n"); // Always with the Idle
405 fprintf(out, "StateTime %ld\n", (long)time(NULL));
406 fprintf(out, "Accepting Yes\n");
407 fprintf(out, "Shared Yes\n");
408 fprintf(out, "QuotaPeriod 0\n");
409 fprintf(out, "PageLimit 0\n");
411 fprintf(out, "Location %s\n", location);
412 /* fprintf(out, "ErrorPolicy abort-job\n"); */
414 fprintf(out, "OpPolicy %s-policy\n", rp);
416 fprintf(out, "OpPolicy default\n");
418 /* Access-control list. */
422 fprintf(out, "AuthType Negotiate\n");
424 fprintf(out, "AuthType Default\n");
425 printer_user_list(out, "LIST", ac, "AllowUser");
428 if (banner == PRN_BANNER_NONE)
429 fprintf(out, "JobSheets none none\n");
431 fprintf(out, "JobSheets athena none\n");
432 fprintf(out, "</Class>\n");
435 /* Define duplex queues as aliases to the regular queues for
436 * accounting reasons. Annoyingly, classes don't always inherit
437 * their printer definitions.
442 fprintf(out, "<Class %s>\n",duplexname);
443 if (!strcmp(prtype,"ALIAS"))
444 fprintf(out, "Info Duplex Alias Queue to %s:%s\n", rp, hwtype);
446 fprintf(out, "Info Duplex Queue for %s:%s\n", rp, hwtype);
447 fprintf(out, "Option sides two-sided-long-edge\n"); // duplex
448 fprintf(out, "Printer %s\n", rp);
449 fprintf(out, "State Idle\n"); // Always with the Idle
450 fprintf(out, "StateTime %ld\n", (long)time(NULL));
451 fprintf(out, "Accepting Yes\n");
452 fprintf(out, "Shared Yes\n");
453 fprintf(out, "QuotaPeriod 0\n");
454 fprintf(out, "PageLimit 0\n");
456 fprintf(out, "Location %s\n", location);
457 fprintf(out, "ErrorPolicy abort-job\n");
459 fprintf(out, "OpPolicy %s-policy\n", rp);
461 fprintf(out, "OpPolicy default\n");
463 /* Access-control list. */
467 fprintf(out, "AuthType Negotiate\n");
469 fprintf(out, "AuthType Default\n");
470 printer_user_list(out, "LIST", ac, "AllowUser");
473 if (banner == PRN_BANNER_NONE)
474 fprintf(out, "JobSheets none none\n");
475 else if (banner == PRN_BANNER_LAST)
476 fprintf(out, "JobSheets athena none\n");
477 fprintf(out, "</Class>\n");
480 EXEC SQL CLOSE csr_duplexqs;
484 out = tarfile_start(tf, "/etc/cups/cupsd.conf", 0755, 1, 1,
487 fprintf(out, "LogLevel info\n");
488 fprintf(out, "SystemGroup sys root ops-group\n");
489 fprintf(out, "Port 631\n");
490 fprintf(out, "Listen /var/run/cups/cups.sock\n");
491 fprintf(out, "Browsing On\n");
492 fprintf(out, "BrowseOrder allow,deny\n");
493 fprintf(out, "BrowseAllow all\n");
494 fprintf(out, "BrowseAddress @LOCAL\n");
495 fprintf(out, "DefaultAuthType Negotiate\n");
496 fprintf(out, "ServerCertificate /etc/cups/ssl/%s-ipp-crt.pem\n", lhost);
497 fprintf(out, "ServerKey /etc/cups/ssl/%s-ipp-key.pem\n", lhost);
498 fprintf(out, "ServerName %s\n", lhost);
499 fprintf(out, "ServerAlias %s\n", phost);
500 fprintf(out, "Krb5Keytab /etc/krb5-ipp.keytab\n");
502 /* The other CUPS servers should be aware of the other hosts'
503 queues, so we'll let them browse each other. */
504 fprintf(out, "Include cups.local.conf\n");
505 fprintf(out, "Include cups.locations.conf\n");
506 fprintf(out, "Include cups.policies.conf\n");
509 /* cups.hosts.conf */
510 out = tarfile_start(tf, "/etc/cups/cups.hosts.conf", 0755, 1, 1,
512 EXEC SQL DECLARE csr_cupshosts CURSOR FOR
513 SELECT m.name AS cupshosts FROM machine m, printservers ps
514 WHERE m.mach_id = ps.mach_id AND ps.kind = 'CUPS';
515 EXEC SQL OPEN csr_cupshosts;
518 EXEC SQL FETCH csr_cupshosts INTO :cupshosts;
524 /* Don't poll yourself looking for answers! */
525 if (strcmp(cupshosts,host))
526 fprintf(out, "BrowsePoll %s\n", cupshosts);
528 EXEC SQL CLOSE csr_cupshosts;
532 /* cups.policies.conf */
533 out = tarfile_start(tf, "/etc/cups/cups.policies.conf", 0755, 1, 1,
535 fprintf(out, "# Printer-specific LPC and LPR ACLs\n");
537 EXEC SQL SELECT ps.lpc_acl INTO :top_lpc_acl
538 FROM printservers ps, machine m
539 WHERE m.name = :spoolhost AND m.mach_id = ps.mach_id;
540 if (!sqlca.sqlcode && lpc_acl)
542 fprintf (out, "<Policy default>\n");
543 fprintf (out, "%s\n", alterjob);
544 fprintf (out, "AuthType Default\n");
545 fprintf (out, "Require user @OWNER @SYSTEM\n");
546 printer_user_list(out, "LIST", top_lpc_acl, "Require user");
547 fprintf (out, "Order deny,allow\n");
548 fprintf (out, "</Limit>\n");
549 fprintf (out, "%s\n", submitjob);
550 fprintf (out, "AuthType None\n");
551 fprintf (out, "Order deny,allow\n");
552 fprintf (out, "Allow from all\n");
553 fprintf (out, "</Limit>\n");
554 fprintf (out, "%s\n", alterpntr);
555 fprintf (out, "AuthType Default\n");
556 fprintf (out, "Require user @SYSTEM\n");
557 fprintf (out, "Order deny,allow\n");
558 fprintf (out, "</Limit>\n");
559 fprintf (out, "%s\n", lpcpntr);
560 fprintf (out, "AuthType Default\n");
561 fprintf (out, "Require user @SYSTEM\n");
562 printer_user_list(out, "LIST", top_lpc_acl, "Require user");
563 fprintf (out, "Order deny,allow\n");
564 fprintf (out, "</Limit>\n");
565 fprintf (out, "%s\n", canceljob);
566 fprintf (out, "AuthType Default\n");
567 fprintf (out, "Require user @OWNER @SYSTEM\n");
568 printer_user_list(out, "LIST", top_lpc_acl, "Require user");
569 fprintf (out, "Order deny,allow\n");
570 fprintf (out, "Allow from all\n");
571 fprintf (out, "</Limit>\n");
572 fprintf (out, "%s\n", catchall);
573 fprintf (out, "AuthType None\n");
574 fprintf (out, "Order deny,allow\n");
575 fprintf (out, "Allow from all\n");
576 fprintf (out, "</Limit>\n");
577 fprintf (out, "</Policy>\n");
580 /* restrict lists and lpcaccess policies. Sadly, we have to put the
581 top level for each new policy since CUPS doesn't have a way of
582 doing it otherwise (well, Unix groups, but not moira) */
583 EXEC SQL DECLARE csr_lpc CURSOR FOR
584 SELECT UNIQUE rp, ka, ac, lpc_acl
586 WHERE (ac != 0 OR lpc_acl != 0) AND rm in (SELECT m.mach_id FROM machine m, serverhosts sh
587 WHERE m.mach_id = sh.mach_id AND (sh.service = 'CUPS-PRINT' OR sh.service = 'CUPS-CLUSTER')
589 EXEC SQL OPEN csr_lpc;
592 EXEC SQL FETCH csr_lpc INTO :name, :ka, :ac, :lpc_acl;
598 fprintf (out, "<Policy %s-policy>\n", name);
599 fprintf (out, "%s\n", alterjob);
600 fprintf (out, "AuthType Default\n");
601 fprintf (out, "Require user @OWNER @SYSTEM\n");
602 printer_user_list(out, "LIST", lpc_acl, "Require user");
603 fprintf (out, "Order deny,allow\n");
604 fprintf (out, "Allow from all\n");
605 fprintf (out, "</Limit>\n");
606 fprintf (out, "%s\n", submitjob);
607 /* If the printer is Kerberized? */
609 fprintf (out, "AuthType Negotiate\n");
611 fprintf (out, "AuthType None\n");
612 /* Access-control list. */
614 printer_user_list(out, "LIST", ac, "Require user");
616 fprintf (out, "Require valid-user\n");
617 fprintf (out, "Order deny,allow\n");
618 fprintf (out, "Allow from all\n");
619 fprintf (out, "</Limit>\n");
620 fprintf (out, "%s\n", alterpntr);
621 fprintf (out, "AuthType Default\n");
622 fprintf (out, "Require user @SYSTEM\n");
623 fprintf (out, "Order deny,allow\n");
624 fprintf (out, "</Limit>\n");
625 fprintf (out, "%s\n", lpcpntr);
626 fprintf (out, "AuthType Default\n");
627 fprintf (out, "Require user @SYSTEM\n");
628 /* printer-specific lpc access. */
630 printer_user_list(out, "LIST", lpc_acl, "Require user");
631 printer_user_list(out, "LIST", top_lpc_acl, "Require user");
632 fprintf (out, "Order deny,allow\n");
633 fprintf (out, "</Limit>\n");
634 fprintf (out, "%s\n", canceljob);
635 fprintf (out, "AuthType Default\n");
636 fprintf (out, "Require user @OWNER @SYSTEM\n");
637 printer_user_list(out, "LIST", lpc_acl, "Require user");
638 printer_user_list(out, "LIST", top_lpc_acl, "Require user");
639 fprintf (out, "Order deny,allow\n");
640 fprintf (out, "Allow from all\n");
641 fprintf (out, "</Limit>\n");
642 fprintf (out, "%s\n", catchall);
643 fprintf (out, "AuthType None\n");
644 fprintf (out, "Order deny,allow\n");
645 fprintf (out, "Allow from all\n");
646 fprintf (out, "</Limit>\n");
647 fprintf (out, "</Policy>\n");
649 EXEC SQL CLOSE csr_lpc;
657 db_error(sqlca.sqlcode);