1 /* 2 * Copyright (c) 2000, Boris Popov 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by Boris Popov. 16 * 4. Neither the name of the author nor the names of any co-contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 * 32 * from: Id: print.c,v 1.4 2001/01/28 07:35:01 bp Exp 33 */ 34 35 /* 36 * Copyright 2011 Nexenta Systems, Inc. All rights reserved. 37 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 38 * Use is subject to license terms. 39 */ 40 41 #include <sys/types.h> 42 #include <err.h> 43 #include <errno.h> 44 #include <fcntl.h> 45 #include <stdio.h> 46 #include <string.h> 47 #include <stdlib.h> 48 #include <unistd.h> 49 #include <libintl.h> 50 51 #include <cflib.h> 52 53 #include <netsmb/smb_lib.h> 54 55 #include "common.h" 56 57 static char titlebuf[256]; 58 static char databuf[4096]; 59 60 static int print_file(smb_ctx_t *, char *, int); 61 62 void 63 print_usage(void) 64 { 65 printf(gettext("usage: smbutil print [connection options] //" 66 "[workgroup;][user[:password]@]" 67 "server/share {print_file|-}\n")); 68 exit(1); 69 } 70 71 int 72 cmd_print(int argc, char *argv[]) 73 { 74 struct smb_ctx *ctx = NULL; 75 char *filename; 76 int error, opt; 77 int file = -1; 78 79 /* last arg is the print file. */ 80 if (argc < 3) 81 print_usage(); 82 83 error = smb_ctx_alloc(&ctx); 84 if (error) 85 goto out; 86 87 error = smb_ctx_scan_argv(ctx, argc-1, argv, 88 SMBL_SHARE, SMBL_SHARE, USE_SPOOLDEV); 89 if (error) 90 goto out; 91 92 error = smb_ctx_readrc(ctx); 93 if (error) 94 goto out; 95 96 while ((opt = getopt(argc-1, argv, STDPARAM_OPT)) != EOF) { 97 if (opt == '?') 98 print_usage(); 99 error = smb_ctx_opt(ctx, opt, optarg); 100 if (error) 101 goto out; 102 } 103 if (optind != argc-2) 104 print_usage(); 105 filename = argv[argc-1]; 106 107 if (strcmp(filename, "-") == 0) { 108 file = 0; /* stdin */ 109 filename = "stdin"; 110 } else { 111 file = open(filename, O_RDONLY, 0); 112 if (file < 0) { 113 smb_error("could not open file %s\n", errno, filename); 114 exit(1); 115 } 116 } 117 118 /* 119 * Resolve the server address, 120 * setup derived defaults. 121 */ 122 error = smb_ctx_resolve(ctx); 123 if (error) 124 goto out; 125 126 /* 127 * Have server + share names, options etc. 128 * Get the session and tree. 129 */ 130 again: 131 error = smb_ctx_get_ssn(ctx); 132 if (error == EAUTH) { 133 int err2 = smb_get_authentication(ctx); 134 if (err2 == 0) 135 goto again; 136 } 137 if (error) { 138 smb_error(gettext("//%s: login failed"), 139 error, ctx->ct_fullserver); 140 goto out; 141 } 142 143 error = smb_ctx_get_tree(ctx); 144 if (error) { 145 smb_error(gettext("//%s/%s: tree connect failed"), 146 error, ctx->ct_fullserver, ctx->ct_origshare); 147 goto out; 148 } 149 150 /* 151 * Have the printer share connection. 152 * Print the file. 153 */ 154 snprintf(titlebuf, sizeof (titlebuf), "%s %s", 155 ctx->ct_user, filename); 156 157 error = print_file(ctx, titlebuf, file); 158 159 160 out: 161 /* don't close stdin (file=0) */ 162 if (file > 0) 163 close(file); 164 165 smb_ctx_free(ctx); 166 167 return (error); 168 } 169 170 /* 171 * Documentation for OPEN_PRINT_FILE is scarse. 172 * It's in a 1996 MS doc. entitled: 173 * SMB FILE SHARING PROTOCOL 174 * 175 * The extra parameters are: 176 * SetupLength: what part of the file is printer setup 177 * Mode: text or graphics (raw data) 178 * IdentifierString: job title 179 */ 180 enum { 181 MODE_TEXT = 0, /* TAB expansion, etc. */ 182 MODE_GRAPHICS /* raw data */ 183 }; 184 185 static int 186 print_file(smb_ctx_t *ctx, char *title, int file) 187 { 188 off_t offset; 189 int rcnt, wcnt; 190 int setup_len = 0; /* No printer setup data */ 191 int mode = MODE_GRAPHICS; /* treat as raw data */ 192 int error = 0; 193 int pfd = -1; 194 195 pfd = smb_open_printer(ctx, title, setup_len, mode); 196 if (pfd < 0) { 197 error = errno; 198 smb_error("could not open print job", error); 199 return (error); 200 } 201 202 offset = 0; 203 for (;;) { 204 rcnt = read(file, databuf, sizeof (databuf)); 205 if (rcnt < 0) { 206 error = errno; 207 smb_error("error reading input file\n", error); 208 break; 209 } 210 if (rcnt == 0) 211 break; 212 213 wcnt = smb_fh_write(pfd, offset, rcnt, databuf); 214 if (wcnt < 0) { 215 error = errno; 216 smb_error("error writing spool file\n", error); 217 break; 218 } 219 if (wcnt != rcnt) { 220 smb_error("incomplete write to spool file\n", 0); 221 error = EIO; 222 break; 223 } 224 offset += wcnt; 225 } 226 227 (void) smb_fh_close(pfd); 228 return (error); 229 } 230