]> git.ipfire.org Git - thirdparty/cups.git/blame - backend/scsi-linux.c
More localization stuff + cleanup to only use fputs and fprintf since we
[thirdparty/cups.git] / backend / scsi-linux.c
CommitLineData
89008a65 1/*
b2e10895 2 * "$Id$"
89008a65 3 *
4 * Linux SCSI printer support for the Common UNIX Printing System (CUPS).
5 *
b2e10895 6 * Copyright 2003-2005 by Easy Software Products, all rights reserved.
89008a65 7 *
8 * Redistribution and use in source and binary forms, with or
9 * without modification, are permitted provided that the
10 * following conditions are met:
11 *
12 * 1. Redistributions of source code must retain the above
13 * copyright notice, this list of conditions and the
14 * following disclaimer.
15 *
16 * 2. Redistributions in binary form must reproduce the
17 * above copyright notice, this list of conditions and
18 * the following disclaimer in the documentation and/or
19 * other materials provided with the distribution.
20 *
21 * 3. All advertising materials mentioning features or use
22 * of this software must display the following
23 * acknowledgement:
24 *
25 * This product includes software developed by Easy
26 * Software Products.
27 *
28 * 4. The name of Easy Software Products may not be used to
29 * endorse or promote products derived from this software
30 * without specific prior written permission.
31 *
32 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS
33 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
34 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
35 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
36 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS
37 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
38 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
39 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
40 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
41 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
42 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
43 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
44 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
45 * DAMAGE.
46 *
47 * Contents:
48 *
49 * list_devices() - List the available SCSI printer devices.
50 * print_device() - Print a file to a SCSI device.
51 */
52
53/*
54 * Include necessary headers.
55 */
56
57#include <scsi/sg.h>
34b18bd4 58#include <cups/i18n.h>
89008a65 59
60
b2e10895 61/*
62 * We currently only support the Linux 2.4 generic SCSI interface.
63 */
64
65#ifndef SG_DXFER_TO_DEV
66/*
67 * Dummy functions that do nothing on unsupported platforms...
68 */
69void list_devices(void) {}
70int print_device(const char *resource, int fd, int copies) { return (1); }
71#else
72
73
89008a65 74/*
75 * 'list_devices()' - List the available SCSI printer devices.
76 */
77
78void
79list_devices(void)
80{
81 puts("direct scsi \"Unknown\" \"SCSI Printer\"");
82}
83
84
85/*
86 * 'print_device()' - Print a file to a SCSI device.
87 */
88
89int /* O - Print status */
90print_device(const char *resource, /* I - SCSI device */
91 int fd, /* I - File to print */
92 int copies) /* I - Number of copies to print */
93{
94 int scsi_fd; /* SCSI file descriptor */
95 char buffer[8192]; /* Data buffer */
96 int bytes; /* Number of bytes */
97 int try; /* Current try */
98 sg_io_hdr_t scsi_req; /* SCSI request */
6248387b 99 unsigned char scsi_cmd[6], /* SCSI command data */
89008a65 100 scsi_sense[32]; /* SCSI sense data */
b2e10895 101# if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
89008a65 102 struct sigaction action; /* Actions for POSIX signals */
b2e10895 103# endif /* HAVE_SIGACTION && !HAVE_SIGSET */
89008a65 104
105
106 /*
107 * Make sure we have a valid resource name...
108 */
109
110 if (strncmp(resource, "/dev/sg", 7) != 0)
111 {
ff0295f0 112 fprintf(stderr, _("ERROR: Bad SCSI device file \"%s\"!\n"), resource);
6248387b 113 return (CUPS_BACKEND_STOP);
89008a65 114 }
115
116 /*
117 * Open the SCSI device file...
118 */
119
22a980cc 120 fputs("STATE: +connecting-to-device\n", stderr);
121
89008a65 122 do
123 {
124 if ((scsi_fd = open(resource, O_RDWR | O_EXCL)) == -1)
125 {
b7b63780 126 if (getenv("CLASS") != NULL)
127 {
128 /*
129 * If the CLASS environment variable is set, the job was submitted
130 * to a class and not to a specific queue. In this case, we want
131 * to abort immediately so that the job can be requeued on the next
132 * available printer in the class.
133 */
134
34b18bd4 135 _cupsLangPuts(stderr,
136 _("INFO: Unable to open SCSI device, queuing on next "
137 "printer in class...\n"));
b7b63780 138
139 /*
140 * Sleep 5 seconds to keep the job from requeuing too rapidly...
141 */
142
143 sleep(5);
144
6248387b 145 return (CUPS_BACKEND_FAILED);
b7b63780 146 }
147
89008a65 148 if (errno != EAGAIN && errno != EBUSY)
149 {
ff0295f0 150 fprintf(stderr, _("ERROR: Unable to open device file \"%s\": %s\n"),
151 resource, strerror(errno));
6248387b 152 return (CUPS_BACKEND_FAILED);
89008a65 153 }
154 else
155 {
ff0295f0 156 fputs(_("INFO: Printer busy; will retry in 30 seconds...\n"), stderr);
89008a65 157 sleep(30);
158 }
159 }
160 }
161 while (scsi_fd == -1);
162
22a980cc 163 fputs("STATE: -connecting-to-device\n", stderr);
164
89008a65 165 /*
166 * Now that we are "connected" to the port, ignore SIGTERM so that we
167 * can finish out any page data the driver sends (e.g. to eject the
168 * current page... Only ignore SIGTERM if we are printing data from
169 * stdin (otherwise you can't cancel raw jobs...)
170 */
171
172 if (fd != 0)
173 {
b2e10895 174# ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
89008a65 175 sigset(SIGTERM, SIG_IGN);
b2e10895 176# elif defined(HAVE_SIGACTION)
89008a65 177 memset(&action, 0, sizeof(action));
178
179 sigemptyset(&action.sa_mask);
180 action.sa_handler = SIG_IGN;
181 sigaction(SIGTERM, &action, NULL);
b2e10895 182# else
89008a65 183 signal(SIGTERM, SIG_IGN);
b2e10895 184# endif /* HAVE_SIGSET */
89008a65 185 }
186
187 /*
188 * Copy the print file to the device...
189 */
190
191 while (copies > 0)
192 {
193 if (fd != 0)
194 lseek(fd, 0, SEEK_SET);
195
196 while ((bytes = read(fd, buffer, sizeof(buffer))) > 0)
197 {
198 memset(&scsi_req, 0, sizeof(scsi_req));
199
200 scsi_req.interface_id = 'S';
201 scsi_req.dxfer_direction = SG_DXFER_TO_DEV;
202 scsi_req.cmd_len = 6;
203 scsi_req.mx_sb_len = sizeof(scsi_sense);
204 scsi_req.iovec_count = 0;
205 scsi_req.dxfer_len = bytes;
206 scsi_req.dxferp = buffer;
207 scsi_req.cmdp = scsi_cmd;
208 scsi_req.sbp = scsi_sense;
209 scsi_req.timeout = 60 * 1000;
210
211 scsi_cmd[0] = 0x0a; /* Group 0 print command */
212 scsi_cmd[1] = 0x00;
213 scsi_cmd[2] = bytes / 65536;
214 scsi_cmd[3] = bytes / 256;
215 scsi_cmd[4] = bytes;
216 scsi_cmd[5] = 0x00;
217
218 for (try = 0; try < 10; try ++)
219 if (ioctl(scsi_fd, SG_IO, &scsi_req) < 0 ||
220 scsi_req.status != 0)
221 {
ff0295f0 222 fprintf(stderr,
223 _("WARNING: SCSI command timed out (%d); retrying...\n"),
224 scsi_req.status);
89008a65 225 sleep(try + 1);
226 }
227 else
228 break;
229
230 if (try >= 10)
231 {
ff0295f0 232 fprintf(stderr, _("ERROR: Unable to send print data (%d)\n"),
233 scsi_req.status);
89008a65 234 close(scsi_fd);
6248387b 235 return (CUPS_BACKEND_FAILED);
89008a65 236 }
237 }
238
239 copies --;
240 }
241
242 /*
243 * Close the device and return...
244 */
245
246 close(fd);
247
6248387b 248 return (CUPS_BACKEND_OK);
89008a65 249}
b2e10895 250#endif /* !SG_DXFER_TO_DEV */
89008a65 251
252
253/*
b2e10895 254 * End of "$Id$".
89008a65 255 */