/* * "$Id: cupsaddsmb.c,v 1.1.1.11 2002/12/24 00:07:38 jlovell Exp $" * * "cupsaddsmb" command for the Common UNIX Printing System (CUPS). * * Copyright 2001-2003 by Easy Software Products. * * These coded instructions, statements, and computer programs are the * property of Easy Software Products and are protected by Federal * copyright law. Distribution and use rights are outlined in the file * "LICENSE.txt" which should have been included with this file. If this * file is missing or damaged please contact Easy Software Products * at: * * Attn: CUPS Licensing Information * Easy Software Products * 44141 Airport View Drive, Suite 204 * Hollywood, Maryland 20636-3111 USA * * Voice: (301) 373-9603 * EMail: cups-info@cups.org * WWW: http://www.cups.org * * Contents: * * main() - Export printers on the command-line. * do_samba_command() - Do a SAMBA command, asking for a password as needed. * export_dest() - Export a destination to SAMBA. * usage() - Show program usage and exit... */ /* * Include necessary headers... */ #include #include #include #include #include #include /* * Local globals... */ int Verbosity = 0; const char *SAMBAUser, *SAMBAServer; /* * Local functions... */ int do_samba_command(const char *, const char *); int export_dest(const char *); void usage(); /* * 'main()' - Export printers on the command-line. */ int /* O - Exit status */ main(int argc, /* I - Number of command-line arguments */ char *argv[]) /* I - Command-line arguments */ { int i, j; /* Looping vars */ int status; /* Status from export_dest() */ int export_all; /* Export all printers? */ int num_printers; /* Number of printers */ char **printers; /* Printers */ /* * Parse command-line arguments... */ export_all = 0; SAMBAUser = cupsUser(); SAMBAServer = NULL; for (i = 1; i < argc; i ++) if (strcmp(argv[i], "-a") == 0) export_all = 1; else if (strcmp(argv[i], "-U") == 0) { i ++; if (i >= argc) usage(); SAMBAUser = argv[i]; } else if (strcmp(argv[i], "-H") == 0) { i ++; if (i >= argc) usage(); SAMBAServer = argv[i]; } else if (strcmp(argv[i], "-h") == 0) { i ++; if (i >= argc) usage(); cupsSetServer(argv[i]); } else if (strcmp(argv[i], "-v") == 0) Verbosity = 1; else if (argv[i][0] != '-') { if (SAMBAServer == NULL) SAMBAServer = cupsServer(); if ((status = export_dest(argv[i])) != 0) return (status); } else usage(); /* * See if the user specified "-a"... */ if (export_all) { /* * Export all printers... */ if (SAMBAServer == NULL) SAMBAServer = cupsServer(); num_printers = cupsGetPrinters(&printers); for (j = 0, status = 0; j < num_printers; j ++) if ((status = export_dest(printers[j])) != 0) break; for (j = 0; j < num_printers; j ++) free(printers[j]); if (num_printers) free(printers); if (status) return (status); } return (0); } /* * 'do_samba_command()' - Do a SAMBA command, asking for * a password as needed. */ int /* O - Status of command */ do_samba_command(const char *command, /* I - Command to run */ const char *subcmd) /* I - Sub-command */ { int status; /* Status of command */ char temp[4096]; /* Command/prompt string */ static const char *p = NULL; /* Password data */ for (status = 1;;) { if (p == NULL) { snprintf(temp, sizeof(temp), "Password for %s required to access %s via SAMBA: ", SAMBAUser, SAMBAServer); if ((p = cupsGetPassword(temp)) == NULL) break; } snprintf(temp, sizeof(temp), "%s -N -U\'%s%%%s\' -c \'%s\'", command, SAMBAUser, p, subcmd); if (Verbosity) printf("Running command: %s\n", temp); else strlcat(temp, " /dev/null 2>/dev/null", sizeof(temp)); if ((status = system(temp)) != 0) { if (Verbosity) puts(""); if (p[0]) p = NULL; else break; } else { if (Verbosity) puts(""); break; } } return (status); } /* * 'export_dest()' - Export a destination to SAMBA. */ int /* O - 0 on success, non-zero on error */ export_dest(const char *dest) /* I - Destination to export */ { int i; /* Looping var */ int status; /* Status of smbclient/rpcclient commands */ const char *ppdfile; /* PPD file for printer drivers */ char command[1024], /* Command to run */ subcmd[1024]; /* Sub-command */ const char *datadir; /* CUPS_DATADIR */ FILE *fp; /* PPD file */ http_t *http; /* Connection to server */ cups_lang_t *language; /* Default language */ ipp_t *request, /* IPP request */ *response; /* IPP response */ ipp_attribute_t *attr; /* IPP attribute */ static const char *pattrs[] = /* Printer attributes we want */ { "job-sheets-supported", "job-sheets-default" }; if ((datadir = getenv("CUPS_DATADIR")) == NULL) datadir = CUPS_DATADIR; /* * Get the PPD file... */ if ((ppdfile = cupsGetPPD(dest)) == NULL) { fprintf(stderr, "Warning: No PPD file for printer \"%s\" - skipping!\n", dest); return (0); } /* * Append the supported banner pages to the PPD file... */ if ((http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption())) == NULL) { fprintf(stderr, "Unable to connect to server \"%s\" for %s - %s\n", cupsServer(), dest, strerror(errno)); unlink(ppdfile); return (1); } request = ippNew(); request->request.op.operation_id = IPP_GET_PRINTER_ATTRIBUTES; request->request.op.request_id = 1; language = cupsLangDefault(); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET, "attributes-charset", NULL, cupsLangEncoding(language)); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, "attributes-natural-language", NULL, language->language); snprintf(command, sizeof(command), "ipp://localhost/printers/%s", dest); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, command); ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "requested-attributes", sizeof(pattrs) / sizeof(pattrs[0]), NULL, pattrs); /* * Do the request and get back a response... */ if ((response = cupsDoRequest(http, request, "/")) != NULL) { if (response->request.status.status_code > IPP_OK_CONFLICT) { fprintf(stderr, "ERROR: get-printer-attributes failed for %s: %s\n", dest, ippErrorString(response->request.status.status_code)); ippDelete(response); unlink(ppdfile); return (2); } } else { fprintf(stderr, "ERROR: get-printer-attributes failed for %s: %s\n", dest, ippErrorString(cupsLastError())); unlink(ppdfile); return (2); } /* * Append the banner attributes to the end of the PPD file... */ if ((fp = fopen(ppdfile, "a")) == NULL) { fprintf(stderr, "ERROR: Unable to append banner attributes to PPD file for %s - %s\n", dest, strerror(errno)); ippDelete(response); unlink(ppdfile); return (3); } if ((attr = ippFindAttribute(response, "job-sheets-supported", IPP_TAG_NAME)) != NULL) { fprintf(fp, "*cupsJobSheetsSupported: \"%s", attr->values[0].string.text); for (i = 1; i < attr->num_values; i ++) fprintf(fp, ",%s", attr->values[i].string.text); fputs("\"\n", fp); } if ((attr = ippFindAttribute(response, "job-sheets-default", IPP_TAG_NAME)) != NULL) { fprintf(fp, "*cupsJobSheetsDefault: \"%s", attr->values[0].string.text); if (attr->num_values > 1) fprintf(fp, ",%s", attr->values[1].string.text); fputs("\"\n", fp); } fclose(fp); ippDelete(response); cupsLangFree(language); httpClose(http); /* * See which drivers are available - the new CUPS drivers or the * Adobe drivers? */ snprintf(command, sizeof(command), "%s/drivers/cupsdrvr.dll", datadir); if (access(command, 0) == 0) { /* * Do the smbclient commands needed for the CUPS WinNT drivers... */ snprintf(command, sizeof(command), "smbclient //%s/print\\$", SAMBAServer); snprintf(subcmd, sizeof(subcmd), "mkdir W32X86;" "put %s W32X86/%s.ppd;" "put %s/drivers/cupsdrvr.dll W32X86/cupsdrvr.dll;" "put %s/drivers/cupsui.dll W32X86/cupsui.dll;" "put %s/drivers/cups.hlp W32X86/cups.hlp", ppdfile, dest, datadir, datadir, datadir); if ((status = do_samba_command(command, subcmd)) != 0) { fprintf(stderr, "ERROR: Unable to copy Windows printer driver files (%d)!\n", status); unlink(ppdfile); return (4); } /* * Do the rpcclient commands needed for the CUPS WinNT drivers... */ snprintf(subcmd, sizeof(subcmd), "adddriver \"Windows NT x86\" \"%s:cupsdrvr.dll:%s.ppd:cupsui.dll:cups.hlp:NULL:RAW:NULL\"", dest, dest); snprintf(command, sizeof(command), "rpcclient %s", SAMBAServer); if ((status = do_samba_command(command, subcmd)) != 0) { fprintf(stderr, "ERROR: Unable to install Windows printer driver files (%d)!\n", status); unlink(ppdfile); return (5); } } else { /* * Do the smbclient commands needed for the Adobe WinNT drivers... */ snprintf(command, sizeof(command), "smbclient //%s/print\\$", SAMBAServer); snprintf(subcmd, sizeof(subcmd), "mkdir W32X86;" "put %s W32X86/%s.PPD;" "put %s/drivers/ADOBEPS5.DLL W32X86/ADOBEPS5.DLL;" "put %s/drivers/ADOBEPSU.DLL W32X86/ADOBEPSU.DLL;" "put %s/drivers/ADOBEPSU.HLP W32X86/ADOBEPSU.HLP", ppdfile, dest, datadir, datadir, datadir); if ((status = do_samba_command(command, subcmd)) != 0) { fprintf(stderr, "ERROR: Unable to copy Windows printer driver files (%d)!\n", status); unlink(ppdfile); return (4); } /* * Do the rpcclient commands needed for the Adobe WinNT drivers... */ snprintf(subcmd, sizeof(subcmd), "adddriver \"Windows NT x86\" \"%s:ADOBEPS5.DLL:%s.PPD:ADOBEPSU.DLL:ADOBEPSU.HLP:NULL:RAW:NULL\"", dest, dest); snprintf(command, sizeof(command), "rpcclient %s", SAMBAServer); if ((status = do_samba_command(command, subcmd)) != 0) { fprintf(stderr, "ERROR: Unable to install Windows printer driver files (%d)!\n", status); unlink(ppdfile); return (5); } } snprintf(command, sizeof(command), "%s/drivers/ADOBEPS4.DRV", datadir); if (access(command, 0) == 0) { /* * Do the smbclient commands needed for the Adobe Win9x drivers... */ snprintf(command, sizeof(command), "smbclient //%s/print\\$", SAMBAServer); snprintf(subcmd, sizeof(subcmd), "mkdir WIN40;" "put %s WIN40/%s.PPD;" "put %s/drivers/ADFONTS.MFM WIN40/ADFONTS.MFM;" "put %s/drivers/ADOBEPS4.DRV WIN40/ADOBEPS4.DRV;" "put %s/drivers/ADOBEPS4.HLP WIN40/ADOBEPS4.HLP;" "put %s/drivers/DEFPRTR2.PPD WIN40/DEFPRTR2.PPD;" "put %s/drivers/ICONLIB.DLL WIN40/ICONLIB.DLL;" "put %s/drivers/PSMON.DLL WIN40/PSMON.DLL;", ppdfile, dest, datadir, datadir, datadir, datadir, datadir, datadir); if ((status = do_samba_command(command, subcmd)) != 0) { fprintf(stderr, "ERROR: Unable to copy Windows printer driver files (%d)!\n", status); unlink(ppdfile); return (6); } /* * Do the rpcclient commands needed for the Adobe Win9x drivers... */ snprintf(command, sizeof(command), "rpcclient %s", SAMBAServer); snprintf(subcmd, sizeof(subcmd), "adddriver \"Windows 4.0\" \"%s:ADOBEPS4.DRV:%s.PPD:NULL:ADOBEPS4.HLP:PSMON.DLL:RAW:" "ADOBEPS4.DRV,%s.PPD,ADOBEPS4.HLP,PSMON.DLL,ADFONTS.MFM,DEFPRTR2.PPD,ICONLIB.DLL\"", dest, dest, dest); if ((status = do_samba_command(command, subcmd)) != 0) { fprintf(stderr, "ERROR: Unable to install Windows printer driver files (%d)!\n", status); unlink(ppdfile); return (7); } } unlink(ppdfile); /* * Finally, associate the drivers we just added with the queue... */ snprintf(command, sizeof(command), "rpcclient %s", SAMBAServer); snprintf(subcmd, sizeof(subcmd), "setdriver %s %s", dest, dest); if ((status = do_samba_command(command, subcmd)) != 0) { fprintf(stderr, "ERROR: Unable to install Windows printer driver files (%d)!\n", status); return (8); } return (0); } /* * 'usage()' - Show program usage and exit... */ void usage() { puts("Usage: cupsaddsmb [options] printer1 ... printerN"); puts(" cupsaddsmb [options] -a"); puts(""); puts("Options:"); puts(" -H samba-server Use the named SAMBA server"); puts(" -U samba-user Authenticate using the named SAMBA user"); puts(" -a Export all printers"); puts(" -h cups-server Use the named CUPS server"); puts(" -v Be verbose (show commands)"); exit(1); } /* * End of "$Id: cupsaddsmb.c,v 1.1.1.11 2002/12/24 00:07:38 jlovell Exp $". */