1 /* @(#)skel.c 1.23 16/01/24 Copyright 1987, 1995-2016 J. Schilling */
2 #include <schily/mconfig.h>
3 #ifndef lint
4 static UConst char sccsid[] =
5 "@(#)skel.c 1.23 16/01/24 Copyright 1987, 1995-2016 J. Schilling";
6 #endif
7 /*
8 * Skeleton for the use of the scg genearal SCSI - driver
9 *
10 * Copyright (c) 1987, 1995-2016 J. Schilling
11 */
12 /*
13 * The contents of this file are subject to the terms of the
14 * Common Development and Distribution License, Version 1.0 only
15 * (the "License"). You may not use this file except in compliance
16 * with the License.
17 *
18 * See the file CDDL.Schily.txt in this distribution for details.
19 * A copy of the CDDL is also available via the Internet at
20 * http://www.opensource.org/licenses/cddl1.txt
21 *
22 * When distributing Covered Code, include this CDDL HEADER in each
23 * file and include the License file CDDL.Schily.txt from this distribution.
24 */
25
26 #define SKEL_MAIN
27 #include <schily/mconfig.h>
28 #include <schily/stdio.h>
29 #include <schily/standard.h>
30 #include <schily/unistd.h>
31 #include <schily/stdlib.h>
32 #include <schily/string.h>
33 #include <schily/fcntl.h>
34 #include <schily/time.h>
35 #include <schily/errno.h>
36 #include <schily/signal.h>
37 #include <schily/schily.h>
38 #include <schily/nlsdefs.h>
39 #include <schily/priv.h>
40 #include <schily/io.h> /* for setmode() prototype */
41
42 #include <scg/scgcmd.h>
43 #include <scg/scsireg.h>
44 #include <scg/scsitransp.h>
45
46 #include "scsi_scan.h"
47 #include "cdrecord.h"
48 #include "cdrdeflt.h"
49 #include "iodefs.h"
50
51 char skel_version[] = "1.2";
52
53 struct exargs {
54 SCSI *scgp;
55 int old_secsize;
56 int flags;
57 int exflags;
58 char oerr[3];
59 } exargs;
60
61 #ifndef NO_DOIT
62 #define NEED_PRSTATS
63 #endif
64
65 LOCAL void usage __PR((int ret));
66 EXPORT int main __PR((int ac, char **av));
67 LOCAL void intr __PR((int sig));
68 LOCAL void exscsi __PR((int excode, void *arg));
69 #ifdef __needed__
70 LOCAL void excdr __PR((int excode, void *arg));
71 #endif
72 #ifdef NEED_PRSTATS
73 LOCAL int prstats __PR((void));
74 #endif
75 #ifdef __needed__
76 LOCAL int prstats_silent __PR((void));
77 #endif
78
79 #ifndef NO_DOIT
80 #include "doit.c"
81 #endif
82
83 #ifndef DOIT_MAIN
84 LOCAL void doit __PR((SCSI *scgp));
85 #endif
86 LOCAL void dofile __PR((SCSI *scgp, char *filename));
87
88
89 struct timeval starttime;
90 struct timeval stoptime;
91 int didintr;
92 int exsig;
93
94 char *Sbuf;
95 long Sbufsize = -1L;
96
97 int help;
98 int xdebug;
99 int lverbose;
100 int quiet;
101 BOOL is_suid;
102
103 LOCAL void
usage(ret)104 usage(ret)
105 int ret;
106 {
107 error(_("Usage:\tscgskeleton [options]\n"));
108 error(_("Options:\n"));
109 error(_("\t-version print version information and exit\n"));
110 error(_("\tdev=target SCSI target to use\n"));
111 error(_("\tscgopts=spec SCSI options for libscg\n"));
112 error(_("\tf=filename Name of file to read/write\n"));
113 error(_("\tts=# set maximum transfer size for a single SCSI command\n"));
114 error(_("\ttimeout=# set the default SCSI command timeout to #.\n"));
115 error(_("\tdebug=#,-d Set to # or increment misc debug level\n"));
116 error(_("\tkdebug=#,kd=# do Kernel debugging\n"));
117 error(_("\t-quiet,-q be more quiet in error retry mode\n"));
118 error(_("\t-verbose,-v increment general verbose level by one\n"));
119 error(_("\t-Verbose,-V increment SCSI command transport verbose level by one\n"));
120 error(_("\t-silent,-s do not print status of failed SCSI commands\n"));
121 error(_("\t-scanbus scan the SCSI bus and exit\n"));
122 exit(ret);
123 }
124
125 /* CSTYLED */
126 char opts[] = "debug#,d+,kdebug#,kd#,timeout#,quiet,q,verbose+,v+,Verbose+,V+,x+,xd#,silent,s,help,h,version,scanbus,dev*,scgopts*,ts&,f*";
127
128 EXPORT int
main(ac,av)129 main(ac, av)
130 int ac;
131 char *av[];
132 {
133 char *dev = NULL;
134 char *scgopts = NULL;
135 int fcount;
136 int cac;
137 char * const *cav;
138 #if defined(USE_NLS)
139 char *dir;
140 #endif
141 int scsibus = -1;
142 int target = -1;
143 int lun = -1;
144 int silent = 0;
145 int verbose = 0;
146 int kdebug = 0;
147 int debug = 0;
148 int deftimeout = 40;
149 int pversion = 0;
150 int scanbus = 0;
151 SCSI *scgp;
152 char *filename = NULL;
153 int err;
154
155 save_args(ac, av);
156
157 #if defined(USE_NLS)
158 (void) setlocale(LC_ALL, "");
159 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
160 #define TEXT_DOMAIN "scgskeleton" /* Use this only if it weren't */
161 #endif
162 dir = searchfileinpath("share/locale", F_OK,
163 SIP_ANY_FILE|SIP_NO_PATH, NULL);
164 if (dir)
165 (void) bindtextdomain(TEXT_DOMAIN, dir);
166 else
167 #if defined(PROTOTYPES) && defined(INS_BASE)
168 (void) bindtextdomain(TEXT_DOMAIN, INS_BASE "/share/locale");
169 #else
170 (void) bindtextdomain(TEXT_DOMAIN, "/usr/share/locale");
171 #endif
172 (void) textdomain(TEXT_DOMAIN);
173 #endif
174
175 cac = --ac;
176 cav = ++av;
177
178 if (getallargs(&cac, &cav, opts,
179 &debug, &debug,
180 &kdebug, &kdebug,
181 &deftimeout,
182 &quiet, &quiet,
183 &lverbose, &lverbose,
184 &verbose, &verbose,
185 &xdebug, &xdebug,
186 &silent, &silent,
187 &help, &help, &pversion,
188 &scanbus,
189 &dev, &scgopts,
190 getnum, &Sbufsize,
191 &filename) < 0) {
192 errmsgno(EX_BAD, _("Bad flag: %s.\n"), cav[0]);
193 usage(EX_BAD);
194 }
195 if (help)
196 usage(0);
197 if (pversion) {
198 printf(_("scgskeleton %s (%s-%s-%s) Copyright (C) 1987, 1995-2016 %s\n"),
199 skel_version,
200 HOST_CPU, HOST_VENDOR, HOST_OS,
201 _("Joerg Schilling"));
202 exit(0);
203 }
204
205 fcount = 0;
206 cac = ac;
207 cav = av;
208
209 while (getfiles(&cac, &cav, opts) > 0) {
210 fcount++;
211 if (fcount == 1) {
212 if (*astoi(cav[0], &target) != '\0') {
213 errmsgno(EX_BAD,
214 _("Target '%s' is not a Number.\n"),
215 cav[0]);
216 usage(EX_BAD);
217 /* NOTREACHED */
218 }
219 }
220 if (fcount == 2) {
221 if (*astoi(cav[0], &lun) != '\0') {
222 errmsgno(EX_BAD,
223 _("Lun is '%s' not a Number.\n"),
224 cav[0]);
225 usage(EX_BAD);
226 /* NOTREACHED */
227 }
228 }
229 if (fcount == 3) {
230 if (*astoi(cav[0], &scsibus) != '\0') {
231 errmsgno(EX_BAD,
232 _("Scsibus is '%s' not a Number.\n"),
233 cav[0]);
234 usage(EX_BAD);
235 /* NOTREACHED */
236 }
237 }
238 cac--;
239 cav++;
240 }
241 /*error("dev: '%s'\n", dev);*/
242
243 cdr_defaults(&dev, NULL, NULL, &Sbufsize, NULL);
244 if (debug) {
245 printf(_("dev: '%s'\n"), dev);
246 }
247 if (!scanbus && dev == NULL &&
248 scsibus == -1 && (target == -1 || lun == -1)) {
249 errmsgno(EX_BAD, _("No SCSI device specified.\n"));
250 usage(EX_BAD);
251 }
252 if (dev || scanbus) {
253 char errstr[80];
254
255 /*
256 * Call scg_remote() to force loading the remote SCSI transport
257 * library code that is located in librscg instead of the dummy
258 * remote routines that are located inside libscg.
259 */
260 scg_remote();
261 if (dev != NULL &&
262 ((strncmp(dev, "HELP", 4) == 0) ||
263 (strncmp(dev, "help", 4) == 0))) {
264 scg_help(stderr);
265 exit(0);
266 }
267 if ((scgp = scg_open(dev, errstr, sizeof (errstr), debug, lverbose)) == (SCSI *)0) {
268 err = geterrno();
269
270 errmsgno(err, _("%s%sCannot open SCSI driver.\n"), errstr, errstr[0]?". ":"");
271 errmsgno(EX_BAD, _("For possible targets try 'scgskeleton -scanbus'. Make sure you are root.\n"));
272 errmsgno(EX_BAD, _("For possible transport specifiers try 'scgskeleton dev=help'.\n"));
273 exit(err);
274 }
275 } else {
276 if (scsibus == -1 && target >= 0 && lun >= 0)
277 scsibus = 0;
278
279 scgp = scg_smalloc();
280 scgp->debug = debug;
281 scgp->kdebug = kdebug;
282
283 scg_settarget(scgp, scsibus, target, lun);
284 if (scg__open(scgp, NULL) <= 0)
285 comerr(_("Cannot open SCSI driver.\n"));
286 }
287 if (scgopts) {
288 int i = scg_opts(scgp, scgopts);
289 if (i <= 0)
290 exit(i < 0 ? EX_BAD : 0);
291 }
292 scgp->silent = silent;
293 scgp->verbose = verbose;
294 scgp->debug = debug;
295 scgp->kdebug = kdebug;
296 scg_settimeout(scgp, deftimeout);
297
298 if (Sbufsize < 0)
299 Sbufsize = 256*1024L;
300 Sbufsize = scg_bufsize(scgp, Sbufsize);
301 if ((Sbuf = scg_getbuf(scgp, Sbufsize)) == NULL)
302 comerr(_("Cannot get SCSI I/O buffer.\n"));
303
304 #ifdef HAVE_PRIV_SET
305 /*
306 * Give up privs we do not need anymore.
307 * We no longer need:
308 * file_dac_read,net_privaddr
309 * We still need:
310 * sys_devices
311 */
312 priv_set(PRIV_OFF, PRIV_EFFECTIVE,
313 PRIV_FILE_DAC_READ, PRIV_NET_PRIVADDR, NULL);
314 priv_set(PRIV_OFF, PRIV_PERMITTED,
315 PRIV_FILE_DAC_READ, PRIV_NET_PRIVADDR, NULL);
316 priv_set(PRIV_OFF, PRIV_INHERITABLE,
317 PRIV_FILE_DAC_READ, PRIV_NET_PRIVADDR, PRIV_SYS_DEVICES, NULL);
318 #endif
319 /*
320 * This is only for OS that do not support fine grained privs.
321 */
322 is_suid = geteuid() != getuid();
323 /*
324 * We don't need root privilleges anymore.
325 */
326 #ifdef HAVE_SETREUID
327 if (setreuid(-1, getuid()) < 0)
328 #else
329 #ifdef HAVE_SETEUID
330 if (seteuid(getuid()) < 0)
331 #else
332 if (setuid(getuid()) < 0)
333 #endif
334 #endif
335 comerr(_("Panic cannot set back effective uid.\n"));
336
337 /* code to use SCG */
338
339 if (scanbus) {
340 if (select_target(scgp, stdout) < 0)
341 exit(EX_BAD);
342 exit(0);
343 }
344 seterrno(0);
345 do_inquiry(scgp, FALSE);
346 err = geterrno();
347 if (err == EPERM || err == EACCES)
348 exit(EX_BAD);
349 allow_atapi(scgp, TRUE); /* Try to switch to 10 byte mode cmds */
350
351 exargs.scgp = scgp;
352 exargs.old_secsize = -1;
353 /* exargs.flags = flags;*/
354 exargs.oerr[2] = 0;
355
356 /*
357 * Install exit handler before we change the drive status.
358 */
359 on_comerr(exscsi, &exargs);
360 signal(SIGINT, intr);
361 signal(SIGTERM, intr);
362
363 if (filename)
364 dofile(scgp, filename);
365 else
366 doit(scgp);
367
368 comexit(0);
369 return (0);
370 }
371
372 /*
373 * XXX Leider kann man vim Signalhandler keine SCSI Kommandos verschicken
374 * XXX da meistens das letzte SCSI Kommando noch laeuft.
375 * XXX Eine Loesung waere ein Abort Callback in SCSI *.
376 */
377 LOCAL void
intr(sig)378 intr(sig)
379 int sig;
380 {
381 didintr++;
382 exsig = sig;
383 /* comexit(sig);*/
384 }
385
386 /* ARGSUSED */
387 LOCAL void
exscsi(excode,arg)388 exscsi(excode, arg)
389 int excode;
390 void *arg;
391 {
392 struct exargs *exp = (struct exargs *)arg;
393 int i;
394
395 /*
396 * Try to restore the old sector size.
397 */
398 if (exp != NULL && exp->exflags == 0) {
399 for (i = 0; i < 10*100; i++) {
400 if (!exp->scgp->running)
401 break;
402 if (i == 10) {
403 errmsgno(EX_BAD,
404 _("Waiting for current SCSI command to finish.\n"));
405 }
406 usleep(100000);
407 }
408
409 #ifdef ___NEEDED___
410 /*
411 * Try to set drive back to original state.
412 */
413 if (!exp->scgp->running) {
414 if (exp->oerr[2] != 0) {
415 domode(exp->scgp, exp->oerr[0], exp->oerr[1]);
416 }
417 if (exp->old_secsize > 0 && exp->old_secsize != 2048)
418 select_secsize(exp->scgp, exp->old_secsize);
419 }
420 #endif
421 exp->exflags++; /* Make sure that it only get called once */
422 }
423 }
424
425 #ifdef __needed__
426 LOCAL void
excdr(excode,arg)427 excdr(excode, arg)
428 int excode;
429 void *arg;
430 {
431 exscsi(excode, arg);
432
433 #ifdef needed
434 /* Do several other restores/statistics here (see cdrecord.c) */
435 #endif
436 }
437 #endif
438
439 #ifdef NEED_PRSTATS
440 /*
441 * Return milliseconds since start time.
442 */
443 LOCAL int
prstats()444 prstats()
445 {
446 int sec;
447 int usec;
448 int tmsec;
449
450 if (gettimeofday(&stoptime, (struct timezone *)0) < 0)
451 comerr(_("Cannot get time\n"));
452
453 sec = stoptime.tv_sec - starttime.tv_sec;
454 usec = stoptime.tv_usec - starttime.tv_usec;
455 tmsec = sec*1000 + usec/1000;
456 #ifdef lint
457 tmsec = tmsec; /* Bisz spaeter */
458 #endif
459 if (usec < 0) {
460 sec--;
461 usec += 1000000;
462 }
463
464 error(_("Time total: %d.%03dsec\n"), sec, usec/1000);
465 return (1000*sec + (usec / 1000));
466 }
467 #endif
468
469 #ifdef __needed__
470 /*
471 * Return milliseconds since start time, but be silent this time.
472 */
473 LOCAL int
prstats_silent()474 prstats_silent()
475 {
476 int sec;
477 int usec;
478 int tmsec;
479
480 if (gettimeofday(&stoptime, (struct timezone *)0) < 0)
481 comerr(_("Cannot get time\n"));
482
483 sec = stoptime.tv_sec - starttime.tv_sec;
484 usec = stoptime.tv_usec - starttime.tv_usec;
485 tmsec = sec*1000 + usec/1000;
486 #ifdef lint
487 tmsec = tmsec; /* Bisz spaeter */
488 #endif
489 if (usec < 0) {
490 sec--;
491 usec += 1000000;
492 }
493
494 return (1000*sec + (usec / 1000));
495 }
496 #endif
497
498 #ifndef DOIT_MAIN
499 LOCAL void
doit(scgp)500 doit(scgp)
501 SCSI *scgp;
502 {
503 int i = 0;
504
505 for (;;) {
506 if (!wait_unit_ready(scgp, 60))
507 comerrno(EX_BAD, _("Device not ready.\n"));
508
509 printf(_("0:read\n"));
510 /* printf("7:wne 8:floppy 9:verify 10:checkcmds 11:read disk 12:write disk\n");*/
511
512 getint(_("Enter selection:"), &i, 0, 20);
513 if (didintr)
514 return;
515
516 switch (i) {
517
518 /* case 1: read_disk(scgp, 0); break;*/
519
520 default: error(_("Unimplemented selection %d\n"), i);
521 }
522 }
523 }
524 #endif /* DOIT_MAIN */
525
526
527 LOCAL void
dofile(scgp,filename)528 dofile(scgp, filename)
529 SCSI *scgp;
530 char *filename;
531 {
532 }
533
534 /*
535 * Add your own code below....
536 */
537