8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / cmd / lp / lib / printers / putprinter.c
blobf7214dfe65b95e9cb03d7d09b2c793dc722f7551
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
20 * CDDL HEADER END
22 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
23 /* All Rights Reserved */
27 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
28 * Use is subject to license terms.
31 #pragma ident "%Z%%M% %I% %E% SMI"
33 /* EMACS_MODES: !fill, lnumb, !overwrite, !nodelete, !picture */
35 #include "sys/types.h"
36 #include "sys/stat.h"
37 #include "stdio.h"
38 #include "string.h"
39 #include "errno.h"
40 #include "stdlib.h"
42 #include "lp.h"
43 #include "printers.h"
45 #include <unistd.h>
46 #include <sys/wait.h>
48 #define SHELL "/bin/sh"
49 #define PPDZIP ".gz"
51 extern struct {
52 char *v;
53 short len,
54 okremote;
55 } prtrheadings[];
57 #if defined(__STDC__)
59 static void print_sdn (int, char *, SCALED);
60 static void print_l (int, char *, char **);
61 static void print_str (int, char *, char *);
63 #ifdef LP_USE_PAPI_ATTR
64 static int addPrintersPPD(char *name, PRINTER *prbufp);
65 static int copyPPDFile(char *ppd, char *printersPPD);
66 static int unzipPPDFile(char *ppd, char *printersPPD);
67 #endif
69 #else
71 static void print_sdn(),
72 print_l(),
73 print_str();
75 #ifdef LP_USE_PAPI_ATTR
76 static int addPrintersPPD();
77 static int copyPPDFile();
78 static int unzipPPDFile();
79 #endif
81 #endif
83 unsigned long ignprinter = 0;
84 int ppdopt = 0;
86 /**
87 ** putprinter() - WRITE PRINTER STRUCTURE TO DISK FILES
88 **/
90 int
91 putprinter(char *name, PRINTER *prbufp)
93 register char * path;
94 register char * stty;
95 register char * speed;
97 int fdin, fdout;
99 int fld;
101 char buf[BUFSIZ];
103 struct stat statbuf1,
104 statbuf2;
107 badprinter = 0;
109 if (!name || !*name) {
110 errno = EINVAL;
111 return (-1);
114 if (STREQU(NAME_ALL, name)) {
115 errno = EINVAL;
116 return (-1);
120 * First go through the structure and see if we have
121 * anything strange.
123 if (!okprinter(name, prbufp, 1)) {
124 errno = EINVAL;
125 return (-1);
128 if (!Lp_A_Printers || !Lp_A_Interfaces) {
129 getadminpaths (LPUSER);
130 if (!Lp_A_Printers || !Lp_A_Interfaces)
131 return (0);
135 * Create the parent directory for this printer
136 * if it doesn't yet exist.
138 if (!(path = getprinterfile(name, (char *)0)))
139 return (-1);
140 if (Stat(path, &statbuf1) == 0) {
141 if (!S_ISDIR(statbuf1.st_mode)) {
142 Free (path);
143 errno = ENOTDIR;
144 return (-1);
146 } else if (errno != ENOENT || mkdir_lpdir(path, MODE_DIR) == -1) {
147 Free (path);
148 return (-1);
150 Free (path);
153 * Create the copy of the interface program, unless
154 * that would be silly or not desired.
155 * Conversely, make sure the interface program doesn't
156 * exist for a remote printer.
158 if (prbufp->remote) {
159 if (!(path = makepath(Lp_A_Interfaces, name, (char *)0)))
160 return (-1);
161 (void)rmfile (path);
162 Free (path);
164 if (prbufp->interface && (ignprinter & BAD_INTERFACE) == 0) {
165 if (Stat(prbufp->interface, &statbuf1) == -1)
166 return (-1);
167 if (!(path = makepath(Lp_A_Interfaces, name, (char *)0)))
168 return (-1);
169 if (
170 Stat(path, &statbuf2) == -1
171 || statbuf1.st_dev != statbuf2.st_dev
172 || statbuf1.st_ino != statbuf2.st_ino
174 register int n;
176 if ((fdin = open_locked(prbufp->interface, "r", 0)) < 0) {
177 Free (path);
178 return (-1);
180 if ((fdout = open_locked(path, "w", MODE_EXEC)) < 0) {
181 Free (path);
182 close(fdin);
183 return (-1);
185 while ((n = read(fdin, buf, BUFSIZ)) > 0)
186 write (fdout, buf, n);
187 close(fdout);
188 close(fdin);
190 Free (path);
193 #ifdef LP_USE_PAPI_ATTR
195 * Handle PPD (Postscript Printer Definition) file for printer
196 * if this printer has been configured with one
198 if ((prbufp->ppd != NULL) && (ppdopt))
200 if (addPrintersPPD(name, prbufp) != 0)
202 /* failed to added the printers PPD file */
203 return (-1);
206 #endif
209 * If this printer is dialed up, remove any baud rates
210 * from the stty option list and move the last one to
211 * the ".speed" member if the ".speed" member isn't already
212 * set. Conversely, if this printer is directly connected,
213 * move any value from the ".speed" member to the stty list.
216 stty = (prbufp->stty? Strdup(prbufp->stty) : 0);
217 if (prbufp->speed)
218 speed = Strdup(prbufp->speed);
219 else
220 speed = 0;
222 if (prbufp->dial_info && stty) {
223 register char *newstty,
227 register int len;
229 if (!(q = newstty = Malloc(strlen(stty) + 1))) {
230 Free (stty);
231 errno = ENOMEM;
232 return (-1);
234 newstty[0] = 0; /* start with empty copy */
236 for (
237 p = strtok(stty, " ");
239 p = strtok((char *)0, " ")
241 len = strlen(p);
242 if (strspn(p, "0123456789") == len) {
244 * If "prbufp->speed" isn't set, then
245 * use the speed we just found. Don't
246 * check "speed", because if more than
247 * one speed was given in the list, we
248 * want the last one.
250 if (!prbufp->speed) {
251 if (speed)
252 Free (speed);
253 speed = Strdup(p);
256 } else {
258 * Not a speed, so copy it to the
259 * new stty string.
261 if (q != newstty)
262 *q++ = ' ';
263 strcpy (q, p);
264 q += len;
268 Free (stty);
269 stty = newstty;
271 } else if (!prbufp->dial_info && speed) {
272 register char *newstty;
274 newstty = Malloc(strlen(stty) + 1 + strlen(speed) + 1);
275 if (!newstty) {
276 if (stty)
277 Free (stty);
278 errno = ENOMEM;
279 return (-1);
282 if (stty) {
283 strcpy (newstty, stty);
284 strcat (newstty, " ");
285 strcat (newstty, speed);
286 Free (stty);
287 } else
288 strcpy (newstty, speed);
289 Free (speed);
290 speed = 0;
292 stty = newstty;
297 * Open the configuration file and write out the printer
298 * configuration.
301 if (!(path = getprinterfile(name, CONFIGFILE))) {
302 if (stty)
303 Free (stty);
304 if (speed)
305 Free (speed);
306 return (-1);
308 if ((fdout = open_locked(path, "w", MODE_READ)) < 0) {
309 Free (path);
310 if (stty)
311 Free (stty);
312 if (speed)
313 Free (speed);
314 return (-1);
316 Free (path);
318 errno = 0;
319 for (fld = 0; fld < PR_MAX; fld++) {
320 if (prbufp->remote && !prtrheadings[fld].okremote)
321 continue;
323 switch (fld) {
325 #define HEAD prtrheadings[fld].v
327 case PR_BAN:
329 char *ptr = NAME_ON;
331 switch (prbufp->banner) {
332 case BAN_ALWAYS:
333 ptr = NAME_ON;
334 break;
335 case BAN_NEVER:
336 ptr = NAME_OFF;
337 break;
338 case BAN_OPTIONAL:
339 ptr = NAME_OPTIONAL;
340 break;
342 (void)fdprintf(fdout, "%s %s\n", HEAD, ptr);
344 break;
346 case PR_CPI:
347 print_sdn(fdout, HEAD, prbufp->cpi);
348 break;
350 case PR_CS:
351 if (!emptylist(prbufp->char_sets))
352 print_l(fdout, HEAD, prbufp->char_sets);
353 break;
355 case PR_ITYPES:
357 * Put out the header even if the list is empty,
358 * to distinguish no input types from the default.
360 print_l(fdout, HEAD, prbufp->input_types);
361 break;
363 case PR_DEV:
364 print_str(fdout, HEAD, prbufp->device);
365 break;
367 case PR_DIAL:
368 print_str(fdout, HEAD, prbufp->dial_info);
369 break;
371 case PR_RECOV:
372 print_str(fdout, HEAD, prbufp->fault_rec);
373 break;
375 case PR_INTFC:
376 print_str(fdout, HEAD, prbufp->interface);
377 break;
379 case PR_LPI:
380 print_sdn(fdout, HEAD, prbufp->lpi);
381 break;
383 case PR_LEN:
384 print_sdn(fdout, HEAD, prbufp->plen);
385 break;
387 case PR_LOGIN:
388 if (prbufp->login & LOG_IN)
389 (void)fdprintf(fdout, "%s\n", HEAD);
390 break;
392 case PR_PTYPE:
394 char **printer_types;
397 * For backward compatibility for those who
398 * use only "->printer_type", we have to play
399 * some games here.
401 if (prbufp->printer_type && !prbufp->printer_types)
402 printer_types = getlist(
403 prbufp->printer_type,
404 LP_WS,
405 LP_SEP
407 else
408 printer_types = prbufp->printer_types;
410 if (!printer_types || !*printer_types)
411 print_str(fdout, HEAD, NAME_UNKNOWN);
412 else
413 print_l(fdout, HEAD, printer_types);
415 if (printer_types != prbufp->printer_types)
416 freelist (printer_types);
417 break;
420 case PR_REMOTE:
421 print_str(fdout, HEAD, prbufp->remote);
422 break;
424 case PR_SPEED:
425 print_str(fdout, HEAD, speed);
426 break;
428 case PR_STTY:
429 print_str(fdout, HEAD, stty);
430 break;
432 case PR_WIDTH:
433 print_sdn(fdout, HEAD, prbufp->pwid);
434 break;
436 #if defined(CAN_DO_MODULES)
437 case PR_MODULES:
439 * Put out the header even if the list is empty,
440 * to distinguish no modules from the default.
442 print_l(fdout, HEAD, prbufp->modules);
443 break;
444 #endif
446 case PR_OPTIONS:
447 print_l(fdout, HEAD, prbufp->options);
448 break;
450 case PR_PPD:
452 print_str(fdout, HEAD, prbufp->ppd);
453 break;
458 if (stty)
459 Free (stty);
460 if (speed)
461 Free (speed);
462 if (errno != 0) {
463 close(fdout);
464 return (-1);
466 close(fdout);
469 * If we have a description of the printer,
470 * write it out to a separate file.
472 if (prbufp->description) {
474 if (!(path = getprinterfile(name, COMMENTFILE)))
475 return (-1);
477 if (dumpstring(path, prbufp->description) == -1) {
478 Free (path);
479 return (-1);
481 Free (path);
486 * Now write out the alert condition.
488 if (
489 prbufp->fault_alert.shcmd
490 && putalert(Lp_A_Printers, name, &(prbufp->fault_alert)) == -1
492 return (-1);
494 return (0);
498 ** print_sdn() - PRINT SCALED DECIMAL NUMBER WITH HEADER
499 ** print_l() - PRINT (char **) LIST WITH HEADER
500 ** print_str() - PRINT STRING WITH HEADER
503 static void
504 print_sdn(int fd, char *head, SCALED sdn)
506 if (sdn.val <= 0)
507 return;
509 (void)fdprintf (fd, "%s ", head);
510 fdprintsdn (fd, sdn);
512 return;
515 static void
516 print_l(int fd, char *head, char **list)
518 (void)fdprintf (fd, "%s ", head);
519 printlist_setup (0, 0, LP_SEP, 0);
520 fdprintlist (fd, list);
521 printlist_unsetup ();
523 return;
526 static void
527 print_str(int fd, char *head, char *str)
529 if (!str || !*str)
530 return;
532 (void)fdprintf (fd, "%s %s\n", head, str);
534 return;
538 #ifdef LP_USE_PAPI_ATTR
540 * Function: addPrintersPPD()
542 * Description: Handle PPD (Postscript Printer Definition) file for this
543 * printer if it has been configured with one
547 static int
548 addPrintersPPD(char *name, PRINTER *prbufp)
551 int result = 0;
552 char *path = NULL;
553 char *ppd = NULL;
554 char buf[BUFSIZ];
555 struct stat statbuf;
557 (void) snprintf(buf, sizeof (buf), "%s.ppd", name);
558 if (prbufp->remote)
560 /* make sure the PPD file doesn't exist for a remote printer */
561 if (!(path = makepath(ETCDIR, "ppd", buf, (char *)0)))
563 result = -1;
565 else
567 (void) rmfile(path);
571 if ((result == 0) && (prbufp->ppd != NULL))
573 ppd = strdup(prbufp->ppd);
575 if (ppd == NULL)
577 result = -1;
579 else
581 /* Check the PPD file given exists */
583 if (Stat(ppd, &statbuf) == -1)
586 * The given ppd files does not exist, but
587 * check if there is a zipped version of the
588 * file that we can use instead
590 if (strstr(ppd, PPDZIP) != NULL)
592 /* this is a zipped file so exit */
593 result = -1;
595 else
597 ppd = Realloc(ppd,
598 strlen(ppd)+strlen(PPDZIP)+2);
599 if (ppd != NULL)
601 ppd = strcat(ppd, PPDZIP);
602 if (Stat(ppd, &statbuf) == -1)
605 * this zipped version
606 * of the file does not
607 * exist either
609 result = -1;
612 else
614 result = -1;
621 * Create the copy of the PPD file for this printer
622 * unless that would be silly or not desired
625 if (result == 0)
627 if (!(path = makepath(ETCDIR, "ppd", buf, (char *)0)))
629 result = -1;
634 * At this point we may have a zipped or unzipped ppd file, if
635 * it's unzipped just copy it otherwise unzip it to the
636 * printer's ppd file (/etc/lp/ppd/<printer>.ppd)
639 if (result == 0)
641 if (strstr(ppd, PPDZIP) == NULL)
643 result = copyPPDFile(ppd, path);
645 else
647 result = unzipPPDFile(ppd, path);
650 (void) chown_lppath(path);
651 (void) chmod(path, 0644);
654 if (ppd != NULL)
656 Free(ppd);
658 if (path != NULL)
660 Free(path);
664 return (result);
665 } /* addPrintersPPD() */
669 * Function: copyPPDFile()
671 * Description: Copy the given ppd file to the printer's file in /etc/lp/ppd
675 static int
676 copyPPDFile(char *ppd, char *printersPPD)
679 int result = 0;
680 register int n = 0;
681 int fdin = 0;
682 int fdout = 0;
683 char buf[BUFSIZ];
685 if ((ppd != NULL) && (printersPPD != NULL))
687 if ((fdin = open_locked(ppd, "r", 0)) < 0)
689 result = -1;
691 else
693 fdout = open_locked(printersPPD, "w", MODE_EXEC);
694 if (fdout < 0)
696 close(fdin);
697 result = -1;
701 if (result == 0)
703 while ((n = read(fdin, buf, BUFSIZ)) > 0)
705 write(fdout, buf, n);
707 close(fdout);
708 close(fdin);
711 else
713 result = -1;
716 return (result);
717 } /* copyPPDFile() */
722 * Function: unzipPPDFile()
724 * Description: Unzip the given ppd file to the printer's file in /etc/lp/ppd.
725 * This is done by forking and running the unzip utility on the
726 * zipped ppd file.
730 static int
731 unzipPPDFile(char *ppd, char *printersPPD)
734 int result = -1;
735 char *cmdLine = NULL;
736 pid_t childPID = 0;
737 int stat = 0;
738 int clSize = 0;
741 if ((ppd != NULL) && (printersPPD != NULL))
743 childPID = fork();
745 switch (childPID)
747 case -1:
749 /* return error */
750 break;
753 case 0:
755 /* child process - so execute something */
757 clSize = strlen("/usr/bin/rm -f ") +
758 strlen(printersPPD) +
759 strlen("/usr/bin/gzip -dc ") +
760 strlen(ppd) +
761 strlen(printersPPD) + 20;
762 cmdLine = malloc(clSize);
763 if (cmdLine != NULL)
766 (void) snprintf(cmdLine, clSize,
767 "/usr/bin/rm -f %s; /usr/bin/gzip -dc %s > %s",
768 printersPPD, ppd,
769 printersPPD);
770 result = execl(SHELL, SHELL, "-c",
771 cmdLine, NULL);
772 exit(result);
774 break;
777 default:
779 /* parent process, child pid is in childPID */
781 while (wait(&stat) != childPID);
783 if ((stat & 0xff00) == 0)
785 result = 0;
787 break;
792 return (result);
793 } /* unzipPPDFile() */
794 #endif