/[debburn]/nonameyet/trunk/rscsi/rscsi.c
ViewVC logotype

Contents of /nonameyet/trunk/rscsi/rscsi.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2 - (show annotations) (download)
Fri Aug 18 17:34:13 2006 UTC (6 years, 9 months ago) by blade
File MIME type: text/plain
File size: 21269 byte(s)
Imported the resorted version a08
1 /* @(#)rscsi.c 1.29 05/05/16 Copyright 1994,2000-2002 J. Schilling*/
2 #ifndef lint
3 static char sccsid[] =
4 "@(#)rscsi.c 1.29 05/05/16 Copyright 1994,2000-2002 J. Schilling";
5 #endif
6 /*
7 * Remote SCSI server
8 *
9 * Copyright (c) 1994,2000-2002 J. Schilling
10 */
11 /*
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License version 2
14 * as published by the Free Software Foundation.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License along with
22 * this program; see the file COPYING. If not, write to the Free Software
23 * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 */
25
26 /*#define FORCE_DEBUG*/
27
28 #include <mconfig.h>
29
30 #include <stdio.h>
31 #include <stdxlib.h>
32 #include <unixstd.h> /* includes <sys/types.h> */
33 #include <utypes.h>
34 #include <fctldefs.h>
35 #include <statdefs.h>
36 #include <strdefs.h>
37 #ifdef HAVE_SYS_SOCKET_H
38 #define USE_REMOTE
39 #include <sys/socket.h>
40 #endif
41 #ifdef HAVE_SYS_PARAM_H
42 #include <sys/param.h> /* BSD-4.2 & Linux need this for MAXHOSTNAMELEN */
43 #endif
44 #include <errno.h>
45 #include <pwd.h>
46
47 #include <standard.h>
48 #include <deflts.h>
49 #include <patmatch.h>
50 #include <schily.h>
51
52 #include <scg/scgcmd.h>
53 #include <scg/scsitransp.h>
54
55 #include <netinet/in.h>
56 #ifdef HAVE_ARPA_INET_H
57 #include <arpa/inet.h> /* BeOS does not have <arpa/inet.h> */
58 #endif /* but inet_ntaoa() is in <netdb.h> */
59 #ifdef HAVE_NETDB_H
60 #include <netdb.h>
61 #endif
62
63 EXPORT int main __PR((int argc, char **argv));
64 #ifdef USE_REMOTE
65 LOCAL void checkuser __PR((void));
66 LOCAL char *getpeer __PR((void));
67 LOCAL BOOL checktarget __PR((void));
68 LOCAL BOOL strmatch __PR((char *str, char *pat));
69 LOCAL void dorscsi __PR((void));
70 LOCAL void scsiversion __PR((void));
71 LOCAL void openscsi __PR((void));
72 LOCAL void closescsi __PR((void));
73 LOCAL void maxdma __PR((void));
74 LOCAL void getbuf __PR((void));
75 LOCAL void freebuf __PR((void));
76 LOCAL void havebus __PR((void));
77 LOCAL void scsifileno __PR((void));
78 LOCAL void initiator_id __PR((void));
79 LOCAL void isatapi __PR((void));
80 LOCAL void scsireset __PR((void));
81 LOCAL void sendcmd __PR((void));
82
83 LOCAL int fillrdbuf __PR((void));
84 LOCAL int readchar __PR((char *cp));
85
86 LOCAL void readbuf __PR((char *buf, int n));
87 LOCAL void voidarg __PR((int n));
88 LOCAL void readarg __PR((char *buf, int n));
89 LOCAL char * preparebuffer __PR((int size));
90 LOCAL int checkscsi __PR((char *decive));
91 LOCAL void rscsirespond __PR((int ret, int err));
92 LOCAL void rscsireply __PR((int ret));
93 LOCAL void rscsierror __PR((int err, char *str, char *xstr));
94
95 #define CMD_SIZE 80
96
97 LOCAL SCSI *scsi_ptr = NULL;
98 LOCAL char *Sbuf;
99 LOCAL long Sbufsize;
100
101 LOCAL char *username;
102 LOCAL char *peername;
103
104 LOCAL char *debug_name;
105 LOCAL FILE *debug_file;
106
107 #define DEBUG(fmt) if (debug_file) js_fprintf(debug_file, fmt)
108 #define DEBUG1(fmt,a) if (debug_file) js_fprintf(debug_file, fmt, a)
109 #define DEBUG2(fmt,a1,a2) if (debug_file) js_fprintf(debug_file, fmt, a1, a2)
110 #define DEBUG3(fmt,a1,a2,a3) if (debug_file) js_fprintf(debug_file, fmt, a1, a2, a3)
111 #define DEBUG4(fmt,a1,a2,a3,a4) if (debug_file) js_fprintf(debug_file, fmt, a1, a2, a3, a4)
112 #define DEBUG5(fmt,a1,a2,a3,a4,a5) if (debug_file) js_fprintf(debug_file, fmt, a1, a2, a3, a4, a5)
113 #define DEBUG6(fmt,a1,a2,a3,a4,a5,a6) if (debug_file) js_fprintf(debug_file, fmt, a1, a2, a3, a4, a5, a6)
114 #endif /* USE_REMOTE */
115
116 EXPORT int
117 main(argc, argv)
118 int argc;
119 char **argv;
120 {
121 save_args(argc, argv);
122 #ifndef USE_REMOTE
123 comerrno(EX_BAD, "No remote SCSI support on this platform.\n");
124 #else
125 argc--, argv++;
126 if (argc > 0 && strcmp(*argv, "-c") == 0) {
127 /*
128 * Skip params in case we have been installed as shell.
129 */
130 argc--, argv++;
131 argc--, argv++;
132 }
133 /*
134 * WARNING you are only allowed to change the defaults configuration
135 * filename if you also change the documentation and add a statement
136 * that makes clear where the official location of the file is, why you
137 * did choose a nonstandard location and that the nonstandard location
138 * only refers to inofficial rscsi versions.
139 *
140 * I was forced to add this because some people change cdrecord without
141 * rational reason and then publish the result. As those people
142 * don't contribute work and don't give support, they are causing extra
143 * work for me and this way slow down the development.
144 */
145 if (defltopen("/etc/default/rscsi") < 0) {
146 rscsierror(geterrno(), errmsgstr(geterrno()),
147 "Remote configuration error: Cannot open /etc/default/rscsi");
148 /* rscsirespond(-1, geterrno());*/
149 exit(EX_BAD);
150 }
151 debug_name=defltread("DEBUG=");
152 #ifdef FORCE_DEBUG
153 if (debug_name == NULL && argc <= 0)
154 debug_name = "/tmp/RSCSI";
155 #endif
156 #ifdef NONONO
157 /*
158 * Should we allow root to shoot himself into the foot?
159 * Allowing to write arbitrary files may be a security risk.
160 */
161 if (argc > 0 && getuid() == 0)
162 debug_name = *argv;
163 #endif
164
165 /*
166 * XXX If someone sets up debugging and allows the debug file to be
167 * XXX replaced by a symlink to e.g. /etc/passwd this would be a
168 * XXX security risk. But /etc/default/rscsi is only writable by root
169 * XXX and for this reason a possible security risk would have been
170 * XXX introduced by the administrator.
171 */
172 if (debug_name != NULL)
173 debug_file = fopen(debug_name, "w");
174
175 if (argc > 0) {
176 if (debug_file == 0) {
177 rscsirespond(-1, geterrno());
178 exit(EX_BAD);
179 }
180 (void) setbuf(debug_file, (char *)0);
181 }
182 checkuser(); /* Check if we are called by a bad guy */
183 peername = getpeer(); /* Get host name of caller */
184 dorscsi();
185 #endif /* USE_REMOTE */
186 return (0);
187 }
188
189 #ifdef USE_REMOTE
190 LOCAL void
191 checkuser()
192 {
193 uid_t uid = getuid();
194 char *uname;
195 struct passwd *pw;
196
197 if (uid == 0) {
198 username = "root";
199 DEBUG("rscsid: user id 0, name root\n");
200 return;
201 }
202 pw = getpwuid(uid);
203 if (pw == NULL)
204 goto notfound;
205
206 username = pw->pw_name;
207 DEBUG2("rscsid: user id %ld, name %s\n", (long)uid, username);
208
209 defltfirst();
210 while ((uname = defltnext("USER=")) != NULL) {
211 if (strmatch(username, uname))
212 return;
213 }
214 notfound:
215 DEBUG2("rscsid: Illegal user '%s' id %ld for RSCSI server\n",
216 username, (long)uid);
217 rscsierror(0, "Illegal user id for RSCSI server", NULL);
218 exit(EX_BAD);
219 }
220
221 #ifndef NI_MAXHOST
222 #ifdef MAXHOSTNAMELEN /* XXX remove this and sys/param.h */
223 #define NI_MAXHOST MAXHOSTNAMELEN
224 #else
225 #define NI_MAXHOST 64
226 #endif
227 #endif
228
229 LOCAL char *
230 getpeer()
231 {
232 #ifdef HAVE_GETNAMEINFO
233 #ifdef HAVE_SOCKADDR_STORAGE
234 struct sockaddr_storage sa;
235 #else
236 char sa[256];
237 #endif
238 #else
239 struct sockaddr sa;
240 struct hostent *he;
241 #endif
242 struct sockaddr *sap;
243 struct sockaddr_in *s;
244 socklen_t sasize = sizeof (sa);
245 static char buffer[NI_MAXHOST];
246
247 sap = (struct sockaddr *)&sa;
248 if (getpeername(STDIN_FILENO, sap, &sasize) < 0) {
249 int errsav = geterrno();
250 struct stat sb;
251
252 if (fstat(STDIN_FILENO, &sb) >= 0) {
253 if (S_ISFIFO(sb.st_mode)) {
254 DEBUG("rmt: stdin is a PIPE\n");
255 return ("PIPE");
256 }
257 DEBUG1("rscsid: stdin st_mode %0llo\n", (Llong)sb.st_mode);
258 }
259
260 DEBUG1("rscsid: peername %s\n", errmsgstr(errsav));
261 return ("ILLEGAL_SOCKET");
262 } else {
263 s = (struct sockaddr_in *)&sa;
264 #ifdef AF_INET6
265 if (s->sin_family != AF_INET && s->sin_family != AF_INET6) {
266 #else
267 if (s->sin_family != AF_INET) {
268 #endif
269 #ifdef AF_UNIX
270 /*
271 * AF_UNIX is not defined on BeOS
272 */
273 if (s->sin_family == AF_UNIX) {
274 DEBUG("rmt: stdin is a PIPE (UNIX domain socket)\n");
275 return ("PIPE");
276 }
277 #endif
278 DEBUG1("rmt: stdin NOT_IP socket (sin_family: %d)\n",
279 s->sin_family);
280 return ("NOT_IP");
281 }
282
283 #ifdef HAVE_GETNAMEINFO
284 buffer[0] = '\0';
285 if (debug_file &&
286 getnameinfo(sap, sasize, buffer, sizeof (buffer), NULL, 0,
287 NI_NUMERICHOST) == 0) {
288 DEBUG1("rmt: peername %s\n", buffer);
289 }
290 buffer[0] = '\0';
291 if (getnameinfo(sap, sasize, buffer, sizeof (buffer), NULL, 0,
292 0) == 0) {
293 DEBUG1("rmt: peername %s\n", buffer);
294 return (buffer);
295 }
296 return ("CANNOT_MAP_ADDRESS");
297 #else /* HAVE_GETNAMEINFO */
298 #ifdef HAVE_INET_NTOA
299 (void) js_snprintf(buffer, sizeof(buffer), "%s", inet_ntoa(s->sin_addr));
300 #else
301 (void) js_snprintf(buffer, sizeof(buffer), "%x", s->sin_addr.s_addr);
302 #endif
303 DEBUG1("rscsid: peername %s\n", buffer);
304 he = gethostbyaddr((char *)&s->sin_addr.s_addr, 4, AF_INET);
305 DEBUG1("rscsid: peername %s\n", he!=NULL?he->h_name:buffer);
306 if (he != NULL)
307 return (he->h_name);
308 return (buffer);
309 #endif /* HAVE_GETNAMEINFO */
310 }
311 }
312
313 LOCAL BOOL
314 checktarget()
315 {
316 char *target;
317 char *user;
318 char *host;
319 char *p;
320 int bus;
321 int chan;
322 int tgt;
323 int lun;
324
325 if (peername == NULL)
326 return (FALSE);
327 defltfirst();
328 while ((target = defltnext("ACCESS=")) != NULL) {
329 p = target;
330 while (*p == '\t')
331 p++;
332 user = p;
333 if ((p = strchr(p, '\t')) != NULL)
334 *p++ = '\0';
335 else
336 continue;
337 if (!strmatch(username, user))
338 continue;
339
340 while (*p == '\t')
341 p++;
342 host = p;
343 if ((p = strchr(p, '\t')) != NULL)
344 *p++ = '\0';
345 else
346 continue;
347 if (!strmatch(peername, host))
348 continue;
349
350 p = astoi(p, &bus);
351 if (*p != '\t')
352 continue;
353 p = astoi(p, &chan);
354 if (*p != '\t')
355 continue;
356 p = astoi(p, &tgt);
357 if (*p != '\t')
358 continue;
359 p = astoi(p, &lun);
360
361 if (*p != '\t' && *p != '\n' && *p != '\r' && *p != '\0')
362 continue;
363 DEBUG6("ACCESS %s %s %d.%d,%d,%d\n", user, host, bus, chan, tgt, lun);
364
365 if (bus != -1 && bus != scg_scsibus(scsi_ptr))
366 continue;
367 if (tgt != -1 && tgt != scg_target(scsi_ptr))
368 continue;
369 if (lun != -1 && lun != scg_lun(scsi_ptr))
370 continue;
371 return (TRUE);
372 }
373 return (FALSE);
374 }
375
376 LOCAL BOOL
377 strmatch(str, pat)
378 char *str;
379 char *pat;
380 {
381 int *aux;
382 int *state;
383 int alt;
384 int plen;
385 char *p;
386
387 plen = strlen(pat);
388 aux = malloc(plen*sizeof(int));
389 state = malloc((plen+1)*sizeof(int));
390 if (aux == NULL || state == NULL) {
391 if (aux) free(aux);
392 if (state) free(state);
393 return (FALSE);
394 }
395
396 if ((alt = patcompile((const unsigned char *)pat, plen, aux)) == 0) {
397 /* Bad pattern */
398 free(aux);
399 free(state);
400 return (FALSE);
401 }
402
403 p = (char *)patmatch((const unsigned char *)pat, aux,
404 (const unsigned char *)str, 0,
405 strlen(str), alt, state);
406 free(aux);
407 free(state);
408
409 if (p != NULL && *p == '\0')
410 return (TRUE);
411 return (FALSE);
412 }
413
414 LOCAL void
415 dorscsi()
416 {
417 char c;
418
419 while (readchar(&c) == 1) {
420 seterrno(0);
421
422 switch (c) {
423
424 case 'V': /* "V" ersion */
425 scsiversion();
426 break;
427 case 'O': /* "O" pen */
428 openscsi();
429 break;
430 case 'C': /* "C" lose */
431 closescsi();
432 break;
433 case 'D': /* "D" MA */
434 maxdma();
435 break;
436 case 'M': /* "M" alloc */
437 getbuf();
438 break;
439 case 'F': /* "F" free */
440 freebuf();
441 break;
442 case 'B': /* "B" us */
443 havebus();
444 break;
445 case 'T': /* "T" arget */
446 scsifileno();
447 break;
448 case 'I': /* "I" nitiator */
449 initiator_id();
450 break;
451 case 'A': /* "A" tapi */
452 isatapi();
453 break;
454 case 'R': /* "R" eset */
455 scsireset();
456 break;
457 case 'S': /* "S" end */
458 sendcmd();
459 break;
460
461 default:
462 DEBUG1("rscsid: garbage command '%c'\n", c);
463 rscsierror(0, "Garbage command", NULL);
464 exit(EX_BAD);
465 }
466 }
467 exit(0);
468 }
469
470 LOCAL void
471 scsiversion()
472 {
473 int ret;
474 char *str;
475 char what[CMD_SIZE];
476
477 readarg(what, sizeof(what));
478 DEBUG1("rscsid: V %s\n", what);
479 if (scsi_ptr == NULL) {
480 rscsirespond(-1, EBADF);
481 return;
482 }
483 str = scg_version(scsi_ptr, atoi(what));
484 ret = strlen(str);
485 ret++; /* Include null char */
486 rscsirespond(ret, geterrno());
487 _nixwrite(STDOUT_FILENO, str, ret);
488 }
489
490 LOCAL void
491 openscsi()
492 {
493 char device[CMD_SIZE];
494 char errstr[80];
495 int debug = 0;
496 int lverbose = 0;
497 int ret = 0;
498 char rbuf[1600];
499
500 if (scsi_ptr != NULL)
501 (void) scg_close(scsi_ptr);
502
503 readarg(device, sizeof(device));
504 DEBUG1("rscsid: O %s\n", device);
505 if (strncmp(device, "REMOTE", 6) == 0) {
506 scsi_ptr = NULL;
507 seterrno(EINVAL);
508 } else if (!checkscsi(device)) {
509 scsi_ptr = NULL;
510 seterrno(EACCES);
511 } else {
512 scsi_ptr = scg_open(device, errstr, sizeof(errstr), debug, lverbose);
513 if (scsi_ptr == NULL) {
514 ret = -1;
515 } else {
516 scsi_ptr->silent = 1;
517 scsi_ptr->verbose = 0;
518 scsi_ptr->debug = 0;
519 scsi_ptr->kdebug = 0;
520 }
521 }
522 if (ret < 0) {
523 /*
524 * XXX This is currently the only place where we use the
525 * XXX extended error string.
526 */
527 rscsierror(geterrno(), errmsgstr(geterrno()), errstr);
528 /* rscsirespond(ret, geterrno());*/
529 return;
530 }
531 DEBUG4("rscsid:>A 0 %d.%d,%d,%d\n",
532 scg_scsibus(scsi_ptr),
533 0,
534 scg_target(scsi_ptr),
535 scg_lun(scsi_ptr));
536
537 ret = js_snprintf(rbuf, sizeof(rbuf), "A0\n%d\n%d\n%d\n%d\n",
538 scg_scsibus(scsi_ptr),
539 0,
540 scg_target(scsi_ptr),
541 scg_lun(scsi_ptr));
542 (void) _nixwrite(STDOUT_FILENO, rbuf, ret);
543 }
544
545 LOCAL void
546 closescsi()
547 {
548 int ret;
549 char device[CMD_SIZE];
550
551 readarg(device, sizeof(device));
552 DEBUG1("rscsid: C %s\n", device);
553 ret = scg_close(scsi_ptr);
554 rscsirespond(ret, geterrno());
555 scsi_ptr = NULL;
556 }
557
558 LOCAL void
559 maxdma()
560 {
561 int ret;
562 char amt[CMD_SIZE];
563
564 readarg(amt, sizeof(amt));
565 DEBUG1("rscsid: D %s\n", amt);
566 if (scsi_ptr == NULL) {
567 rscsirespond(-1, EBADF);
568 return;
569 }
570 ret = scg_bufsize(scsi_ptr, atol(amt));
571 rscsirespond(ret, geterrno());
572 }
573
574 LOCAL void
575 getbuf()
576 {
577 int ret = 0;
578 char amt[CMD_SIZE];
579
580 readarg(amt, sizeof(amt));
581 DEBUG1("rscsid: M %s\n", amt);
582 if (scsi_ptr == NULL) {
583 rscsirespond(-1, EBADF);
584 return;
585 }
586 ret = scg_bufsize(scsi_ptr, atol(amt));
587 if (preparebuffer(ret) == NULL)
588 ret = -1;
589 rscsirespond(ret, geterrno());
590 }
591
592 LOCAL void
593 freebuf()
594 {
595 int ret = 0;
596 char dummy[CMD_SIZE];
597
598 readarg(dummy, sizeof(dummy));
599 DEBUG1("rscsid: F %s\n", dummy);
600 if (scsi_ptr == NULL) {
601 rscsirespond(-1, EBADF);
602 return;
603 }
604 scg_freebuf(scsi_ptr);
605 Sbuf = NULL;
606 rscsirespond(ret, geterrno());
607 }
608
609 LOCAL void
610 havebus()
611 {
612 int ret;
613 char bus[CMD_SIZE];
614 char chan[CMD_SIZE];
615
616 readarg(bus, sizeof(bus));
617 readarg(chan, sizeof(chan));
618 DEBUG2("rscsid: B %s.%s\n", bus, chan);
619 if (scsi_ptr == NULL) {
620 rscsirespond(-1, EBADF);
621 return;
622 }
623 ret = scg_havebus(scsi_ptr, atol(bus));
624 rscsirespond(ret, geterrno());
625 }
626
627 LOCAL void
628 scsifileno()
629 {
630 int ret;
631 char bus[CMD_SIZE];
632 char chan[CMD_SIZE];
633 char tgt[CMD_SIZE];
634 char lun[CMD_SIZE];
635
636 readarg(bus, sizeof(bus));
637 readarg(chan, sizeof(chan));
638 readarg(tgt, sizeof(tgt));
639 readarg(lun, sizeof(lun));
640 DEBUG4("rscsid: T %s.%s,%s,%s\n", bus, chan, tgt, lun);
641 if (scsi_ptr == NULL) {
642 rscsirespond(-1, EBADF);
643 return;
644 }
645 seterrno(0);
646 ret = scg_settarget(scsi_ptr, atoi(bus), atoi(tgt), atoi(lun));
647 if (!checktarget()) {
648 scg_settarget(scsi_ptr, -1, -1, -1);
649 ret = -1;
650 }
651 if (geterrno() != 0)
652 rscsirespond(ret, geterrno());
653 else
654 rscsireply(ret);
655 }
656
657 LOCAL void
658 initiator_id()
659 {
660 int ret;
661 char dummy[CMD_SIZE];
662
663 readarg(dummy, sizeof(dummy));
664 DEBUG1("rscsid: I %s\n", dummy);
665 if (scsi_ptr == NULL) {
666 rscsirespond(-1, EBADF);
667 return;
668 }
669 seterrno(0);
670 ret = scg_initiator_id(scsi_ptr);
671 if (geterrno() != 0)
672 rscsirespond(ret, geterrno());
673 else
674 rscsireply(ret);
675 }
676
677 LOCAL void
678 isatapi()
679 {
680 int ret;
681 char dummy[CMD_SIZE];
682
683 readarg(dummy, sizeof(dummy));
684 DEBUG1("rscsid: A %s\n", dummy);
685 if (scsi_ptr == NULL) {
686 rscsirespond(-1, EBADF);
687 return;
688 }
689 seterrno(0);
690 ret = scg_isatapi(scsi_ptr);
691 if (geterrno() != 0)
692 rscsirespond(ret, geterrno());
693 else
694 rscsireply(ret);
695 }
696
697 LOCAL void
698 scsireset()
699 {
700 int ret;
701 char what[CMD_SIZE];
702
703 readarg(what, sizeof(what));
704 DEBUG1("rscsid: R %s\n", what);
705 if (scsi_ptr == NULL) {
706 rscsirespond(-1, EBADF);
707 return;
708 }
709 ret = scg_reset(scsi_ptr, atoi(what));
710 rscsirespond(ret, geterrno());
711 }
712
713 LOCAL void
714 sendcmd()
715 {
716 register struct scg_cmd *scmd;
717 int n;
718 int ret;
719 char count[CMD_SIZE];
720 char flags[CMD_SIZE];
721 char cdb_len[CMD_SIZE];
722 char sense_len[CMD_SIZE];
723 char timeout[CMD_SIZE];
724 int csize;
725 int cflags;
726 int clen;
727 int ctimeout;
728 char rbuf[1600];
729 char *p;
730
731 /*
732 * S count\n
733 * flags\n
734 * cdb_len\n
735 * sense_len\n
736 * timeout\n
737 * <data if available>
738 *
739 * Timeout:
740 * - sss (e.g. 10)
741 * - sss.uuu (e.g. 10.23)
742 */
743 readarg(count, sizeof(count));
744 readarg(flags, sizeof(flags));
745 readarg(cdb_len, sizeof(cdb_len));
746 readarg(sense_len, sizeof(sense_len));
747 readarg(timeout, sizeof(timeout));
748 DEBUG5("rscsid: S %s %s %s %s %s", count, flags, cdb_len, sense_len, timeout);
749 csize = atoi(count);
750 cflags = atoi(flags);
751 clen = atoi(cdb_len);
752
753 p = strchr(timeout, '.');
754 if (p)
755 *p = '\0';
756 ctimeout = atoi(timeout);
757
758 if (scsi_ptr == NULL || clen > SCG_MAX_CMD || csize > Sbufsize) {
759 DEBUG("\n");
760 voidarg(clen);
761 if ((cflags & SCG_RECV_DATA) == 0 && csize > 0)
762 voidarg(csize);
763 rscsirespond(-1, scsi_ptr==NULL ? EBADF : EINVAL);
764 return;
765 }
766
767 scmd = scsi_ptr->scmd;
768 fillbytes((caddr_t)scmd, sizeof(*scmd), '\0');
769 scmd->addr = (caddr_t)Sbuf;
770 scmd->size = csize;
771 scmd->flags = cflags;
772 scmd->cdb_len = clen;
773 scmd->sense_len = atoi(sense_len);
774 scmd->timeout = ctimeout;
775 readbuf((char *)scmd->cdb.cmd_cdb, clen);
776 DEBUG6(" 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X\n",
777 scmd->cdb.cmd_cdb[0],
778 scmd->cdb.cmd_cdb[1],
779 scmd->cdb.cmd_cdb[2],
780 scmd->cdb.cmd_cdb[3],
781 scmd->cdb.cmd_cdb[4],
782 scmd->cdb.cmd_cdb[5]);
783
784 if ((cflags & SCG_RECV_DATA) == 0 && csize > 0)
785 readbuf(Sbuf, scmd->size);
786
787 scsi_ptr->cmdname = "";
788
789 ret = scg_cmd(scsi_ptr);
790
791 n = 0;
792 if ((csize - scmd->resid) > 0)
793 n = csize - scmd->resid;
794
795 /*
796 * A count\n
797 * error\n
798 * errno\n
799 * scb\n
800 * sense_count\n
801 * <data if available>
802 */
803 DEBUG5("rscsid:>A %d %d %d %d %d\n",
804 n,
805 scmd->error,
806 scmd->ux_errno,
807 *(Uchar *)&scmd->scb,
808 scmd->sense_count);
809
810 ret = js_snprintf(rbuf, sizeof(rbuf), "A%d\n%d\n%d\n%d\n%d\n",
811 n,
812 scmd->error,
813 scmd->ux_errno,
814 *(Uchar *)&scmd->scb,
815 scmd->sense_count);
816
817 if (scmd->sense_count > 0) {
818 movebytes(scmd->u_sense.cmd_sense, &rbuf[ret], scmd->sense_count);
819 ret += scmd->sense_count;
820 }
821 if ((cflags & SCG_RECV_DATA) == 0)
822 n = 0;
823 if (n > 0 && ((ret + n) <= sizeof(rbuf))) {
824 movebytes(Sbuf, &rbuf[ret], n);
825 ret += n;
826 n = 0;
827 }
828 (void) _nixwrite(STDOUT_FILENO, rbuf, ret);
829
830 if (n > 0)
831 (void) _nixwrite(STDOUT_FILENO, Sbuf, n);
832 }
833
834 #define READB_SIZE 128
835 LOCAL char readb[READB_SIZE];
836 LOCAL char *readbptr;
837 LOCAL int readbcnt;
838
839 LOCAL int
840 fillrdbuf()
841 {
842 readbptr = readb;
843
844 return (readbcnt = _niread(STDIN_FILENO, readb, READB_SIZE));
845 }
846
847 LOCAL int
848 readchar(cp)
849 char *cp;
850 {
851 if (--readbcnt < 0) {
852 if (fillrdbuf() <= 0)
853 return (readbcnt);
854 --readbcnt;
855 }
856 *cp = *readbptr++;
857 return (1);
858 }
859
860 LOCAL void
861 readbuf(buf, n)
862 register char *buf;
863 register int n;
864 {
865 register int i = 0;
866 register int amt;
867
868 if (readbcnt > 0) {
869 amt = readbcnt;
870 if (amt > n)
871 amt = n;
872 movebytes(readbptr, buf, amt);
873 readbptr += amt;
874 readbcnt -= amt;
875 i += amt;
876 }
877
878 for (; i < n; i += amt) {
879 amt = _niread(STDIN_FILENO, &buf[i], n - i);
880 if (amt <= 0) {
881 DEBUG("rscsid: premature eof\n");
882 rscsierror(0, "Premature eof", NULL);
883 exit(EX_BAD);
884 }
885 }
886 }
887
888 LOCAL void
889 voidarg(n)
890 register int n;
891 {
892 register int i;
893 register int amt;
894 char buf[512];
895
896 for (i = 0; i < n; i += amt) {
897 amt = sizeof(buf);
898 if ((n - i) < amt)
899 amt = n - i;
900 readbuf(buf, amt);
901 }
902 }
903
904 LOCAL void
905 readarg(buf, n)
906 char *buf;
907 int n;
908 {
909 int i;
910
911 for (i = 0; i < n; i++) {
912 if (readchar(&buf[i]) != 1)
913 exit(0);
914 if (buf[i] == '\n')
915 break;
916 }
917 buf[i] = '\0';
918 }
919
920 LOCAL char *
921 preparebuffer(size)
922 int size;
923 {
924 Sbufsize = size;
925 if ((Sbuf = scg_getbuf(scsi_ptr, Sbufsize)) == NULL) {
926 Sbufsize = 0L;
927 return (Sbuf);
928 }
929 size = Sbufsize + 1024; /* Add protocol overhead */
930
931 #ifdef SO_SNDBUF
932 while (size > 512 &&
933 setsockopt(STDOUT_FILENO, SOL_SOCKET, SO_SNDBUF, (char *)&size, sizeof (size)) < 0)
934 size -= 512;
935 DEBUG1("rscsid: sndsize: %d\n", size);
936 #endif
937 #ifdef SO_RCVBUF
938 while (size > 512 &&
939 setsockopt(STDIN_FILENO, SOL_SOCKET, SO_RCVBUF, (char *)&size, sizeof (size)) < 0)
940 size -= 512;
941 DEBUG1("rscsid: rcvsize: %d\n", size);
942 #endif
943 return (Sbuf);
944 }
945
946 LOCAL int
947 checkscsi(device)
948 char *device;
949 {
950 #ifdef CHECKTAPE
951 if (strncmp(device, "/dev/rst", 8) == 0 ||
952 strncmp(device, "/dev/nrst", 9) == 0 ||
953 strcmp(device, "/dev/zero") == 0 ||
954 strcmp(device, "/dev/null") == 0)
955 return (1);
956 return (0);
957 #else
958 return (1);
959 #endif
960 }
961
962 LOCAL void
963 rscsirespond(ret, err)
964 int ret;
965 int err;
966 {
967 if (ret < 0) {
968 rscsierror(err, errmsgstr(err), NULL);
969 } else {
970 rscsireply(ret);
971 }
972 }
973
974 LOCAL void
975 rscsireply(ret)
976 int ret;
977 {
978 char rbuf[CMD_SIZE];
979
980 DEBUG1("rscsid:>A %d\n", ret);
981 (void) js_snprintf(rbuf, sizeof(rbuf), "A%d\n", ret);
982 (void) _nixwrite(STDOUT_FILENO, rbuf, strlen(rbuf));
983 }
984
985 LOCAL void
986 rscsierror(err, str, xstr)
987 int err;
988 char *str;
989 char *xstr;
990 {
991 char rbuf[1600];
992 int xlen = 0;
993 int n;
994
995 if (xstr != NULL)
996 xlen = strlen(xstr) + 1;
997
998 DEBUG3("rscsid:>E %d (%s) [%s]\n", err, str, xstr?xstr:"");
999 n = js_snprintf(rbuf, sizeof(rbuf), "E%d\n%s\n%d\n", err, str, xlen);
1000
1001 if (xlen > 0 && ((xlen + n) <= sizeof(rbuf))) {
1002 movebytes(xstr, &rbuf[n], xlen);
1003 n += xlen;
1004 xlen = 0;
1005 }
1006 (void) _nixwrite(STDOUT_FILENO, rbuf, n);
1007 if (xlen > 0)
1008 (void) _nixwrite(STDOUT_FILENO, xstr, xlen);
1009 }
1010 #endif /* USE_REMOTE */

  ViewVC Help
Powered by ViewVC 1.1.5