/*
* Copyright (c) 2000-2001 Silicon Graphics, Inc.; provided copyright in
* certain portions may be held by third parties as indicated herein.
* All Rights Reserved.
*
* The code in this source file represents an aggregation of work from
* Georgia Tech, Fred Fish, Jeff Lee, Arnold Robbins and other Silicon
* Graphics engineers over the period 1985-2000.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it would be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <unistd.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "config.h"
#include "rmtlib.h"
#define RMT_DEBUG_FILE "/tmp/librmt_debug" /* file for debug output on server */
static int _rmt_open(char *, int, int);
int _rmt_Ctp[MAXUNIT][2] = { {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1} };
int _rmt_Ptc[MAXUNIT][2] = { {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1} };
int _rmt_host[MAXUNIT] = { -1, -1, -1, -1};
struct uname_table
{
int id;
char *name;
};
struct uname_table uname_table[] =
{ {UNAME_LINUX, "Linux"}, {UNAME_IRIX, "IRIX"}, {0, 0} };
/*
* Open a local or remote file. Looks just like open(2) to
* caller.
*/
int rmtopen (path, oflag, mode)
char *path;
int oflag;
int mode;
{
if (strchr (path, ':') != NULL)
{
return (_rmt_open (path, oflag, mode) | REM_BIAS);
}
else
{
return (open (path, oflag, mode));
}
}
/*
* _rmt_open --- open a magtape device (or file) on system specified,
* as given user
*
* file name has the form system[.user]:????
*/
#define MAXHOSTLEN 257
#define MAXDBGPATH 100
/* ARGSUSED */
static int _rmt_open (char *path, int oflag, int mode)
{
int i, rc;
char buffer[BUFMAGIC];
char system[MAXHOSTLEN];
char device[BUFMAGIC];
char login[BUFMAGIC];
char *sys, *dev, *user;
char *rsh_path;
char *rmt_path;
char rmt_cmd[MAXDBGPATH];
sys = system;
dev = device;
user = login;
if ((rsh_path = getenv("RSH")) == NULL) {
rsh_path = RSH_PATH;
}
if ((rmt_path = getenv("RMT")) == NULL) {
rmt_path = RMT_PATH;
}
/*
* first, find an open pair of file descriptors
*/
for (i = 0; i < MAXUNIT; i++)
if (RMTREAD(i) == -1 && RMTWRITE(i) == -1)
break;
if (i == MAXUNIT)
{
setoserror(EMFILE);
return(-1);
}
/*
* pull apart system and device, and optional user
* don't munge original string
*/
while (*path != '@' && *path != ':') {
*user++ = *path++;
}
*user = '\0';
path++;
if (*(path - 1) == '@')
{
while (*path != ':') {
*sys++ = *path++;
}
*sys = '\0';
path++;
}
else
{
for (user = login; (*sys = *user); user++, sys++)
;
user = login;
}
while (*path) {
*dev++ = *path++;
}
*dev = '\0';
_rmt_turnonmsgsbyenv();
/* try to find out the uname of the remote host */
{
#define MAX_UNAMECMD MAXHOSTLEN+40
#define MAX_UNAME 20
FILE *rmt_f;
char cmd[MAX_UNAMECMD];
char uname[MAX_UNAME];
struct uname_table *p;
if (user != login) {
snprintf(cmd, sizeof(cmd), "%s -l %s %s uname", rsh_path, login, system);
}
else {
snprintf(cmd, sizeof(cmd), "%s %s uname", rsh_path, system);
}
rmt_f = popen(cmd, "r");
if (rmt_f == NULL) {
_rmt_msg(RMTWARN, _(
"rmtopen: failed to detect remote host type using \"%s\"\n"),
cmd);
RMTHOST(i) = UNAME_UNDEFINED;
goto do_rmt;
}
else {
int len;
char *c = fgets(uname, sizeof(uname), rmt_f);
pclose(rmt_f);
if (c == NULL) {
_rmt_msg(RMTWARN, _(
"rmtopen: failed to detect remote host type reading \"%s\"\n"),
cmd);
RMTHOST(i) = UNAME_UNDEFINED;
goto do_rmt;
}
len = strlen(uname);
if (len > 0 && uname[len-1] == '\n')
uname[len-1] = '\0'; /* chomp the '\n' */
}
for(p = &uname_table[0]; p->name != 0; p++) {
if (strncmp(p->name, uname, strlen(p->name)) == 0)
break;
}
if (p->name == 0) {
RMTHOST(i) = UNAME_UNKNOWN;
_rmt_msg(RMTWARN, _(
"rmtopen: remote host type, \"%s\", is unknown to librmt\n"),
uname);
}
else {
RMTHOST(i) = p->id;
_rmt_msg(RMTDBG, "rmtopen: RMTHOST(%d) = %s\n", i, p->name);
}
}
/*
* setup the pipes for the 'rsh' command and fork
*/
do_rmt:
if (pipe(_rmt_Ptc[i]) == -1 || pipe(_rmt_Ctp[i]) == -1)
return(-1);
if ((rc = fork()) == -1)
return(-1);
if (rc == 0)
{
close(0);
dup(_rmt_Ptc[i][0]);
close(_rmt_Ptc[i][0]); close(_rmt_Ptc[i][1]);
close(1);
dup(_rmt_Ctp[i][1]);
close(_rmt_Ctp[i][0]); close(_rmt_Ctp[i][1]);
(void) setuid (getuid ());
(void) setgid (getgid ());
if (_rmt_msgson() == RMTDBG) {
snprintf(rmt_cmd, sizeof(rmt_cmd), "%s %s.%d",
rmt_path, RMT_DEBUG_FILE, getpid());
}
else {
strncpy(rmt_cmd, rmt_path, sizeof(rmt_cmd));
}
if (user != login)
{
execl(rsh_path, "rsh", system, "-l", login,
rmt_cmd, (char *) 0);
}
else
{
execl(rsh_path, "rsh", system,
rmt_cmd, (char *) 0);
}
/*
* bad problems if we get here
*/
fprintf(stderr,
"librmt: problem finding either RSH(%s) or RMT(%s): %s\n",
rsh_path, rmt_path, strerror(errno));
exit(1);
}
close(_rmt_Ptc[i][0]); close(_rmt_Ctp[i][1]);
/*
* now attempt to open the tape device
*/
sprintf(buffer, "O%s\n%d\n", device, oflag);
if (_rmt_command(i, buffer) == -1 || _rmt_status(i) == -1)
return(-1);
return(i);
}