2 * "$Id: cupsaddsmb.c 5187 2006-02-26 20:36:03Z mike $"
4 * "cupsaddsmb" command for the Common UNIX Printing System (CUPS).
6 * Copyright 2001-2006 by Easy Software Products.
8 * These coded instructions, statements, and computer programs are the
9 * property of Easy Software Products and are protected by Federal
10 * copyright law. Distribution and use rights are outlined in the file
11 * "LICENSE.txt" which should have been included with this file. If this
12 * file is missing or damaged please contact Easy Software Products
15 * Attn: CUPS Licensing Information
16 * Easy Software Products
17 * 44141 Airport View Drive, Suite 204
18 * Hollywood, Maryland 20636 USA
20 * Voice: (301) 373-9600
21 * EMail: cups-info@cups.org
22 * WWW: http://www.cups.org
26 * main() - Export printers on the command-line.
27 * convert_ppd() - Convert a PPD file to a form usable by any of the
28 * Windows PostScript printer drivers.
29 * do_samba_command() - Do a SAMBA command, asking for a password as needed.
30 * export_dest() - Export a destination to SAMBA.
31 * ppd_gets() - Get a CR and/or LF-terminated line.
32 * usage() - Show program usage and exit...
33 * write_option() - Write a CUPS option to a PPD file.
37 * Include necessary headers...
42 #include <cups/string.h>
43 #include <cups/cups.h>
44 #include <cups/i18n.h>
45 #include <cups/debug.h>
57 const char *SAMBAUser
,
66 int convert_ppd(const char *src
, char *dst
, int dstsize
, ipp_t
*info
);
67 int do_samba_command(const char *command
, const char *address
,
68 const char *subcommand
);
69 int export_dest(const char *dest
);
70 char *ppd_gets(FILE *fp
, char *buf
, int buflen
);
72 int write_option(FILE *dstfp
, int order
, const char *name
,
73 const char *text
, const char *attrname
,
74 ipp_attribute_t
*suppattr
, ipp_attribute_t
*defattr
,
75 int defval
, int valcount
);
79 * 'main()' - Export printers on the command-line.
82 int /* O - Exit status */
83 main(int argc
, /* I - Number of command-line arguments */
84 char *argv
[]) /* I - Command-line arguments */
86 int i
, j
; /* Looping vars */
87 int status
; /* Status from export_dest() */
88 int export_all
; /* Export all printers? */
89 int num_dests
; /* Number of printers */
90 cups_dest_t
*dests
; /* Printers */
94 * Parse command-line arguments...
99 SAMBAUser
= cupsUser();
100 SAMBAPassword
= NULL
;
103 for (i
= 1; i
< argc
; i
++)
104 if (!strcmp(argv
[i
], "-a"))
106 else if (!strcmp(argv
[i
], "-U"))
108 char *sep
; /* Separator for password */
117 if ((sep
= strchr(argv
[i
], '%')) != NULL
)
120 * Nul-terminate the username at the first % and point the
121 * password at the rest...
129 else if (!strcmp(argv
[i
], "-H"))
135 SAMBAServer
= argv
[i
];
137 else if (!strcmp(argv
[i
], "-h"))
143 cupsSetServer(argv
[i
]);
145 else if (!strcmp(argv
[i
], "-v"))
147 else if (argv
[i
][0] != '-')
149 if (SAMBAServer
== NULL
)
150 SAMBAServer
= cupsServer();
152 if ((status
= export_dest(argv
[i
])) != 0)
159 * See if the user specified "-a"...
165 * Export all printers...
168 if (SAMBAServer
== NULL
)
169 SAMBAServer
= cupsServer();
171 num_dests
= cupsGetDests(&dests
);
173 for (j
= 0, status
= 0; j
< num_dests
; j
++)
174 if (!dests
[j
].instance
)
176 if ((status
= export_dest(dests
[j
].name
)) != 0)
180 cupsFreeDests(num_dests
, dests
);
191 * 'convert_ppd()' - Convert a PPD file to a form usable by any of the
192 * Windows PostScript printer drivers.
195 int /* O - 0 on success, 1 on failure */
196 convert_ppd(const char *src
, /* I - Source (original) PPD */
197 char *dst
, /* O - Destination PPD */
198 int dstsize
, /* I - Size of destination buffer */
199 ipp_t
*info
) /* I - Printer attributes */
201 FILE *srcfp
, /* Source file */
202 *dstfp
; /* Destination file */
203 int dstfd
; /* Destination file descriptor */
204 ipp_attribute_t
*suppattr
, /* IPP -supported attribute */
205 *defattr
; /* IPP -default attribute */
206 char line
[256], /* Line from PPD file */
207 junk
[256], /* Extra junk to throw away */
208 *ptr
, /* Pointer into line */
209 option
[41], /* Option */
210 choice
[41]; /* Choice */
211 int jcloption
, /* In a JCL option? */
212 linenum
; /* Current line number */
213 time_t curtime
; /* Current time */
214 struct tm
*curdate
; /* Current date */
218 * Open the original PPD file...
221 if ((srcfp
= fopen(src
, "rb")) == NULL
)
225 * Create a temporary output file using the destination buffer...
228 if ((dstfd
= cupsTempFd(dst
, dstsize
)) < 0)
235 if ((dstfp
= fdopen(dstfd
, "w")) == NULL
)
238 * Unable to convert to FILE *...
249 * Write a new header explaining that this isn't the original PPD...
252 fputs("*PPD-Adobe: \"4.3\"\n", dstfp
);
254 curtime
= time(NULL
);
255 curdate
= gmtime(&curtime
);
257 fprintf(dstfp
, "*%% Modified on %04d%02d%02d%02d%02d%02d+0000 by cupsaddsmb\n",
258 curdate
->tm_year
+ 1900, curdate
->tm_mon
+ 1, curdate
->tm_mday
,
259 curdate
->tm_hour
, curdate
->tm_min
, curdate
->tm_sec
);
262 * Read the existing PPD file, converting all PJL commands to CUPS
263 * job ticket comments...
269 while (ppd_gets(srcfp
, line
, sizeof(line
)) != NULL
)
273 if (!strncmp(line
, "*PPD-Adobe:", 11))
276 * Already wrote the PPD header...
281 else if (!strncmp(line
, "*JCLBegin:", 10) ||
282 !strncmp(line
, "*JCLToPSInterpreter:", 20) ||
283 !strncmp(line
, "*JCLEnd:", 8) ||
284 !strncmp(line
, "*Protocols:", 11))
287 * Don't use existing JCL keywords; we'll create our own, below...
290 fprintf(dstfp
, "*%% Commented out by cupsaddsmb...\n*%%%s", line
+ 1);
293 else if (!strncmp(line
, "*JCLOpenUI", 10))
298 else if (!strncmp(line
, "*JCLCloseUI", 11))
303 else if (jcloption
&&
304 strncmp(line
, "*End", 4) &&
305 strncmp(line
, "*Default", 8) &&
306 strncmp(line
, "*OrderDependency", 16))
308 if ((ptr
= strchr(line
, ':')) == NULL
)
310 _cupsLangPrintf(stderr
,
311 _("cupsaddsmb: Missing value on line %d!\n"), linenum
);
319 if ((ptr
= strchr(ptr
, '\"')) == NULL
)
321 _cupsLangPrintf(stderr
,
322 _("cupsaddsmb: Missing double quote on line %d!\n"),
331 if (sscanf(line
, "*%40s%*[ \t]%40[^/]", option
, choice
) != 2)
333 _cupsLangPrintf(stderr
,
334 _("cupsaddsmb: Bad option + choice on line %d!\n"),
343 if (strchr(ptr
+ 1, '\"') == NULL
)
349 while (ppd_gets(srcfp
, junk
, sizeof(junk
)) != NULL
)
353 if (!strncmp(junk
, "*End", 4))
358 snprintf(ptr
+ 1, sizeof(line
) - (ptr
- line
+ 1),
359 "%%cupsJobTicket: %s=%s\n\"\n*End\n", option
, choice
);
361 fprintf(dstfp
, "*%% Changed by cupsaddsmb...\n%s", line
);
370 * Now add the CUPS-specific attributes and options...
373 fputs("\n*% CUPS Job Ticket support and options...\n", dstfp
);
374 fputs("*Protocols: PJL\n", dstfp
);
375 fputs("*JCLBegin: \"%!PS-Adobe-3.0<0A>\"\n", dstfp
);
376 fputs("*JCLToPSInterpreter: \"\"\n", dstfp
);
377 fputs("*JCLEnd: \"\"\n", dstfp
);
379 fputs("\n*OpenGroup: CUPS/CUPS Options\n\n", dstfp
);
381 if ((defattr
= ippFindAttribute(info
, "job-hold-until-default",
382 IPP_TAG_ZERO
)) != NULL
&&
383 (suppattr
= ippFindAttribute(info
, "job-hold-until-supported",
384 IPP_TAG_ZERO
)) != NULL
)
385 write_option(dstfp
, 10, "cupsJobHoldUntil", "Hold Until", "job-hold-until",
386 suppattr
, defattr
, 0, 1);
388 if ((defattr
= ippFindAttribute(info
, "job-priority-default",
389 IPP_TAG_INTEGER
)) != NULL
&&
390 (suppattr
= ippFindAttribute(info
, "job-priority-supported",
391 IPP_TAG_RANGE
)) != NULL
)
392 write_option(dstfp
, 11, "cupsJobPriority", "Priority", "job-priority",
393 suppattr
, defattr
, 0, 1);
395 if ((defattr
= ippFindAttribute(info
, "job-sheets-default",
396 IPP_TAG_ZERO
)) != NULL
&&
397 (suppattr
= ippFindAttribute(info
, "job-sheets-supported",
398 IPP_TAG_ZERO
)) != NULL
)
400 write_option(dstfp
, 20, "cupsJobSheetsStart", "Start Banner",
401 "job-sheets", suppattr
, defattr
, 0, 2);
402 write_option(dstfp
, 21, "cupsJobSheetsEnd", "End Banner",
403 "job-sheets", suppattr
, defattr
, 1, 2);
406 fputs("*CloseGroup: CUPS\n", dstfp
);
416 * 'do_samba_command()' - Do a SAMBA command, asking for
417 * a password as needed.
420 int /* O - Status of command */
421 do_samba_command(const char *command
, /* I - Command to run */
422 const char *address
, /* I - Address for command */
423 const char *subcmd
) /* I - Sub-command */
425 int status
; /* Status of command */
426 char temp
[4096]; /* Command/prompt string */
427 int pid
; /* Process ID of child */
430 DEBUG_printf(("do_samba_command(command=\"%s\", address=\"%s\", subcmd=\"%s\")\n",
431 command
, address
, subcmd
));
432 DEBUG_printf(("SAMBAUser=\"%s\", SAMBAPassword=\"%s\"\n", SAMBAUser
,
435 for (status
= 1; status
; )
439 snprintf(temp
, sizeof(temp
),
440 _("Password for %s required to access %s via SAMBA: "),
441 SAMBAUser
, SAMBAServer
);
443 if ((SAMBAPassword
= cupsGetPassword(temp
)) == NULL
)
447 snprintf(temp
, sizeof(temp
), "%s%%%s", SAMBAUser
, SAMBAPassword
);
450 _cupsLangPrintf(stdout
,
451 _("Running command: %s %s -N -U \'%s%%%s\' -c \'%s\'\n"),
452 command
, address
, SAMBAUser
, SAMBAPassword
, subcmd
);
454 if ((pid
= fork()) == 0)
457 * Child goes here, redirect stdin/out/err and execute the command...
461 open("/dev/null", O_RDONLY
);
466 open("/dev/null", O_WRONLY
);
471 execlp(command
, command
, address
, "-N", "-U", temp
, "-c", subcmd
,
479 _cupsLangPrintf(stderr
, _("cupsaddsmb: Unable to run \"%s\": %s\n"),
480 command
, strerror(errno
));
485 * Wait for the process to complete...
488 while (wait(&status
) != pid
);
491 DEBUG_printf(("status=%d\n", status
));
494 _cupsLangPuts(stdout
, "\n");
498 if (SAMBAPassword
[0])
499 SAMBAPassword
= NULL
;
510 * 'export_dest()' - Export a destination to SAMBA.
513 int /* O - 0 on success, non-zero on error */
514 export_dest(const char *dest
) /* I - Destination to export */
516 int status
; /* Status of smbclient/rpcclient commands */
517 int have_drivers
; /* Have drivers? */
518 const char *ppdfile
; /* PPD file for printer drivers */
519 char newppd
[1024], /* New PPD file for printer drivers */
520 file
[1024], /* File to test for */
521 address
[1024], /* Address for command */
522 uri
[1024], /* Printer URI */
523 subcmd
[1024]; /* Sub-command */
524 const char *datadir
; /* CUPS_DATADIR */
525 http_t
*http
; /* Connection to server */
526 ipp_t
*request
, /* IPP request */
527 *response
; /* IPP response */
528 static const char *pattrs
[] = /* Printer attributes we want */
530 "job-hold-until-supported",
531 "job-hold-until-default",
532 "job-sheets-supported",
533 "job-sheets-default",
534 "job-priority-supported",
535 "job-priority-default"
540 * Get the location of the printer driver files...
543 if ((datadir
= getenv("CUPS_DATADIR")) == NULL
)
544 datadir
= CUPS_DATADIR
;
547 * Open a connection to the scheduler...
550 if ((http
= httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption())) == NULL
)
552 _cupsLangPrintf(stderr
,
553 _("cupsaddsmb: Unable to connect to server \"%s\" for "
555 cupsServer(), dest
, strerror(errno
));
560 * Get the PPD file...
563 if ((ppdfile
= cupsGetPPD2(http
, dest
)) == NULL
)
565 _cupsLangPrintf(stderr
,
566 _("cupsaddsmb: No PPD file for printer \"%s\" - "
568 dest
, cupsLastErrorString());
574 * Append the supported banner pages to the PPD file...
577 request
= ippNewRequest(IPP_GET_PRINTER_ATTRIBUTES
);
579 httpAssembleURIf(HTTP_URI_CODING_ALL
, uri
, sizeof(uri
), "ipp", NULL
,
580 "localhost", 0, "/printers/%s", dest
);
581 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
582 "printer-uri", NULL
, uri
);
584 ippAddStrings(request
, IPP_TAG_OPERATION
, IPP_TAG_KEYWORD
,
585 "requested-attributes", sizeof(pattrs
) / sizeof(pattrs
[0]),
589 * Do the request and get back a response...
592 if ((response
= cupsDoRequest(http
, request
, "/")) != NULL
)
594 if (response
->request
.status
.status_code
> IPP_OK_CONFLICT
)
596 _cupsLangPrintf(stderr
, "cupsaddsmb: %s - %s\n", dest
,
597 cupsLastErrorString());
606 _cupsLangPrintf(stderr
, "cupsaddsmb: %s - %s\n", dest
,
607 cupsLastErrorString());
614 * Convert the PPD file to the Windows driver format...
617 if (convert_ppd(ppdfile
, newppd
, sizeof(newppd
), response
))
619 _cupsLangPrintf(stderr
,
620 _("cupsaddsmb: Unable to convert PPD file for %s - %s\n"),
621 dest
, strerror(errno
));
632 * Remove the old PPD and point to the new one...
640 * See which drivers are available; the new CUPS v6 and Adobe drivers
641 * depend on the Windows 2k PS driver, so copy that driver first:
653 snprintf(file
, sizeof(file
), "%s/drivers/pscript5.dll", datadir
);
654 if (!access(file
, 0))
659 * Windows 2k driver is installed; do the smbclient commands needed
660 * to copy the Win2k drivers over...
663 snprintf(address
, sizeof(address
), "//%s/print$", SAMBAServer
);
665 snprintf(subcmd
, sizeof(subcmd
),
667 "put %s W32X86/%s.ppd;"
668 "put %s/drivers/ps5ui.dll W32X86/ps5ui.dll;"
669 "put %s/drivers/pscript.hlp W32X86/pscript.hlp;"
670 "put %s/drivers/pscript.ntf W32X86/pscript.ntf;"
671 "put %s/drivers/pscript5.dll W32X86/pscript5.dll",
672 ppdfile
, dest
, datadir
, datadir
, datadir
, datadir
);
674 if ((status
= do_samba_command("smbclient", address
, subcmd
)) != 0)
676 _cupsLangPrintf(stderr
,
677 _("cupsaddsmb: Unable to copy Windows 2000 printer "
678 "driver files (%d)!\n"),
685 * See if we also have the CUPS driver files; if so, use them!
688 snprintf(file
, sizeof(file
), "%s/drivers/cupsps6.dll", datadir
);
689 if (!access(file
, 0))
692 * Copy the CUPS driver files over...
695 snprintf(subcmd
, sizeof(subcmd
),
696 "put %s/drivers/cups6.ini W32X86/cups6.ini;"
697 "put %s/drivers/cupsps6.dll W32X86/cupsps6.dll;"
698 "put %s/drivers/cupsui6.dll W32X86/cupsui6.dll",
699 datadir
, datadir
, datadir
);
701 if ((status
= do_samba_command("smbclient", address
, subcmd
)) != 0)
703 _cupsLangPrintf(stderr
,
704 _("cupsaddsmb: Unable to copy CUPS printer driver "
712 * Do the rpcclient command needed for the CUPS drivers...
715 snprintf(subcmd
, sizeof(subcmd
),
716 "adddriver \"Windows NT x86\" \"%s:"
717 "pscript5.dll:%s.ppd:ps5ui.dll:pscript.hlp:NULL:RAW:"
718 "pscript5.dll,%s.ppd,ps5ui.dll,pscript.hlp,pscript.ntf,"
719 "cups6.ini,cupsps6.dll,cupsui6.dll\"",
725 * Don't have the CUPS drivers, so just use the standard Windows
729 snprintf(subcmd
, sizeof(subcmd
),
730 "adddriver \"Windows NT x86\" \"%s:"
731 "pscript5.dll:%s.ppd:ps5ui.dll:pscript.hlp:NULL:RAW:"
732 "pscript5.dll,%s.ppd,ps5ui.dll,pscript.hlp,pscript.ntf\"",
736 if ((status
= do_samba_command("rpcclient", SAMBAServer
, subcmd
)) != 0)
738 _cupsLangPrintf(stderr
,
739 _("cupsaddsmb: Unable to install Windows 2000 printer "
740 "driver files (%d)!\n"),
747 snprintf(file
, sizeof(file
), "%s/drivers/ADOBEPS4.DRV", datadir
);
748 if (!access(file
, 0))
753 * Do the smbclient commands needed for the Adobe Win9x drivers...
756 snprintf(address
, sizeof(address
), "//%s/print$", SAMBAServer
);
758 snprintf(subcmd
, sizeof(subcmd
),
760 "put %s WIN40/%s.PPD;"
761 "put %s/drivers/ADFONTS.MFM WIN40/ADFONTS.MFM;"
762 "put %s/drivers/ADOBEPS4.DRV WIN40/ADOBEPS4.DRV;"
763 "put %s/drivers/ADOBEPS4.HLP WIN40/ADOBEPS4.HLP;"
764 "put %s/drivers/ICONLIB.DLL WIN40/ICONLIB.DLL;"
765 "put %s/drivers/PSMON.DLL WIN40/PSMON.DLL;",
766 ppdfile
, dest
, datadir
, datadir
, datadir
, datadir
, datadir
);
768 if ((status
= do_samba_command("smbclient", address
, subcmd
)) != 0)
770 _cupsLangPrintf(stderr
,
771 _("cupsaddsmb: Unable to copy Windows 9x printer "
772 "driver files (%d)!\n"),
779 * Do the rpcclient commands needed for the Adobe Win9x drivers...
782 snprintf(subcmd
, sizeof(subcmd
),
783 "adddriver \"Windows 4.0\" \"%s:ADOBEPS4.DRV:%s.PPD:NULL:"
784 "ADOBEPS4.HLP:PSMON.DLL:RAW:"
785 "ADOBEPS4.DRV,%s.PPD,ADOBEPS4.HLP,PSMON.DLL,ADFONTS.MFM,"
789 if ((status
= do_samba_command("rpcclient", SAMBAServer
, subcmd
)) != 0)
791 _cupsLangPrintf(stderr
,
792 _("cupsaddsmb: Unable to install Windows 9x printer "
793 "driver files (%d)!\n"),
802 if (have_drivers
== 0)
804 _cupsLangPuts(stderr
,
805 _("cupsaddsmb: No Windows printer drivers are installed!\n"));
808 else if (have_drivers
== 2)
809 _cupsLangPuts(stderr
,
810 _("cupsaddsmb: Warning, no Windows 2000 printer drivers "
811 "are installed!\n"));
814 * Finally, associate the drivers we just added with the queue...
817 snprintf(subcmd
, sizeof(subcmd
), "setdriver %s %s", dest
, dest
);
819 if ((status
= do_samba_command("rpcclient", SAMBAServer
, subcmd
)) != 0)
821 _cupsLangPrintf(stderr
,
822 _("cupsaddsmb: Unable to set Windows printer driver (%d)!\n"),
832 * 'ppd_gets()' - Get a CR and/or LF-terminated line.
835 char * /* O - Line read or NULL on eof/error */
836 ppd_gets(FILE *fp
, /* I - File to read from*/
837 char *buf
, /* O - String buffer */
838 int buflen
) /* I - Size of string buffer */
840 int ch
; /* Character from file */
841 char *ptr
, /* Current position in line buffer */
842 *end
; /* End of line buffer */
846 * Range check input...
849 if (!fp
|| !buf
|| buflen
< 2 || feof(fp
))
853 * Now loop until we have a valid line...
856 for (ptr
= buf
, end
= buf
+ buflen
- 1; ptr
< end
;)
858 if ((ch
= getc(fp
)) == EOF
)
874 if ((ch
= getc(fp
)) != '\n')
884 * Line feed ends a line...
898 * 'usage()' - Show program usage and exit...
904 _cupsLangPuts(stdout
,
905 _("Usage: cupsaddsmb [options] printer1 ... printerN\n"
906 " cupsaddsmb [options] -a\n"
909 " -H samba-server Use the named SAMBA server\n"
910 " -U samba-user Authenticate using the named SAMBA user\n"
911 " -a Export all printers\n"
912 " -h cups-server Use the named CUPS server\n"
913 " -v Be verbose (show commands)\n"));
919 * 'write_option()' - Write a CUPS option to a PPD file.
922 int /* O - 0 on success, 1 on failure */
923 write_option(FILE *dstfp
, /* I - PPD file */
924 int order
, /* I - Order dependency */
925 const char *name
, /* I - Option name */
926 const char *text
, /* I - Option text */
927 const char *attrname
, /* I - Attribute name */
928 ipp_attribute_t
*suppattr
, /* I - IPP -supported attribute */
929 ipp_attribute_t
*defattr
, /* I - IPP -default attribute */
930 int defval
, /* I - Default value number */
931 int valcount
) /* I - Number of values */
933 int i
; /* Looping var */
936 if (!dstfp
|| !name
|| !text
|| !suppattr
|| !defattr
)
939 fprintf(dstfp
, "*JCLOpenUI *%s/%s: PickOne\n"
940 "*OrderDependency: %d JCLSetup *%s\n",
941 name
, text
, order
, name
);
943 if (defattr
->value_tag
== IPP_TAG_INTEGER
)
946 * Do numeric options with a range or list...
949 fprintf(dstfp
, "*Default%s: %d\n", name
, defattr
->values
[defval
].integer
);
951 if (suppattr
->value_tag
== IPP_TAG_RANGE
)
954 * List each number in the range...
957 for (i
= suppattr
->values
[0].range
.lower
;
958 i
<= suppattr
->values
[0].range
.upper
;
961 fprintf(dstfp
, "*%s %d: \"", name
, i
);
964 fprintf(dstfp
, "%%cupsJobTicket: %s=%d\n\"\n*End\n", attrname
, i
);
965 else if (defval
== 0)
966 fprintf(dstfp
, "%%cupsJobTicket: %s=%d\"\n", attrname
, i
);
967 else if (defval
< (valcount
- 1))
968 fprintf(dstfp
, ",%d\"\n", i
);
970 fprintf(dstfp
, ",%d\n\"\n*End\n", i
);
976 * List explicit numbers...
979 for (i
= 0; i
< suppattr
->num_values
; i
++)
981 fprintf(dstfp
, "*%s %d: \"", name
, suppattr
->values
[i
].integer
);
984 fprintf(dstfp
, "%%cupsJobTicket: %s=%d\n\"\n*End\n", attrname
,
985 suppattr
->values
[i
].integer
);
986 else if (defval
== 0)
987 fprintf(dstfp
, "%%cupsJobTicket: %s=%d\"\n", attrname
,
988 suppattr
->values
[i
].integer
);
989 else if (defval
< (valcount
- 1))
990 fprintf(dstfp
, ",%d\"\n", suppattr
->values
[i
].integer
);
992 fprintf(dstfp
, ",%d\n\"\n*End\n", suppattr
->values
[i
].integer
);
999 * Do text options with a list...
1002 fprintf(dstfp
, "*Default%s: %s\n", name
,
1003 defattr
->values
[defval
].string
.text
);
1005 for (i
= 0; i
< suppattr
->num_values
; i
++)
1007 fprintf(dstfp
, "*%s %s: \"", name
, suppattr
->values
[i
].string
.text
);
1010 fprintf(dstfp
, "%%cupsJobTicket: %s=%s\n\"\n*End\n", attrname
,
1011 suppattr
->values
[i
].string
.text
);
1012 else if (defval
== 0)
1013 fprintf(dstfp
, "%%cupsJobTicket: %s=%s\"\n", attrname
,
1014 suppattr
->values
[i
].string
.text
);
1015 else if (defval
< (valcount
- 1))
1016 fprintf(dstfp
, ",%s\"\n", suppattr
->values
[i
].string
.text
);
1018 fprintf(dstfp
, ",%s\n\"\n*End\n", suppattr
->values
[i
].string
.text
);
1022 fprintf(dstfp
, "*JCLCloseUI: *%s\n\n", name
);
1029 * End of "$Id: cupsaddsmb.c 5187 2006-02-26 20:36:03Z mike $".