14bff34e3Sthurlow /* 24bff34e3Sthurlow * Copyright (c) 2000, Boris Popov 34bff34e3Sthurlow * All rights reserved. 44bff34e3Sthurlow * 54bff34e3Sthurlow * Redistribution and use in source and binary forms, with or without 64bff34e3Sthurlow * modification, are permitted provided that the following conditions 74bff34e3Sthurlow * are met: 84bff34e3Sthurlow * 1. Redistributions of source code must retain the above copyright 94bff34e3Sthurlow * notice, this list of conditions and the following disclaimer. 104bff34e3Sthurlow * 2. Redistributions in binary form must reproduce the above copyright 114bff34e3Sthurlow * notice, this list of conditions and the following disclaimer in the 124bff34e3Sthurlow * documentation and/or other materials provided with the distribution. 134bff34e3Sthurlow * 3. All advertising materials mentioning features or use of this software 144bff34e3Sthurlow * must display the following acknowledgement: 154bff34e3Sthurlow * This product includes software developed by Boris Popov. 164bff34e3Sthurlow * 4. Neither the name of the author nor the names of any co-contributors 174bff34e3Sthurlow * may be used to endorse or promote products derived from this software 184bff34e3Sthurlow * without specific prior written permission. 194bff34e3Sthurlow * 204bff34e3Sthurlow * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 214bff34e3Sthurlow * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 224bff34e3Sthurlow * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 234bff34e3Sthurlow * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 244bff34e3Sthurlow * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 254bff34e3Sthurlow * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 264bff34e3Sthurlow * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 274bff34e3Sthurlow * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 284bff34e3Sthurlow * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 294bff34e3Sthurlow * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 304bff34e3Sthurlow * SUCH DAMAGE. 314bff34e3Sthurlow * 32613a2f6bSGordon Ross * from: Id: print.c,v 1.4 2001/01/28 07:35:01 bp Exp 334bff34e3Sthurlow */ 344bff34e3Sthurlow 35613a2f6bSGordon Ross /* 36*430b4c46SGordon Ross * Copyright 2011 Nexenta Systems, Inc. All rights reserved. 37613a2f6bSGordon Ross * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 38613a2f6bSGordon Ross * Use is subject to license terms. 39613a2f6bSGordon Ross */ 404bff34e3Sthurlow 41613a2f6bSGordon Ross #include <sys/types.h> 42613a2f6bSGordon Ross #include <err.h> 43613a2f6bSGordon Ross #include <errno.h> 444bff34e3Sthurlow #include <fcntl.h> 454bff34e3Sthurlow #include <stdio.h> 46613a2f6bSGordon Ross #include <string.h> 474bff34e3Sthurlow #include <stdlib.h> 48613a2f6bSGordon Ross #include <unistd.h> 494bff34e3Sthurlow #include <libintl.h> 504bff34e3Sthurlow 514bff34e3Sthurlow #include <cflib.h> 524bff34e3Sthurlow 534bff34e3Sthurlow #include <netsmb/smb_lib.h> 544bff34e3Sthurlow 554bff34e3Sthurlow #include "common.h" 564bff34e3Sthurlow 57613a2f6bSGordon Ross static char titlebuf[256]; 58613a2f6bSGordon Ross static char databuf[4096]; 594bff34e3Sthurlow 60613a2f6bSGordon Ross static int print_file(smb_ctx_t *, char *, int); 614bff34e3Sthurlow 624bff34e3Sthurlow void 634bff34e3Sthurlow print_usage(void) 644bff34e3Sthurlow { 654bff34e3Sthurlow printf(gettext("usage: smbutil print [connection options] //" 664bff34e3Sthurlow "[workgroup;][user[:password]@]" 67613a2f6bSGordon Ross "server/share {print_file|-}\n")); 684bff34e3Sthurlow exit(1); 694bff34e3Sthurlow } 70613a2f6bSGordon Ross 71613a2f6bSGordon Ross int 72613a2f6bSGordon Ross cmd_print(int argc, char *argv[]) 73613a2f6bSGordon Ross { 74613a2f6bSGordon Ross struct smb_ctx *ctx = NULL; 75613a2f6bSGordon Ross char *filename; 76613a2f6bSGordon Ross int error, opt; 77613a2f6bSGordon Ross int file = -1; 78613a2f6bSGordon Ross 79613a2f6bSGordon Ross /* last arg is the print file. */ 80613a2f6bSGordon Ross if (argc < 3) 81613a2f6bSGordon Ross print_usage(); 82613a2f6bSGordon Ross 83613a2f6bSGordon Ross error = smb_ctx_alloc(&ctx); 84613a2f6bSGordon Ross if (error) 85613a2f6bSGordon Ross goto out; 86613a2f6bSGordon Ross 87613a2f6bSGordon Ross error = smb_ctx_scan_argv(ctx, argc-1, argv, 88613a2f6bSGordon Ross SMBL_SHARE, SMBL_SHARE, USE_SPOOLDEV); 89613a2f6bSGordon Ross if (error) 90613a2f6bSGordon Ross goto out; 91613a2f6bSGordon Ross 92613a2f6bSGordon Ross error = smb_ctx_readrc(ctx); 93613a2f6bSGordon Ross if (error) 94613a2f6bSGordon Ross goto out; 95613a2f6bSGordon Ross 96613a2f6bSGordon Ross while ((opt = getopt(argc-1, argv, STDPARAM_OPT)) != EOF) { 97613a2f6bSGordon Ross if (opt == '?') 98613a2f6bSGordon Ross print_usage(); 99613a2f6bSGordon Ross error = smb_ctx_opt(ctx, opt, optarg); 100613a2f6bSGordon Ross if (error) 101613a2f6bSGordon Ross goto out; 102613a2f6bSGordon Ross } 103613a2f6bSGordon Ross if (optind != argc-2) 104613a2f6bSGordon Ross print_usage(); 105613a2f6bSGordon Ross filename = argv[argc-1]; 106613a2f6bSGordon Ross 107613a2f6bSGordon Ross if (strcmp(filename, "-") == 0) { 108613a2f6bSGordon Ross file = 0; /* stdin */ 109613a2f6bSGordon Ross filename = "stdin"; 110613a2f6bSGordon Ross } else { 111613a2f6bSGordon Ross file = open(filename, O_RDONLY, 0); 112613a2f6bSGordon Ross if (file < 0) { 113613a2f6bSGordon Ross smb_error("could not open file %s\n", errno, filename); 114613a2f6bSGordon Ross exit(1); 115613a2f6bSGordon Ross } 116613a2f6bSGordon Ross } 117613a2f6bSGordon Ross 118613a2f6bSGordon Ross /* 119613a2f6bSGordon Ross * Resolve the server address, 120613a2f6bSGordon Ross * setup derived defaults. 121613a2f6bSGordon Ross */ 122613a2f6bSGordon Ross error = smb_ctx_resolve(ctx); 123613a2f6bSGordon Ross if (error) 124613a2f6bSGordon Ross goto out; 125613a2f6bSGordon Ross 126613a2f6bSGordon Ross /* 127613a2f6bSGordon Ross * Have server + share names, options etc. 128613a2f6bSGordon Ross * Get the session and tree. 129613a2f6bSGordon Ross */ 130613a2f6bSGordon Ross again: 131613a2f6bSGordon Ross error = smb_ctx_get_ssn(ctx); 132613a2f6bSGordon Ross if (error == EAUTH) { 133613a2f6bSGordon Ross int err2 = smb_get_authentication(ctx); 134613a2f6bSGordon Ross if (err2 == 0) 135613a2f6bSGordon Ross goto again; 136613a2f6bSGordon Ross } 137613a2f6bSGordon Ross if (error) { 138613a2f6bSGordon Ross smb_error(gettext("//%s: login failed"), 139613a2f6bSGordon Ross error, ctx->ct_fullserver); 140613a2f6bSGordon Ross goto out; 141613a2f6bSGordon Ross } 142613a2f6bSGordon Ross 143613a2f6bSGordon Ross error = smb_ctx_get_tree(ctx); 144613a2f6bSGordon Ross if (error) { 145613a2f6bSGordon Ross smb_error(gettext("//%s/%s: tree connect failed"), 146613a2f6bSGordon Ross error, ctx->ct_fullserver, ctx->ct_origshare); 147613a2f6bSGordon Ross goto out; 148613a2f6bSGordon Ross } 149613a2f6bSGordon Ross 150613a2f6bSGordon Ross /* 151613a2f6bSGordon Ross * Have the printer share connection. 152613a2f6bSGordon Ross * Print the file. 153613a2f6bSGordon Ross */ 154*430b4c46SGordon Ross snprintf(titlebuf, sizeof (titlebuf), "%s %s", 155613a2f6bSGordon Ross ctx->ct_user, filename); 156613a2f6bSGordon Ross 157613a2f6bSGordon Ross error = print_file(ctx, titlebuf, file); 158613a2f6bSGordon Ross 159613a2f6bSGordon Ross 160613a2f6bSGordon Ross out: 161613a2f6bSGordon Ross /* don't close stdin (file=0) */ 162613a2f6bSGordon Ross if (file > 0) 163613a2f6bSGordon Ross close(file); 164613a2f6bSGordon Ross 165613a2f6bSGordon Ross smb_ctx_free(ctx); 166613a2f6bSGordon Ross 167613a2f6bSGordon Ross return (error); 168613a2f6bSGordon Ross } 169613a2f6bSGordon Ross 170613a2f6bSGordon Ross /* 171613a2f6bSGordon Ross * Documentation for OPEN_PRINT_FILE is scarse. 172613a2f6bSGordon Ross * It's in a 1996 MS doc. entitled: 173613a2f6bSGordon Ross * SMB FILE SHARING PROTOCOL 174613a2f6bSGordon Ross * 175613a2f6bSGordon Ross * The extra parameters are: 176613a2f6bSGordon Ross * SetupLength: what part of the file is printer setup 177613a2f6bSGordon Ross * Mode: text or graphics (raw data) 178613a2f6bSGordon Ross * IdentifierString: job title 179613a2f6bSGordon Ross */ 180613a2f6bSGordon Ross enum { 181613a2f6bSGordon Ross MODE_TEXT = 0, /* TAB expansion, etc. */ 182613a2f6bSGordon Ross MODE_GRAPHICS /* raw data */ 183613a2f6bSGordon Ross }; 184613a2f6bSGordon Ross 185613a2f6bSGordon Ross static int 186613a2f6bSGordon Ross print_file(smb_ctx_t *ctx, char *title, int file) 187613a2f6bSGordon Ross { 188613a2f6bSGordon Ross off_t offset; 189*430b4c46SGordon Ross int rcnt, wcnt; 190613a2f6bSGordon Ross int setup_len = 0; /* No printer setup data */ 191613a2f6bSGordon Ross int mode = MODE_GRAPHICS; /* treat as raw data */ 192*430b4c46SGordon Ross int error = 0; 193*430b4c46SGordon Ross int pfd = -1; 194613a2f6bSGordon Ross 195*430b4c46SGordon Ross pfd = smb_open_printer(ctx, title, setup_len, mode); 196*430b4c46SGordon Ross if (pfd < 0) { 197*430b4c46SGordon Ross error = errno; 198613a2f6bSGordon Ross smb_error("could not open print job", error); 199613a2f6bSGordon Ross return (error); 200613a2f6bSGordon Ross } 201613a2f6bSGordon Ross 202613a2f6bSGordon Ross offset = 0; 203613a2f6bSGordon Ross for (;;) { 204613a2f6bSGordon Ross rcnt = read(file, databuf, sizeof (databuf)); 205613a2f6bSGordon Ross if (rcnt < 0) { 206613a2f6bSGordon Ross error = errno; 207613a2f6bSGordon Ross smb_error("error reading input file\n", error); 208613a2f6bSGordon Ross break; 209613a2f6bSGordon Ross } 210613a2f6bSGordon Ross if (rcnt == 0) 211613a2f6bSGordon Ross break; 212613a2f6bSGordon Ross 213*430b4c46SGordon Ross wcnt = smb_fh_write(pfd, offset, rcnt, databuf); 214613a2f6bSGordon Ross if (wcnt < 0) { 215613a2f6bSGordon Ross error = errno; 216613a2f6bSGordon Ross smb_error("error writing spool file\n", error); 217613a2f6bSGordon Ross break; 218613a2f6bSGordon Ross } 219613a2f6bSGordon Ross if (wcnt != rcnt) { 220613a2f6bSGordon Ross smb_error("incomplete write to spool file\n", 0); 221613a2f6bSGordon Ross error = EIO; 222613a2f6bSGordon Ross break; 223613a2f6bSGordon Ross } 224613a2f6bSGordon Ross offset += wcnt; 225613a2f6bSGordon Ross } 226613a2f6bSGordon Ross 227*430b4c46SGordon Ross (void) smb_fh_close(pfd); 228613a2f6bSGordon Ross return (error); 229613a2f6bSGordon Ross } 230