2 * This file has been modified for the cdrkit suite.
4 * The behaviour and appearence of the program code below can differ to a major
5 * extent from the version distributed by the original author(s).
7 * For details, see Changelog file distributed with the cdrkit package. If you
8 * received this file from another source then ask the distributing person for
9 * a log of modifications.
14 /* @(#)scsi-remote.c 1.18 06/01/12 Copyright 1990,2000-2003 J. Schilling */
16 * Remote SCSI user level command transport routines
18 * Warning: you may change this source, but if you do that
19 * you need to change the _usal_version and _usal_auth* string below.
20 * You may not return "schily" for an SCG_AUTHOR request anymore.
21 * Choose your name instead of "schily" and make clear that the version
22 * string is related to a modified source.
24 * Copyright (c) 1990,2000-2003 J. Schilling
27 * This program is free software; you can redistribute it and/or modify
28 * it under the terms of the GNU General Public License version 2
29 * as published by the Free Software Foundation.
31 * This program is distributed in the hope that it will be useful,
32 * but WITHOUT ANY WARRANTY; without even the implied warranty of
33 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
34 * GNU General Public License for more details.
36 * You should have received a copy of the GNU General Public License along with
37 * this program; see the file COPYING. If not, write to the Free Software
38 * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
43 #if !defined(HAVE_FORK) || !defined(HAVE_SOCKETPAIR) || !defined(HAVE_DUP2)
47 * We may work without getservbyname() if we restructure the code not to
48 * use the port number if we only use _rcmdrsh().
50 #if !defined(HAVE_GETSERVBYNAME)
51 #undef USE_REMOTE /* Cannot get rcmd() port # */
53 #if (!defined(HAVE_NETDB_H) || !defined(HAVE_RCMD)) && !defined(USE_RCMD_RSH)
54 #undef USE_REMOTE /* There is no rcmd() */
59 #include <sys/types.h>
61 #ifdef HAVE_SYS_SOCKET_H
62 #include <sys/socket.h>
78 #include <usal/usalcmd.h>
79 #include <usal/scsitransp.h>
81 #if defined(SIGDEFER) || defined(SVR4)
86 * On Cygwin, there are no privilleged ports.
87 * On UNIX, rcmd() uses privilleged port that only work for root.
90 #define privport_ok() (1)
93 #define privport_ok() ppriv_ok()
95 #define privport_ok() (geteuid() == 0)
101 #define MAX_SCG 16 /* Max # of SCSI controllers */
105 /*extern BOOL debug;*/
106 LOCAL BOOL debug = 1;
108 LOCAL char _usal_trans_version[] = "remote-1.18"; /* The version for remote SCSI */
109 LOCAL char _usal_auth_cdrkit[] = "cdrkit-team"; /* The author for this module */
111 LOCAL int usalo_rsend __PR((SCSI *usalp));
112 LOCAL char * usalo_rversion __PR((SCSI *usalp, int what));
113 LOCAL int usalo_rhelp __PR((SCSI *usalp, FILE *f));
114 LOCAL int usalo_ropen __PR((SCSI *usalp, char *device));
115 LOCAL int usalo_rclose __PR((SCSI *usalp));
116 LOCAL long usalo_rmaxdma __PR((SCSI *usalp, long amt));
117 LOCAL void * usalo_rgetbuf __PR((SCSI *usalp, long amt));
118 LOCAL void usalo_rfreebuf __PR((SCSI *usalp));
119 LOCAL BOOL usalo_rhavebus __PR((SCSI *usalp, int busno));
120 LOCAL int usalo_rfileno __PR((SCSI *usalp, int busno, int tgt, int tlun));
121 LOCAL int usalo_rinitiator_id __PR((SCSI *usalp));
122 LOCAL int usalo_risatapi __PR((SCSI *usalp));
123 LOCAL int usalo_rreset __PR((SCSI *usalp, int what));
126 * XXX We should rethink the fd parameter now that we introduced
127 * XXX the rscsirchar() function and most access of remfd is done
128 * XXX via usallocal(usalp)->remfd.
130 LOCAL void rscsiabrt __PR((int sig));
131 LOCAL int rscsigetconn __PR((SCSI *usalp, char *host));
132 LOCAL char *rscsiversion __PR((SCSI *usalp, int fd, int what));
133 LOCAL int rscsiopen __PR((SCSI *usalp, int fd, char *fname));
134 LOCAL int rscsiclose __PR((SCSI *usalp, int fd));
135 LOCAL int rscsimaxdma __PR((SCSI *usalp, int fd, long amt));
136 LOCAL int rscsigetbuf __PR((SCSI *usalp, int fd, long amt));
137 LOCAL int rscsifreebuf __PR((SCSI *usalp, int fd));
138 LOCAL int rscsihavebus __PR((SCSI *usalp, int fd, int bus));
139 LOCAL int rscsifileno __PR((SCSI *usalp, int fd, int busno, int tgt, int tlun));
140 LOCAL int rscsiinitiator_id __PR((SCSI *usalp, int fd));
141 LOCAL int rscsiisatapi __PR((SCSI *usalp, int fd));
142 LOCAL int rscsireset __PR((SCSI *usalp, int fd, int what));
143 LOCAL int rscsiscmd __PR((SCSI *usalp, int fd, struct usal_cmd *sp));
144 LOCAL int rscsifillrbuf __PR((SCSI *usalp));
145 LOCAL int rscsirchar __PR((SCSI *usalp, char *cp));
146 LOCAL int rscsireadbuf __PR((SCSI *usalp, int fd, char *buf, int count));
147 LOCAL void rscsivoidarg __PR((SCSI *usalp, int fd, int count));
148 LOCAL int rscsicmd __PR((SCSI *usalp, int fd, char *name, char *cbuf));
149 LOCAL void rscsisendcmd __PR((SCSI *usalp, int fd, char *name, char *cbuf));
150 LOCAL int rscsigetline __PR((SCSI *usalp, int fd, char *line, int count));
151 LOCAL int rscsireadnum __PR((SCSI *usalp, int fd));
152 LOCAL int rscsigetstatus __PR((SCSI *usalp, int fd, char *name));
153 LOCAL int rscsiaborted __PR((SCSI *usalp, int fd));
155 LOCAL int _rcmdrsh __PR((char **ahost, int inport,
161 LOCAL BOOL ppriv_ok __PR((void));
165 /*--------------------------------------------------------------------------*/
167 #define READBUF_SIZE 128
171 char readbuf[READBUF_SIZE];
183 #define usallocal(p) ((struct usal_local *)((p)->local))
185 usal_ops_t remote_ops = {
186 usalo_rsend, /* "S" end */
187 usalo_rversion, /* "V" ersion */
188 usalo_rhelp, /* help */
189 usalo_ropen, /* "O" pen */
190 usalo_rclose, /* "C" lose */
191 usalo_rmaxdma, /* "D" MA */
192 usalo_rgetbuf, /* "M" alloc */
193 usalo_rfreebuf, /* "F" free */
194 usalo_rhavebus, /* "B" us */
195 usalo_rfileno, /* "T" arget */
196 usalo_rinitiator_id, /* "I" nitiator */
197 usalo_risatapi, /* "A" tapi */
198 usalo_rreset, /* "R" eset */
202 * Return our ops ptr.
207 return (&remote_ops);
211 * Return version information for the low level SCSI transport code.
212 * This has been introduced to make it easier to trace down problems
216 usalo_rversion(usalp, what)
222 if (usalp->local == NULL)
225 f = usallocal(usalp)->remfd;
226 if (usalp != (SCSI *)0) {
230 return (_usal_trans_version);
232 * If you changed this source, you are not allowed to
233 * return "schily" for the SCG_AUTHOR request.
236 return (_usal_auth_cdrkit);
241 if (usallocal(usalp)->v_version == NULL)
242 usallocal(usalp)->v_version = rscsiversion(usalp, f, SCG_VERSION);
243 return (usallocal(usalp)->v_version);
245 * If you changed this source, you are not allowed to
246 * return "schily" for the SCG_AUTHOR request.
249 if (usallocal(usalp)->v_author == NULL)
250 usallocal(usalp)->v_author = rscsiversion(usalp, f, SCG_AUTHOR);
251 return (usallocal(usalp)->v_author);
253 if (usallocal(usalp)->v_sccs_id == NULL)
254 usallocal(usalp)->v_sccs_id = rscsiversion(usalp, f, SCG_SCCS_ID);
255 return (usallocal(usalp)->v_sccs_id);
262 usalo_rhelp(usalp, f)
266 __usal_help(f, "RSCSI", "Remote SCSI",
267 "REMOTE:", "rscsi@host:bus,target,lun", "REMOTE:rscsi@host:1,2,0", TRUE, FALSE);
272 usalo_ropen(usalp, device)
276 int busno = usal_scsibus(usalp);
277 int tgt = usal_target(usalp);
278 int tlun = usal_lun(usalp);
280 register int nopen = 0;
285 fprintf(stderr, "Warning: Using remote SCSI interface.\n");
287 if (busno >= MAX_SCG || tgt >= MAX_TGT || tlun >= MAX_LUN) {
290 snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
291 "Illegal value for busno, target or lun '%d,%d,%d'",
296 if (usalp->local == NULL) {
297 usalp->local = malloc(sizeof (struct usal_local));
298 if (usalp->local == NULL)
300 usallocal(usalp)->remfd = -1;
301 usallocal(usalp)->readbptr = usallocal(usalp)->readbuf;
302 usallocal(usalp)->readbcnt = 0;
303 usallocal(usalp)->isopen = FALSE;
304 usallocal(usalp)->rsize = 0;
305 usallocal(usalp)->wsize = 0;
306 usallocal(usalp)->v_version = NULL;
307 usallocal(usalp)->v_author = NULL;
308 usallocal(usalp)->v_sccs_id = NULL;
311 if (device == NULL || (strncmp(device, "REMOTE", 6) != 0) ||
312 (device = strchr(device, ':')) == NULL) {
314 snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
315 "Illegal remote device syntax");
320 * Save non user@host:device
322 snprintf(devname, sizeof (devname), "%s", device);
324 if ((p = strchr(devname, ':')) != NULL)
327 f = rscsigetconn(usalp, devname);
330 snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
331 "Cannot get connection to remote host");
334 usallocal(usalp)->remfd = f;
335 debug = usalp->debug;
336 if (rscsiopen(usalp, f, p) >= 0) {
338 usallocal(usalp)->isopen = TRUE;
350 if (usalp->local == NULL)
353 if (usallocal(usalp)->v_version != NULL) {
354 free(usallocal(usalp)->v_version);
355 usallocal(usalp)->v_version = NULL;
357 if (usallocal(usalp)->v_author != NULL) {
358 free(usallocal(usalp)->v_author);
359 usallocal(usalp)->v_author = NULL;
361 if (usallocal(usalp)->v_sccs_id != NULL) {
362 free(usallocal(usalp)->v_sccs_id);
363 usallocal(usalp)->v_sccs_id = NULL;
366 f = usallocal(usalp)->remfd;
367 if (f < 0 || !usallocal(usalp)->isopen)
369 ret = rscsiclose(usalp, f);
370 usallocal(usalp)->isopen = FALSE;
372 usallocal(usalp)->remfd = -1;
377 usalo_rmaxdma(usalp, amt)
381 if (usalp->local == NULL)
384 return (rscsimaxdma(usalp, usallocal(usalp)->remfd, amt));
388 usalo_rgetbuf(usalp, amt)
394 if (usalp->local == NULL)
397 ret = rscsigetbuf(usalp, usallocal(usalp)->remfd, amt);
402 usalp->bufbase = (void *)valloc((size_t)amt);
404 usalp->bufbase = (void *)malloc((size_t)amt);
406 if (usalp->bufbase == NULL) {
407 usalo_rfreebuf(usalp);
410 return (usalp->bufbase);
414 usalo_rfreebuf(usalp)
420 free(usalp->bufbase);
421 usalp->bufbase = NULL;
423 if (usalp->local == NULL)
426 f = usallocal(usalp)->remfd;
427 if (f < 0 || !usallocal(usalp)->isopen)
429 rscsifreebuf(usalp, f);
433 usalo_rhavebus(usalp, busno)
437 if (usalp->local == NULL || busno < 0 || busno >= MAX_SCG)
440 return (rscsihavebus(usalp, usallocal(usalp)->remfd, busno));
444 usalo_rfileno(usalp, busno, tgt, tlun)
452 if (usalp->local == NULL ||
453 busno < 0 || busno >= MAX_SCG ||
454 tgt < 0 || tgt >= MAX_TGT ||
455 tlun < 0 || tlun >= MAX_LUN)
458 f = usallocal(usalp)->remfd;
459 if (f < 0 || !usallocal(usalp)->isopen)
461 return (rscsifileno(usalp, f, busno, tgt, tlun));
465 usalo_rinitiator_id(usalp)
468 if (usalp->local == NULL)
471 return (rscsiinitiator_id(usalp, usallocal(usalp)->remfd));
475 usalo_risatapi(usalp)
478 if (usalp->local == NULL)
481 return (rscsiisatapi(usalp, usallocal(usalp)->remfd));
485 usalo_rreset(usalp, what)
489 if (usalp->local == NULL)
492 return (rscsireset(usalp, usallocal(usalp)->remfd, what));
499 struct usal_cmd *sp = usalp->scmd;
502 if (usalp->local == NULL)
506 sp->error = SCG_FATAL;
509 ret = rscsiscmd(usalp, usallocal(usalp)->remfd, usalp->scmd);
514 /*--------------------------------------------------------------------------*/
519 rscsiaborted((SCSI *)0, -1);
523 rscsigetconn(usalp, host)
527 static struct servent *sp = 0;
528 static struct passwd *pw = 0;
538 signal(SIGPIPE, rscsiabrt);
540 sp = getservbyname("shell", "tcp");
542 comerrno(EX_BAD, "shell/tcp: unknown service\n");
545 pw = getpwuid(getuid());
547 comerrno(EX_BAD, "who are you? No passwd entry found.\n");
551 if ((p = strchr(host, '@')) != NULL) {
554 if (d > sizeof (rscsiuser))
555 d = sizeof (rscsiuser);
556 snprintf(rscsiuser, sizeof (rscsiuser), "%.*s", (int)d, host);
562 if (usalp->debug > 0)
563 errmsgno(EX_BAD, "locuser: '%s' rscsiuser: '%s' host: '%s'\n",
564 pw->pw_name, name, host);
567 if ((rscsi = getenv("RSCSI")) == NULL)
568 rscsi = "/usr/sbin/netscsid";
572 if (!privport_ok() || rsh != NULL)
573 rscsisock = _rcmdrsh(&rscsipeer, (unsigned short)sp->s_port,
574 pw->pw_name, name, rscsi, rsh);
578 rscsisock = rcmd(&rscsipeer, (unsigned short)sp->s_port,
579 pw->pw_name, name, rscsi, 0);
581 rscsisock = _rcmdrsh(&rscsipeer, (unsigned short)sp->s_port,
582 pw->pw_name, name, rscsi, rsh);
589 rscsiversion(usalp, fd, what)
598 snprintf(cbuf, sizeof (cbuf), "V%d\n", what);
599 ret = rscsicmd(usalp, fd, "version", cbuf);
603 rscsireadbuf(usalp, fd, p, ret);
608 rscsiopen(usalp, fd, fname)
620 snprintf(cbuf, sizeof (cbuf), "O%s\n", fname?fname:"");
621 ret = rscsicmd(usalp, fd, "open", cbuf);
625 bus = rscsireadnum(usalp, fd);
626 chan = rscsireadnum(usalp, fd);
627 tgt = rscsireadnum(usalp, fd);
628 lun = rscsireadnum(usalp, fd);
630 usal_settarget(usalp, bus, tgt, lun);
635 rscsiclose(usalp, fd)
639 return (rscsicmd(usalp, fd, "close", "C\n"));
643 rscsimaxdma(usalp, fd, amt)
650 snprintf(cbuf, sizeof (cbuf), "D%ld\n", amt);
651 return (rscsicmd(usalp, fd, "maxdma", cbuf));
655 rscsigetbuf(usalp, fd, amt)
664 snprintf(cbuf, sizeof (cbuf), "M%ld\n", amt);
665 ret = rscsicmd(usalp, fd, "getbuf", cbuf);
669 size = ret + 1024; /* Add protocol overhead */
672 if (size > usallocal(usalp)->wsize) while (size > 512 &&
673 setsockopt(fd, SOL_SOCKET, SO_SNDBUF,
674 (char *)&size, sizeof (size)) < 0) {
677 if (size > usallocal(usalp)->wsize) {
678 usallocal(usalp)->wsize = size;
679 if (usalp->debug > 0)
680 errmsgno(EX_BAD, "sndsize: %d\n", size);
684 if (size > usallocal(usalp)->rsize) while (size > 512 &&
685 setsockopt(fd, SOL_SOCKET, SO_RCVBUF,
686 (char *)&size, sizeof (size)) < 0) {
689 if (size > usallocal(usalp)->rsize) {
690 usallocal(usalp)->rsize = size;
691 if (usalp->debug > 0)
692 errmsgno(EX_BAD, "rcvsize: %d\n", size);
699 rscsifreebuf(usalp, fd)
703 return (rscsicmd(usalp, fd, "freebuf", "F\n"));
707 rscsihavebus(usalp, fd, busno)
712 char cbuf[2*CMD_SIZE];
714 snprintf(cbuf, sizeof (cbuf), "B%d\n%d\n",
717 return (rscsicmd(usalp, fd, "havebus", cbuf));
721 rscsifileno(usalp, fd, busno, tgt, tlun)
728 char cbuf[3*CMD_SIZE];
730 snprintf(cbuf, sizeof (cbuf), "T%d\n%d\n%d\n%d\n",
735 return (rscsicmd(usalp, fd, "fileno", cbuf));
739 rscsiinitiator_id(usalp, fd)
743 return (rscsicmd(usalp, fd, "initiator id", "I\n"));
747 rscsiisatapi(usalp, fd)
751 return (rscsicmd(usalp, fd, "isatapi", "A\n"));
755 rscsireset(usalp, fd, what)
762 snprintf(cbuf, sizeof (cbuf), "R%d\n", what);
763 return (rscsicmd(usalp, fd, "reset", cbuf));
767 rscsiscmd(usalp, fd, sp)
777 ret = snprintf(cbuf, sizeof (cbuf), "S%d\n%d\n%d\n%d\n%d\n",
779 sp->cdb_len, sp->sense_len,
781 movebytes(sp->cdb.cmd_cdb, &cbuf[ret], sp->cdb_len);
784 if ((sp->flags & SCG_RECV_DATA) == 0 && sp->size > 0) {
786 if ((ret + amt) <= sizeof (cbuf)) {
787 movebytes(sp->addr, &cbuf[ret], amt);
793 if (_nixwrite(fd, cbuf, ret) != ret)
794 rscsiaborted(usalp, fd);
797 if (_nixwrite(fd, sp->addr, amt) != amt)
798 rscsiaborted(usalp, fd);
801 ret = rscsigetstatus(usalp, fd, "sendcmd");
805 sp->resid = sp->size - ret;
806 sp->error = rscsireadnum(usalp, fd);
807 sp->ux_errno = rscsireadnum(usalp, fd);
808 *(Uchar *)&sp->scb = rscsireadnum(usalp, fd);
809 sp->sense_count = rscsireadnum(usalp, fd);
811 if (sp->sense_count > SCG_MAX_SENSE) {
812 voidsize = sp->sense_count - SCG_MAX_SENSE;
813 sp->sense_count = SCG_MAX_SENSE;
815 if (sp->sense_count > 0) {
816 rscsireadbuf(usalp, fd, (char *)sp->u_sense.cmd_sense, sp->sense_count);
817 rscsivoidarg(usalp, fd, voidsize);
820 if ((sp->flags & SCG_RECV_DATA) != 0 && ret > 0)
821 rscsireadbuf(usalp, fd, sp->addr, ret);
830 usallocal(usalp)->readbptr = usallocal(usalp)->readbuf;
832 return (usallocal(usalp)->readbcnt =
833 _niread(usallocal(usalp)->remfd,
834 usallocal(usalp)->readbuf, READBUF_SIZE));
838 rscsirchar(usalp, cp)
842 if (--(usallocal(usalp)->readbcnt) < 0) {
843 if (rscsifillrbuf(usalp) <= 0)
844 return (usallocal(usalp)->readbcnt);
845 --(usallocal(usalp)->readbcnt);
847 *cp = *(usallocal(usalp)->readbptr)++;
852 rscsireadbuf(usalp, fd, buf, count)
858 register int n = count;
859 register int amt = 0;
862 if (usallocal(usalp)->readbcnt > 0) {
863 cnt = usallocal(usalp)->readbcnt;
866 movebytes(usallocal(usalp)->readbptr, buf, cnt);
867 usallocal(usalp)->readbptr += cnt;
868 usallocal(usalp)->readbcnt -= cnt;
872 if ((cnt = _niread(fd, &buf[amt], n - amt)) <= 0) {
873 return (rscsiaborted(usalp, fd));
881 rscsivoidarg(usalp, fd, n)
890 for (i = 0; i < n; i += amt) {
894 rscsireadbuf(usalp, fd, buf, amt);
899 rscsicmd(usalp, fd, name, cbuf)
905 rscsisendcmd(usalp, fd, name, cbuf);
906 return (rscsigetstatus(usalp, fd, name));
910 rscsisendcmd(usalp, fd, name, cbuf)
916 int buflen = strlen(cbuf);
919 if (_nixwrite(fd, cbuf, buflen) != buflen)
920 rscsiaborted(usalp, fd);
924 rscsigetline(usalp, fd, line, count)
932 for (cp = line; cp < &line[count]; cp++) {
933 if (rscsirchar(usalp, cp) != 1)
934 return (rscsiaborted(usalp, fd));
941 return (rscsiaborted(usalp, fd));
945 rscsireadnum(usalp, fd)
951 rscsigetline(usalp, fd, cbuf, sizeof (cbuf));
956 rscsigetstatus(usalp, fd, name)
967 rscsigetline(usalp, fd, cbuf, sizeof (cbuf));
969 number = atoi(&cbuf[1]);
971 if (code == 'E' || code == 'F') {
972 rscsigetline(usalp, fd, cbuf, sizeof (cbuf));
973 if (code == 'F') /* should close file ??? */
974 rscsiaborted(usalp, fd);
976 rscsigetline(usalp, fd, cbuf, sizeof (cbuf));
979 if (usalp->errstr == NULL) {
982 } else if (count > SCSI_ERRSTR_SIZE) {
983 voidsize = count - SCSI_ERRSTR_SIZE;
984 count = SCSI_ERRSTR_SIZE;
986 rscsireadbuf(usalp, fd, usalp->errstr, count);
987 rscsivoidarg(usalp, fd, voidsize);
989 if (usalp->debug > 0)
990 errmsgno(number, "Remote status(%s): %d '%s'.\n",
996 /* XXX Hier kommt evt Command not found ... */
997 if (usalp->debug > 0)
998 errmsgno(EX_BAD, "Protocol error (got %s).\n", cbuf);
999 return (rscsiaborted(usalp, fd));
1005 rscsiaborted(usalp, fd)
1009 if ((usalp && usalp->debug > 0) || debug)
1010 errmsgno(EX_BAD, "Lost connection to remote host ??\n");
1018 /*--------------------------------------------------------------------------*/
1021 * If we make a separate file for libschily, we would need these include files:
1023 * socketpair(): sys/types.h + sys/socket.h
1024 * dup2(): unixstd.h (hat auch sys/types.h)
1025 * strrchr(): strdefs.h
1027 * and make sure that we use sigset() instead of signal() if possible.
1029 #include <waitdefs.h>
1031 _rcmdrsh(ahost, inport, locuser, remuser, cmd, rsh)
1033 int inport; /* port is ignored */
1034 const char *locuser;
1035 const char *remuser;
1047 * Verify that 'locuser' is present on local host.
1049 if ((pw = getpwnam(locuser)) == NULL) {
1050 errmsgno(EX_BAD, "Unknown user: %s\n", locuser);
1053 /* XXX Check the existence for 'ahost' here? */
1056 * rcmd(3) creates a single socket to be used for communication.
1057 * We need a bi-directional pipe to implement the same interface.
1058 * On newer OS that implement bi-directional we could use pipe(2)
1059 * but it makes no sense unless we find an OS that implements a
1060 * bi-directional pipe(2) but no socketpair().
1062 if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pp) == -1) {
1063 errmsg("Cannot create socketpair.\n");
1070 } else if (pid == 0) {
1075 (void) close(pp[0]);
1076 if (dup2(pp[1], 0) == -1 || /* Pipe becomes 'stdin' */
1077 dup2(0, 1) == -1) { /* Pipe becomes 'stdout' */
1079 errmsg("dup2 failed.\n");
1083 (void) close(pp[1]); /* We don't need this anymore*/
1086 * Become 'locuser' to tell the rsh program the local user id.
1088 if (getuid() != pw->pw_uid &&
1089 setuid(pw->pw_uid) == -1) {
1090 errmsg("setuid(%lld) failed.\n",
1095 if (getuid() != geteuid() &&
1096 #ifdef HAVE_SETREUID
1097 setreuid(-1, pw->pw_uid) == -1) {
1100 seteuid(pw->pw_uid) == -1) {
1102 setuid(pw->pw_uid) == -1) {
1105 errmsg("seteuid(%lld) failed.\n",
1110 if (getuid() != geteuid() &&
1111 seteuid(pw->pw_uid) == -1) {
1112 errmsg("seteuid(%lld) failed.\n",
1119 * Fork again to completely detach from parent
1120 * and avoid the need to wait(2).
1122 if ((xpid = fork()) == -1) {
1123 errmsg("rcmdsh: fork to lose parent failed.\n");
1133 * Always use remote shell programm (even for localhost).
1134 * The client command may call getpeername() for security
1135 * reasons and this would fail on a simple pipe.
1140 * By default, 'rsh' handles terminal created signals
1141 * but this is not what we like.
1142 * For this reason, we tell 'rsh' to ignore these signals.
1143 * Ignoring these signals is important to allow 'star' / 'sdd'
1144 * to e.g. implement SIGQUIT as signal to trigger intermediate
1147 * For now (late 2002), we know that the following programs
1148 * are broken and do not implement signal handling correctly:
1150 * rsh on SunOS-5.0...SunOS-5.9
1152 * ssh from openssh.org
1154 * Sun already did accept a bug report for 'rsh'. For the ssh
1155 * commands we need to send out bug reports. Meanwhile it could
1156 * help to call setsid() if we are running under X so the ssh
1157 * X pop up for passwd reading will work.
1159 signal(SIGINT, SIG_IGN);
1160 signal(SIGQUIT, SIG_IGN);
1162 signal(SIGTSTP, SIG_IGN); /* We would not be able to continue*/
1166 if ((p = strrchr(rsh, '/')) != NULL)
1168 execlp(rsh, av0, *ahost, "-l", remuser, cmd, (char *)NULL);
1170 errmsg("execlp '%s' failed.\n", rsh);
1174 (void) close(pp[1]);
1176 * Wait for the intermediate child.
1177 * The real 'rsh' program is completely detached from us.
1182 return (-1); /* keep gcc happy */
1185 #ifdef HAVE_GETPPRIV
1191 priv_set_t *privset;
1192 BOOL net_privaddr = FALSE;
1195 if ((privset = priv_allocset()) == NULL) {
1198 if (getppriv(PRIV_EFFECTIVE, privset) == -1) {
1199 priv_freeset(privset);
1202 if (priv_ismember(privset, PRIV_NET_PRIVADDR)) {
1203 net_privaddr = TRUE;
1205 priv_freeset(privset);
1207 return (net_privaddr);
1209 #endif /* HAVE_GETPPRIV */
1211 #endif /* USE_RCMD_RSH */
1213 #endif /* USE_REMOTE */