1 #define USE_REMOTE
2 /* @(#)scsi-remote.c 1.16 04/08/24 Copyright 1990,2000-2003 J. Schilling */
3 #ifndef lint
4 static char __sccsid[] =
5 "@(#)scsi-remote.c 1.16 04/08/24 Copyright 1990,2000-2003 J. Schilling";
6 #endif
7 /*
8 * Remote SCSI user level command transport routines
9 *
10 * Warning: you may change this source, but if you do that
11 * you need to change the _scg_version and _scg_auth* string below.
12 * You may not return "schily" for an SCG_AUTHOR request anymore.
13 * Choose your name instead of "schily" and make clear that the version
14 * string is related to a modified source.
15 *
16 * Copyright (c) 1990,2000-2003 J. Schilling
17 */
18 /*
19 * This program is free software; you can redistribute it and/or modify
20 * it under the terms of the GNU General Public License as published by
21 * the Free Software Foundation; either version 2, or (at your option)
22 * any later version.
23 *
24 * This program is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 * GNU General Public License for more details.
28 *
29 * You should have received a copy of the GNU General Public License along with
30 * this program; see the file COPYING. If not, write to the Free Software
31 * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
32 */
33
34 #include <mconfig.h>
35
36 #if !defined(HAVE_FORK) || !defined(HAVE_SOCKETPAIR) || !defined(HAVE_DUP2)
37 #undef USE_RCMD_RSH
38 #endif
39 /*
40 * We may work without getservbyname() if we restructure the code not to
41 * use the port number if we only use _rcmdrsh().
42 */
43 #if !defined(HAVE_GETSERVBYNAME)
44 #undef USE_REMOTE /* Cannot get rcmd() port # */
45 #endif
46 #if (!defined(HAVE_NETDB_H) || !defined(HAVE_RCMD)) && !defined(USE_RCMD_RSH)
47 #undef USE_REMOTE /* There is no rcmd() */
48 #endif
49
50 #ifdef USE_REMOTE
51 #include <stdio.h>
52 #include <sys/types.h>
53 #include <fctldefs.h>
54 #ifdef HAVE_SYS_SOCKET_H
55 #include <sys/socket.h>
56 #endif
57 #include <errno.h>
58 #include <signal.h>
59 #ifdef HAVE_NETDB_H
60 #include <netdb.h>
61 #endif
62 #ifdef HAVE_PWD_H
63 #include <pwd.h>
64 #endif
65 #include <standard.h>
66 #include <stdxlib.h>
67 #include <unixstd.h>
68 #include <strdefs.h>
69 #include <schily.h>
70
71 #include <scg/scgcmd.h>
72 #include <scg/scsitransp.h>
73
74 #if defined(SIGDEFER) || defined(SVR4)
75 #define signal sigset
76 #endif
77
78 /*
79 * On Cygwin, there are no privilleged ports.
80 * On UNIX, rcmd() uses privilleged port that only work for root.
81 */
82 #ifdef IS_CYGWIN
83 #define privport_ok() (1)
84 #else
85 #define privport_ok() (geteuid() == 0)
86 #endif
87
88 #define CMD_SIZE 80
89
90 #define MAX_SCG 16 /* Max # of SCSI controllers */
91 #define MAX_TGT 16
92 #define MAX_LUN 8
93
94 /*extern BOOL debug;*/
95 LOCAL BOOL debug = 1;
96
97 LOCAL char _scg_trans_version[] = "remote-1.16"; /* The version for remote SCSI */
98 LOCAL char _scg_auth_schily[] = "schily"; /* The author for this module */
99
100 LOCAL int scgo_rsend __PR((SCSI *scgp));
101 LOCAL char * scgo_rversion __PR((SCSI *scgp, int what));
102 LOCAL int scgo_rhelp __PR((SCSI *scgp, FILE *f));
103 LOCAL int scgo_ropen __PR((SCSI *scgp, char *device));
104 LOCAL int scgo_rclose __PR((SCSI *scgp));
105 LOCAL long scgo_rmaxdma __PR((SCSI *scgp, long amt));
106 LOCAL void * scgo_rgetbuf __PR((SCSI *scgp, long amt));
107 LOCAL void scgo_rfreebuf __PR((SCSI *scgp));
108 LOCAL BOOL scgo_rhavebus __PR((SCSI *scgp, int busno));
109 LOCAL int scgo_rfileno __PR((SCSI *scgp, int busno, int tgt, int tlun));
110 LOCAL int scgo_rinitiator_id __PR((SCSI *scgp));
111 LOCAL int scgo_risatapi __PR((SCSI *scgp));
112 LOCAL int scgo_rreset __PR((SCSI *scgp, int what));
113
114 /*
115 * XXX We should rethink the fd parameter now that we introduced
116 * XXX the rscsirchar() function and most access of remfd is done
117 * XXX via scglocal(scgp)->remfd.
118 */
119 LOCAL void rscsiabrt __PR((int sig));
120 LOCAL int rscsigetconn __PR((SCSI *scgp, char *host));
121 LOCAL char *rscsiversion __PR((SCSI *scgp, int fd, int what));
122 LOCAL int rscsiopen __PR((SCSI *scgp, int fd, char *fname));
123 LOCAL int rscsiclose __PR((SCSI *scgp, int fd));
124 LOCAL int rscsimaxdma __PR((SCSI *scgp, int fd, long amt));
125 LOCAL int rscsigetbuf __PR((SCSI *scgp, int fd, long amt));
126 LOCAL int rscsifreebuf __PR((SCSI *scgp, int fd));
127 LOCAL int rscsihavebus __PR((SCSI *scgp, int fd, int bus));
128 LOCAL int rscsifileno __PR((SCSI *scgp, int fd, int busno, int tgt, int tlun));
129 LOCAL int rscsiinitiator_id __PR((SCSI *scgp, int fd));
130 LOCAL int rscsiisatapi __PR((SCSI *scgp, int fd));
131 LOCAL int rscsireset __PR((SCSI *scgp, int fd, int what));
132 LOCAL int rscsiscmd __PR((SCSI *scgp, int fd, struct scg_cmd *sp));
133 LOCAL int rscsifillrbuf __PR((SCSI *scgp));
134 LOCAL int rscsirchar __PR((SCSI *scgp, char *cp));
135 LOCAL int rscsireadbuf __PR((SCSI *scgp, int fd, char *buf, int count));
136 LOCAL void rscsivoidarg __PR((SCSI *scgp, int fd, int count));
137 LOCAL int rscsicmd __PR((SCSI *scgp, int fd, char *name, char *cbuf));
138 LOCAL void rscsisendcmd __PR((SCSI *scgp, int fd, char *name, char *cbuf));
139 LOCAL int rscsigetline __PR((SCSI *scgp, int fd, char *line, int count));
140 LOCAL int rscsireadnum __PR((SCSI *scgp, int fd));
141 LOCAL int rscsigetstatus __PR((SCSI *scgp, int fd, char *name));
142 LOCAL int rscsiaborted __PR((SCSI *scgp, int fd));
143 #ifdef USE_RCMD_RSH
144 LOCAL int _rcmdrsh __PR((char **ahost, int inport,
145 const char *locuser,
146 const char *remuser,
147 const char *cmd,
148 const char *rsh));
149 #endif
150
151 /*--------------------------------------------------------------------------*/
152
153 #define READBUF_SIZE 128
154
155 struct scg_local {
156 int remfd;
157 char readbuf[READBUF_SIZE];
158 char *readbptr;
159 int readbcnt;
160 BOOL isopen;
161 int rsize;
162 int wsize;
163 char *v_version;
164 char *v_author;
165 char *v_sccs_id;
166 };
167
168
169 #define scglocal(p) ((struct scg_local *)((p)->local))
170
171 scg_ops_t remote_ops = {
172 scgo_rsend, /* "S" end */
173 scgo_rversion, /* "V" ersion */
174 scgo_rhelp, /* help */
175 scgo_ropen, /* "O" pen */
176 scgo_rclose, /* "C" lose */
177 scgo_rmaxdma, /* "D" MA */
178 scgo_rgetbuf, /* "M" alloc */
179 scgo_rfreebuf, /* "F" free */
180 scgo_rhavebus, /* "B" us */
181 scgo_rfileno, /* "T" arget */
182 scgo_rinitiator_id, /* "I" nitiator */
183 scgo_risatapi, /* "A" tapi */
184 scgo_rreset, /* "R" eset */
185 };
186
187 /*
188 * Return our ops ptr.
189 */
190 scg_ops_t *
scg_remote()191 scg_remote()
192 {
193 return (&remote_ops);
194 }
195
196 /*
197 * Return version information for the low level SCSI transport code.
198 * This has been introduced to make it easier to trace down problems
199 * in applications.
200 */
201 LOCAL char *
scgo_rversion(scgp,what)202 scgo_rversion(scgp, what)
203 SCSI *scgp;
204 int what;
205 {
206 int f;
207
208 if (scgp->local == NULL)
209 return ((char *)0);
210
211 f = scglocal(scgp)->remfd;
212 if (scgp != (SCSI *)0) {
213 switch (what) {
214
215 case SCG_VERSION:
216 return (_scg_trans_version);
217 /*
218 * If you changed this source, you are not allowed to
219 * return "schily" for the SCG_AUTHOR request.
220 */
221 case SCG_AUTHOR:
222 return (_scg_auth_schily);
223 case SCG_SCCS_ID:
224 return (__sccsid);
225
226 case SCG_RVERSION:
227 if (scglocal(scgp)->v_version == NULL)
228 scglocal(scgp)->v_version = rscsiversion(scgp, f, SCG_VERSION);
229 return (scglocal(scgp)->v_version);
230 /*
231 * If you changed this source, you are not allowed to
232 * return "schily" for the SCG_AUTHOR request.
233 */
234 case SCG_RAUTHOR:
235 if (scglocal(scgp)->v_author == NULL)
236 scglocal(scgp)->v_author = rscsiversion(scgp, f, SCG_AUTHOR);
237 return (scglocal(scgp)->v_author);
238 case SCG_RSCCS_ID:
239 if (scglocal(scgp)->v_sccs_id == NULL)
240 scglocal(scgp)->v_sccs_id = rscsiversion(scgp, f, SCG_SCCS_ID);
241 return (scglocal(scgp)->v_sccs_id);
242 }
243 }
244 return ((char *)0);
245 }
246
247 LOCAL int
scgo_rhelp(scgp,f)248 scgo_rhelp(scgp, f)
249 SCSI *scgp;
250 FILE *f;
251 {
252 __scg_help(f, "RSCSI", "Remote SCSI",
253 "REMOTE:", "rscsi@host:bus,target,lun", "REMOTE:rscsi@host:1,2,0", TRUE, FALSE);
254 return (0);
255 }
256
257 LOCAL int
scgo_ropen(scgp,device)258 scgo_ropen(scgp, device)
259 SCSI *scgp;
260 char *device;
261 {
262 int busno = scg_scsibus(scgp);
263 int tgt = scg_target(scgp);
264 int tlun = scg_lun(scgp);
265 register int f;
266 register int nopen = 0;
267 char devname[128];
268 char *p;
269
270 if (scgp->overbose)
271 error("Warning: Using remote SCSI interface.\n");
272
273 if (busno >= MAX_SCG || tgt >= MAX_TGT || tlun >= MAX_LUN) {
274 errno = EINVAL;
275 if (scgp->errstr)
276 js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
277 "Illegal value for busno, target or lun '%d,%d,%d'",
278 busno, tgt, tlun);
279
280 return (-1);
281 }
282 if (scgp->local == NULL) {
283 scgp->local = malloc(sizeof (struct scg_local));
284 if (scgp->local == NULL)
285 return (0);
286 scglocal(scgp)->remfd = -1;
287 scglocal(scgp)->readbptr = scglocal(scgp)->readbuf;
288 scglocal(scgp)->readbcnt = 0;
289 scglocal(scgp)->isopen = FALSE;
290 scglocal(scgp)->rsize = 0;
291 scglocal(scgp)->wsize = 0;
292 scglocal(scgp)->v_version = NULL;
293 scglocal(scgp)->v_author = NULL;
294 scglocal(scgp)->v_sccs_id = NULL;
295 }
296
297 if (device == NULL || (strncmp(device, "REMOTE", 6) != 0) ||
298 (device = strchr(device, ':')) == NULL) {
299 if (scgp->errstr)
300 js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
301 "Illegal remote device syntax");
302 return (-1);
303 }
304 device++;
305 /*
306 * Save non user@host:device
307 */
308 js_snprintf(devname, sizeof (devname), "%s", device);
309
310 if ((p = strchr(devname, ':')) != NULL)
311 *p++ = '\0';
312
313 f = rscsigetconn(scgp, devname);
314 if (f < 0) {
315 if (scgp->errstr)
316 js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
317 "Cannot get connection to remote host");
318 return (-1);
319 }
320 scglocal(scgp)->remfd = f;
321 debug = scgp->debug;
322 if (rscsiopen(scgp, f, p) >= 0) {
323 nopen++;
324 scglocal(scgp)->isopen = TRUE;
325 }
326 return (nopen);
327 }
328
329 LOCAL int
scgo_rclose(scgp)330 scgo_rclose(scgp)
331 SCSI *scgp;
332 {
333 register int f;
334 int ret;
335
336 if (scgp->local == NULL)
337 return (-1);
338
339 if (scglocal(scgp)->v_version != NULL) {
340 free(scglocal(scgp)->v_version);
341 scglocal(scgp)->v_version = NULL;
342 }
343 if (scglocal(scgp)->v_author != NULL) {
344 free(scglocal(scgp)->v_author);
345 scglocal(scgp)->v_author = NULL;
346 }
347 if (scglocal(scgp)->v_sccs_id != NULL) {
348 free(scglocal(scgp)->v_sccs_id);
349 scglocal(scgp)->v_sccs_id = NULL;
350 }
351
352 f = scglocal(scgp)->remfd;
353 if (f < 0 || !scglocal(scgp)->isopen)
354 return (0);
355 ret = rscsiclose(scgp, f);
356 scglocal(scgp)->isopen = FALSE;
357 close(f);
358 scglocal(scgp)->remfd = -1;
359 return (ret);
360 }
361
362 LOCAL long
scgo_rmaxdma(scgp,amt)363 scgo_rmaxdma(scgp, amt)
364 SCSI *scgp;
365 long amt;
366 {
367 if (scgp->local == NULL)
368 return (-1L);
369
370 return (rscsimaxdma(scgp, scglocal(scgp)->remfd, amt));
371 }
372
373 LOCAL void *
scgo_rgetbuf(scgp,amt)374 scgo_rgetbuf(scgp, amt)
375 SCSI *scgp;
376 long amt;
377 {
378 int ret;
379
380 if (scgp->local == NULL)
381 return ((void *)0);
382
383 ret = rscsigetbuf(scgp, scglocal(scgp)->remfd, amt);
384 if (ret < 0)
385 return ((void *)0);
386
387 #ifdef HAVE_VALLOC
388 scgp->bufbase = (void *)valloc((size_t)amt);
389 #else
390 scgp->bufbase = (void *)malloc((size_t)amt);
391 #endif
392 if (scgp->bufbase == NULL) {
393 scgo_rfreebuf(scgp);
394 return ((void *)0);
395 }
396 return (scgp->bufbase);
397 }
398
399 LOCAL void
scgo_rfreebuf(scgp)400 scgo_rfreebuf(scgp)
401 SCSI *scgp;
402 {
403 int f;
404
405 if (scgp->bufbase)
406 free(scgp->bufbase);
407 scgp->bufbase = NULL;
408
409 if (scgp->local == NULL)
410 return;
411
412 f = scglocal(scgp)->remfd;
413 if (f < 0 || !scglocal(scgp)->isopen)
414 return;
415 rscsifreebuf(scgp, f);
416 }
417
418 LOCAL BOOL
scgo_rhavebus(scgp,busno)419 scgo_rhavebus(scgp, busno)
420 SCSI *scgp;
421 int busno;
422 {
423 if (scgp->local == NULL || busno < 0 || busno >= MAX_SCG)
424 return (FALSE);
425
426 return (rscsihavebus(scgp, scglocal(scgp)->remfd, busno));
427 }
428
429 LOCAL int
scgo_rfileno(scgp,busno,tgt,tlun)430 scgo_rfileno(scgp, busno, tgt, tlun)
431 SCSI *scgp;
432 int busno;
433 int tgt;
434 int tlun;
435 {
436 int f;
437
438 if (scgp->local == NULL ||
439 busno < 0 || busno >= MAX_SCG ||
440 tgt < 0 || tgt >= MAX_TGT ||
441 tlun < 0 || tlun >= MAX_LUN)
442 return (-1);
443
444 f = scglocal(scgp)->remfd;
445 if (f < 0 || !scglocal(scgp)->isopen)
446 return (-1);
447 return (rscsifileno(scgp, f, busno, tgt, tlun));
448 }
449
450 LOCAL int
scgo_rinitiator_id(scgp)451 scgo_rinitiator_id(scgp)
452 SCSI *scgp;
453 {
454 if (scgp->local == NULL)
455 return (-1);
456
457 return (rscsiinitiator_id(scgp, scglocal(scgp)->remfd));
458 }
459
460 LOCAL int
scgo_risatapi(scgp)461 scgo_risatapi(scgp)
462 SCSI *scgp;
463 {
464 if (scgp->local == NULL)
465 return (-1);
466
467 return (rscsiisatapi(scgp, scglocal(scgp)->remfd));
468 }
469
470 LOCAL int
scgo_rreset(scgp,what)471 scgo_rreset(scgp, what)
472 SCSI *scgp;
473 int what;
474 {
475 if (scgp->local == NULL)
476 return (-1);
477
478 return (rscsireset(scgp, scglocal(scgp)->remfd, what));
479 }
480
481 LOCAL int
scgo_rsend(scgp)482 scgo_rsend(scgp)
483 SCSI *scgp;
484 {
485 struct scg_cmd *sp = scgp->scmd;
486 int ret;
487
488 if (scgp->local == NULL)
489 return (-1);
490
491 if (scgp->fd < 0) {
492 sp->error = SCG_FATAL;
493 return (0);
494 }
495 ret = rscsiscmd(scgp, scglocal(scgp)->remfd, scgp->scmd);
496
497 return (ret);
498 }
499
500 /*--------------------------------------------------------------------------*/
501 LOCAL void
rscsiabrt(sig)502 rscsiabrt(sig)
503 int sig;
504 {
505 rscsiaborted((SCSI *)0, -1);
506 }
507
508 LOCAL int
rscsigetconn(scgp,host)509 rscsigetconn(scgp, host)
510 SCSI *scgp;
511 char *host;
512 {
513 static struct servent *sp = 0;
514 static struct passwd *pw = 0;
515 char *name = "root";
516 char *p;
517 char *rscsi;
518 char *rsh;
519 int rscsisock;
520 char *rscsipeer;
521 char rscsiuser[128];
522
523
524 signal(SIGPIPE, rscsiabrt);
525 if (sp == 0) {
526 sp = getservbyname("shell", "tcp");
527 if (sp == 0) {
528 comerrno(EX_BAD, "shell/tcp: unknown service\n");
529 /* NOTREACHED */
530 }
531 pw = getpwuid(getuid());
532 if (pw == 0) {
533 comerrno(EX_BAD, "who are you? No passwd entry found.\n");
534 /* NOTREACHED */
535 }
536 }
537 if ((p = strchr(host, '@')) != NULL) {
538 size_t d = p - host;
539
540 if (d > sizeof (rscsiuser))
541 d = sizeof (rscsiuser);
542 js_snprintf(rscsiuser, sizeof (rscsiuser), "%.*s", (int)d, host);
543 name = rscsiuser;
544 host = &p[1];
545 } else {
546 name = pw->pw_name;
547 }
548 if (scgp->debug > 0)
549 errmsgno(EX_BAD, "locuser: '%s' rscsiuser: '%s' host: '%s'\n",
550 pw->pw_name, name, host);
551 rscsipeer = host;
552
553 if ((rscsi = getenv("RSCSI")) == NULL)
554 rscsi = "/opt/schily/sbin/rscsi";
555 rsh = getenv("RSH");
556
557 #ifdef USE_RCMD_RSH
558 if (!privport_ok() || rsh != NULL)
559 rscsisock = _rcmdrsh(&rscsipeer, (unsigned short)sp->s_port,
560 pw->pw_name, name, rscsi, rsh);
561 else
562 #endif
563 #ifdef HAVE_RCMD
564 rscsisock = rcmd(&rscsipeer, (unsigned short)sp->s_port,
565 pw->pw_name, name, rscsi, 0);
566 #else
567 rscsisock = _rcmdrsh(&rscsipeer, (unsigned short)sp->s_port,
568 pw->pw_name, name, rscsi, rsh);
569 #endif
570
571 return (rscsisock);
572 }
573
574 LOCAL char *
rscsiversion(scgp,fd,what)575 rscsiversion(scgp, fd, what)
576 SCSI *scgp;
577 int fd;
578 int what;
579 {
580 char cbuf[CMD_SIZE];
581 char *p;
582 int ret;
583
584 js_snprintf(cbuf, sizeof (cbuf), "V%d\n", what);
585 ret = rscsicmd(scgp, fd, "version", cbuf);
586 p = malloc(ret);
587 if (p == NULL)
588 return (p);
589 rscsireadbuf(scgp, fd, p, ret);
590 return (p);
591 }
592
593 LOCAL int
rscsiopen(scgp,fd,fname)594 rscsiopen(scgp, fd, fname)
595 SCSI *scgp;
596 int fd;
597 char *fname;
598 {
599 char cbuf[CMD_SIZE];
600 int ret;
601 int bus;
602 int chan;
603 int tgt;
604 int lun;
605
606 js_snprintf(cbuf, sizeof (cbuf), "O%s\n", fname?fname:"");
607 ret = rscsicmd(scgp, fd, "open", cbuf);
608 if (ret < 0)
609 return (ret);
610
611 bus = rscsireadnum(scgp, fd);
612 chan = rscsireadnum(scgp, fd);
613 tgt = rscsireadnum(scgp, fd);
614 lun = rscsireadnum(scgp, fd);
615
616 scg_settarget(scgp, bus, tgt, lun);
617 return (ret);
618 }
619
620 LOCAL int
rscsiclose(scgp,fd)621 rscsiclose(scgp, fd)
622 SCSI *scgp;
623 int fd;
624 {
625 return (rscsicmd(scgp, fd, "close", "C\n"));
626 }
627
628 LOCAL int
rscsimaxdma(scgp,fd,amt)629 rscsimaxdma(scgp, fd, amt)
630 SCSI *scgp;
631 int fd;
632 long amt;
633 {
634 char cbuf[CMD_SIZE];
635
636 js_snprintf(cbuf, sizeof (cbuf), "D%ld\n", amt);
637 return (rscsicmd(scgp, fd, "maxdma", cbuf));
638 }
639
640 LOCAL int
rscsigetbuf(scgp,fd,amt)641 rscsigetbuf(scgp, fd, amt)
642 SCSI *scgp;
643 int fd;
644 long amt;
645 {
646 char cbuf[CMD_SIZE];
647 int size;
648 int ret;
649
650 js_snprintf(cbuf, sizeof (cbuf), "M%ld\n", amt);
651 ret = rscsicmd(scgp, fd, "getbuf", cbuf);
652 if (ret < 0)
653 return (ret);
654
655 size = ret + 1024; /* Add protocol overhead */
656
657 #ifdef SO_SNDBUF
658 if (size > scglocal(scgp)->wsize) while (size > 512 &&
659 setsockopt(fd, SOL_SOCKET, SO_SNDBUF,
660 (char *)&size, sizeof (size)) < 0) {
661 size -= 512;
662 }
663 if (size > scglocal(scgp)->wsize) {
664 scglocal(scgp)->wsize = size;
665 if (scgp->debug > 0)
666 errmsgno(EX_BAD, "sndsize: %d\n", size);
667 }
668 #endif
669 #ifdef SO_RCVBUF
670 if (size > scglocal(scgp)->rsize) while (size > 512 &&
671 setsockopt(fd, SOL_SOCKET, SO_RCVBUF,
672 (char *)&size, sizeof (size)) < 0) {
673 size -= 512;
674 }
675 if (size > scglocal(scgp)->rsize) {
676 scglocal(scgp)->rsize = size;
677 if (scgp->debug > 0)
678 errmsgno(EX_BAD, "rcvsize: %d\n", size);
679 }
680 #endif
681 return (ret);
682 }
683
684 LOCAL int
rscsifreebuf(scgp,fd)685 rscsifreebuf(scgp, fd)
686 SCSI *scgp;
687 int fd;
688 {
689 return (rscsicmd(scgp, fd, "freebuf", "F\n"));
690 }
691
692 LOCAL int
rscsihavebus(scgp,fd,busno)693 rscsihavebus(scgp, fd, busno)
694 SCSI *scgp;
695 int fd;
696 int busno;
697 {
698 char cbuf[2*CMD_SIZE];
699
700 js_snprintf(cbuf, sizeof (cbuf), "B%d\n%d\n",
701 busno,
702 0);
703 return (rscsicmd(scgp, fd, "havebus", cbuf));
704 }
705
706 LOCAL int
rscsifileno(scgp,fd,busno,tgt,tlun)707 rscsifileno(scgp, fd, busno, tgt, tlun)
708 SCSI *scgp;
709 int fd;
710 int busno;
711 int tgt;
712 int tlun;
713 {
714 char cbuf[3*CMD_SIZE];
715
716 js_snprintf(cbuf, sizeof (cbuf), "T%d\n%d\n%d\n%d\n",
717 busno,
718 0,
719 tgt,
720 tlun);
721 return (rscsicmd(scgp, fd, "fileno", cbuf));
722 }
723
724 LOCAL int
rscsiinitiator_id(scgp,fd)725 rscsiinitiator_id(scgp, fd)
726 SCSI *scgp;
727 int fd;
728 {
729 return (rscsicmd(scgp, fd, "initiator id", "I\n"));
730 }
731
732 LOCAL int
rscsiisatapi(scgp,fd)733 rscsiisatapi(scgp, fd)
734 SCSI *scgp;
735 int fd;
736 {
737 return (rscsicmd(scgp, fd, "isatapi", "A\n"));
738 }
739
740 LOCAL int
rscsireset(scgp,fd,what)741 rscsireset(scgp, fd, what)
742 SCSI *scgp;
743 int fd;
744 int what;
745 {
746 char cbuf[CMD_SIZE];
747
748 js_snprintf(cbuf, sizeof (cbuf), "R%d\n", what);
749 return (rscsicmd(scgp, fd, "reset", cbuf));
750 }
751
752 LOCAL int
rscsiscmd(scgp,fd,sp)753 rscsiscmd(scgp, fd, sp)
754 SCSI *scgp;
755 int fd;
756 struct scg_cmd *sp;
757 {
758 char cbuf[1600];
759 int ret;
760 int amt = 0;
761 int voidsize = 0;
762
763 ret = js_snprintf(cbuf, sizeof (cbuf), "S%d\n%d\n%d\n%d\n%d\n",
764 sp->size, sp->flags,
765 sp->cdb_len, sp->sense_len,
766 sp->timeout);
767 movebytes(sp->cdb.cmd_cdb, &cbuf[ret], sp->cdb_len);
768 ret += sp->cdb_len;
769
770 if ((sp->flags & SCG_RECV_DATA) == 0 && sp->size > 0) {
771 amt = sp->size;
772 if ((ret + amt) <= sizeof (cbuf)) {
773 movebytes(sp->addr, &cbuf[ret], amt);
774 ret += amt;
775 amt = 0;
776 }
777 }
778 errno = 0;
779 if (_nixwrite(fd, cbuf, ret) != ret)
780 rscsiaborted(scgp, fd);
781
782 if (amt > 0) {
783 if (_nixwrite(fd, sp->addr, amt) != amt)
784 rscsiaborted(scgp, fd);
785 }
786
787 ret = rscsigetstatus(scgp, fd, "sendcmd");
788 if (ret < 0)
789 return (ret);
790
791 sp->resid = sp->size - ret;
792 sp->error = rscsireadnum(scgp, fd);
793 sp->ux_errno = rscsireadnum(scgp, fd);
794 *(Uchar *)&sp->scb = rscsireadnum(scgp, fd);
795 sp->sense_count = rscsireadnum(scgp, fd);
796
797 if (sp->sense_count > SCG_MAX_SENSE) {
798 voidsize = sp->sense_count - SCG_MAX_SENSE;
799 sp->sense_count = SCG_MAX_SENSE;
800 }
801 if (sp->sense_count > 0) {
802 rscsireadbuf(scgp, fd, (char *)sp->u_sense.cmd_sense, sp->sense_count);
803 rscsivoidarg(scgp, fd, voidsize);
804 }
805
806 if ((sp->flags & SCG_RECV_DATA) != 0 && ret > 0)
807 rscsireadbuf(scgp, fd, sp->addr, ret);
808
809 return (0);
810 }
811
812 LOCAL int
rscsifillrbuf(scgp)813 rscsifillrbuf(scgp)
814 SCSI *scgp;
815 {
816 scglocal(scgp)->readbptr = scglocal(scgp)->readbuf;
817
818 return (scglocal(scgp)->readbcnt =
819 _niread(scglocal(scgp)->remfd,
820 scglocal(scgp)->readbuf, READBUF_SIZE));
821 }
822
823 LOCAL int
rscsirchar(scgp,cp)824 rscsirchar(scgp, cp)
825 SCSI *scgp;
826 char *cp;
827 {
828 if (--(scglocal(scgp)->readbcnt) < 0) {
829 if (rscsifillrbuf(scgp) <= 0)
830 return (scglocal(scgp)->readbcnt);
831 --(scglocal(scgp)->readbcnt);
832 }
833 *cp = *(scglocal(scgp)->readbptr)++;
834 return (1);
835 }
836
837 LOCAL int
rscsireadbuf(scgp,fd,buf,count)838 rscsireadbuf(scgp, fd, buf, count)
839 SCSI *scgp;
840 int fd;
841 char *buf;
842 int count;
843 {
844 register int n = count;
845 register int amt = 0;
846 register int cnt;
847
848 if (scglocal(scgp)->readbcnt > 0) {
849 cnt = scglocal(scgp)->readbcnt;
850 if (cnt > n)
851 cnt = n;
852 movebytes(scglocal(scgp)->readbptr, buf, cnt);
853 scglocal(scgp)->readbptr += cnt;
854 scglocal(scgp)->readbcnt -= cnt;
855 amt += cnt;
856 }
857 while (amt < n) {
858 if ((cnt = _niread(fd, &buf[amt], n - amt)) <= 0) {
859 return (rscsiaborted(scgp, fd));
860 }
861 amt += cnt;
862 }
863 return (amt);
864 }
865
866 LOCAL void
rscsivoidarg(scgp,fd,n)867 rscsivoidarg(scgp, fd, n)
868 SCSI *scgp;
869 int fd;
870 register int n;
871 {
872 register int i;
873 register int amt;
874 char buf[512];
875
876 for (i = 0; i < n; i += amt) {
877 amt = sizeof (buf);
878 if ((n - i) < amt)
879 amt = n - i;
880 rscsireadbuf(scgp, fd, buf, amt);
881 }
882 }
883
884 LOCAL int
rscsicmd(scgp,fd,name,cbuf)885 rscsicmd(scgp, fd, name, cbuf)
886 SCSI *scgp;
887 int fd;
888 char *name;
889 char *cbuf;
890 {
891 rscsisendcmd(scgp, fd, name, cbuf);
892 return (rscsigetstatus(scgp, fd, name));
893 }
894
895 LOCAL void
rscsisendcmd(scgp,fd,name,cbuf)896 rscsisendcmd(scgp, fd, name, cbuf)
897 SCSI *scgp;
898 int fd;
899 char *name;
900 char *cbuf;
901 {
902 int buflen = strlen(cbuf);
903
904 errno = 0;
905 if (_nixwrite(fd, cbuf, buflen) != buflen)
906 rscsiaborted(scgp, fd);
907 }
908
909 LOCAL int
rscsigetline(scgp,fd,line,count)910 rscsigetline(scgp, fd, line, count)
911 SCSI *scgp;
912 int fd;
913 char *line;
914 int count;
915 {
916 register char *cp;
917
918 for (cp = line; cp < &line[count]; cp++) {
919 if (rscsirchar(scgp, cp) != 1)
920 return (rscsiaborted(scgp, fd));
921
922 if (*cp == '\n') {
923 *cp = '\0';
924 return (cp - line);
925 }
926 }
927 return (rscsiaborted(scgp, fd));
928 }
929
930 LOCAL int
rscsireadnum(scgp,fd)931 rscsireadnum(scgp, fd)
932 SCSI *scgp;
933 int fd;
934 {
935 char cbuf[CMD_SIZE];
936
937 rscsigetline(scgp, fd, cbuf, sizeof (cbuf));
938 return (atoi(cbuf));
939 }
940
941 LOCAL int
rscsigetstatus(scgp,fd,name)942 rscsigetstatus(scgp, fd, name)
943 SCSI *scgp;
944 int fd;
945 char *name;
946 {
947 char cbuf[CMD_SIZE];
948 char code;
949 int number;
950 int count;
951 int voidsize = 0;
952
953 rscsigetline(scgp, fd, cbuf, sizeof (cbuf));
954 code = cbuf[0];
955 number = atoi(&cbuf[1]);
956
957 if (code == 'E' || code == 'F') {
958 rscsigetline(scgp, fd, cbuf, sizeof (cbuf));
959 if (code == 'F') /* should close file ??? */
960 rscsiaborted(scgp, fd);
961
962 rscsigetline(scgp, fd, cbuf, sizeof (cbuf));
963 count = atoi(cbuf);
964 if (count > 0) {
965 if (scgp->errstr == NULL) {
966 voidsize = count;
967 count = 0;
968 } else if (count > SCSI_ERRSTR_SIZE) {
969 voidsize = count - SCSI_ERRSTR_SIZE;
970 count = SCSI_ERRSTR_SIZE;
971 }
972 rscsireadbuf(scgp, fd, scgp->errstr, count);
973 rscsivoidarg(scgp, fd, voidsize);
974 }
975 if (scgp->debug > 0)
976 errmsgno(number, "Remote status(%s): %d '%s'.\n",
977 name, number, cbuf);
978 errno = number;
979 return (-1);
980 }
981 if (code != 'A') {
982 /* XXX Hier kommt evt Command not found ... */
983 if (scgp->debug > 0)
984 errmsgno(EX_BAD, "Protocol error (got %s).\n", cbuf);
985 return (rscsiaborted(scgp, fd));
986 }
987 return (number);
988 }
989
990 LOCAL int
rscsiaborted(scgp,fd)991 rscsiaborted(scgp, fd)
992 SCSI *scgp;
993 int fd;
994 {
995 if ((scgp && scgp->debug > 0) || debug)
996 errmsgno(EX_BAD, "Lost connection to remote host ??\n");
997 /* if fd >= 0 */
998 /* close file */
999 if (errno == 0)
1000 errno = EIO;
1001 return (-1);
1002 }
1003
1004 /*--------------------------------------------------------------------------*/
1005 #ifdef USE_RCMD_RSH
1006 /*
1007 * If we make a separate file for libschily, we would need these include files:
1008 *
1009 * socketpair(): sys/types.h + sys/socket.h
1010 * dup2(): unixstd.h (hat auch sys/types.h)
1011 * strrchr(): strdefs.h
1012 *
1013 * and make sure that we use sigset() instead of signal() if possible.
1014 */
1015 #include <waitdefs.h>
1016 LOCAL int
_rcmdrsh(ahost,inport,locuser,remuser,cmd,rsh)1017 _rcmdrsh(ahost, inport, locuser, remuser, cmd, rsh)
1018 char **ahost;
1019 int inport; /* port is ignored */
1020 const char *locuser;
1021 const char *remuser;
1022 const char *cmd;
1023 const char *rsh;
1024 {
1025 struct passwd *pw;
1026 int pp[2];
1027 int pid;
1028
1029 if (rsh == 0)
1030 rsh = "rsh";
1031
1032 /*
1033 * Verify that 'locuser' is present on local host.
1034 */
1035 if ((pw = getpwnam(locuser)) == NULL) {
1036 errmsgno(EX_BAD, "Unknown user: %s\n", locuser);
1037 return (-1);
1038 }
1039 /* XXX Check the existence for 'ahost' here? */
1040
1041 /*
1042 * rcmd(3) creates a single socket to be used for communication.
1043 * We need a bi-directional pipe to implement the same interface.
1044 * On newer OS that implement bi-directional we could use pipe(2)
1045 * but it makes no sense unless we find an OS that implements a
1046 * bi-directional pipe(2) but no socketpair().
1047 */
1048 if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pp) == -1) {
1049 errmsg("Cannot create socketpair.\n");
1050 return (-1);
1051 }
1052
1053 pid = fork();
1054 if (pid < 0) {
1055 return (-1);
1056 } else if (pid == 0) {
1057 const char *p;
1058 const char *av0;
1059 int xpid;
1060
1061 (void) close(pp[0]);
1062 if (dup2(pp[1], 0) == -1 || /* Pipe becomes 'stdin' */
1063 dup2(0, 1) == -1) { /* Pipe becomes 'stdout' */
1064
1065 errmsg("dup2 failed.\n");
1066 _exit(EX_BAD);
1067 /* NOTREACHED */
1068 }
1069 (void) close(pp[1]); /* We don't need this anymore*/
1070
1071 /*
1072 * Become 'locuser' to tell the rsh program the local user id.
1073 */
1074 if (getuid() != pw->pw_uid &&
1075 setuid(pw->pw_uid) == -1) {
1076 errmsg("setuid(%lld) failed.\n",
1077 (Llong)pw->pw_uid);
1078 _exit(EX_BAD);
1079 /* NOTREACHED */
1080 }
1081 if (getuid() != geteuid() &&
1082 seteuid(pw->pw_uid) == -1) {
1083 errmsg("seteuid(%lld) failed.\n",
1084 (Llong)pw->pw_uid);
1085 _exit(EX_BAD);
1086 /* NOTREACHED */
1087 }
1088
1089 /*
1090 * Fork again to completely detach from parent
1091 * and avoid the need to wait(2).
1092 */
1093 if ((xpid = fork()) == -1) {
1094 errmsg("rcmdsh: fork to lose parent failed.\n");
1095 _exit(EX_BAD);
1096 /* NOTREACHED */
1097 }
1098 if (xpid > 0) {
1099 _exit(0);
1100 /* NOTREACHED */
1101 }
1102
1103 /*
1104 * Always use remote shell programm (even for localhost).
1105 * The client command may call getpeername() for security
1106 * reasons and this would fail on a simple pipe.
1107 */
1108
1109
1110 /*
1111 * By default, 'rsh' handles terminal created signals
1112 * but this is not what we like.
1113 * For this reason, we tell 'rsh' to ignore these signals.
1114 * Ignoring these signals is important to allow 'star' / 'sdd'
1115 * to e.g. implement SIGQUIT as signal to trigger intermediate
1116 * status printing.
1117 *
1118 * For now (late 2002), we know that the following programs
1119 * are broken and do not implement signal handling correctly:
1120 *
1121 * rsh on SunOS-5.0...SunOS-5.9
1122 * ssh from ssh.com
1123 * ssh from openssh.org
1124 *
1125 * Sun already did accept a bug report for 'rsh'. For the ssh
1126 * commands we need to send out bug reports. Meanwhile it could
1127 * help to call setsid() if we are running under X so the ssh
1128 * X pop up for passwd reading will work.
1129 */
1130 signal(SIGINT, SIG_IGN);
1131 signal(SIGQUIT, SIG_IGN);
1132 #ifdef SIGTSTP
1133 signal(SIGTSTP, SIG_IGN); /* We would not be able to continue*/
1134 #endif
1135
1136 av0 = rsh;
1137 if ((p = strrchr(rsh, '/')) != NULL)
1138 av0 = ++p;
1139 execlp(rsh, av0, *ahost, "-l", remuser, cmd, (char *)NULL);
1140
1141 errmsg("execlp '%s' failed.\n", rsh);
1142 _exit(EX_BAD);
1143 /* NOTREACHED */
1144 } else {
1145 (void) close(pp[1]);
1146 /*
1147 * Wait for the intermediate child.
1148 * The real 'rsh' program is completely detached from us.
1149 */
1150 wait(0);
1151 return (pp[0]);
1152 }
1153 return (-1); /* keep gcc happy */
1154 }
1155 #endif /* USE_RCMD_RSH */
1156
1157 #endif /* USE_REMOTE */
1158