/* Functions for communicating with a remote tape drive.
- Copyright (C) 1988, 1992, 1994, 1996 Free Software Foundation, Inc.
+ Copyright 1988, 1992, 1994, 1996, 1997, 1999 Free Software Foundation, Inc.
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
#include "system.h"
+#include "basename.h"
+#include "safe-read.h"
+
/* Try hard to get EOPNOTSUPP defined. 486/ISC has it in net/errno.h,
3B2/SVR3 has it in sys/inet.h. Otherwise, like on MSDOS, use EINVAL. */
close (WRITE_SIDE (handle));
READ_SIDE (handle) = -1;
WRITE_SIDE (handle) = -1;
- errno = errno_value; /* FIXME: errno should be read-only */
+ errno = errno_value;
}
/*-------------------------------------------------------------------------.
if (*cursor == 'E' || *cursor == 'F')
{
- errno = atoi (cursor + 1); /* FIXME: errno should be read-only */
+ errno = atoi (cursor + 1);
/* Skip the error message line. */
/*-------------------------------------------------------------------------.
| Execute /etc/rmt as user USER on remote system HOST using rexec. Return |
| a file descriptor of a bidirectional socket for stdin and stdout. If |
-| USER is NULL, use the current username. |
+| USER is zero, use the current username. |
| |
| By default, this code is not used, since it requires that the user have |
| a .netrc file in his/her home directory, or that the application |
/dev/tty before the rexec and give them back their original value
after. */
- if (freopen ("/dev/tty", "r", stdin) == NULL)
+ if (! freopen ("/dev/tty", "r", stdin))
freopen ("/dev/null", "r", stdin);
- if (freopen ("/dev/tty", "w", stdout) == NULL)
+ if (! freopen ("/dev/tty", "w", stdout))
freopen ("/dev/null", "w", stdout);
if (rexecserv = getservbyname ("exec", "tcp"), !rexecserv)
error (EXIT_ON_EXEC_ERROR, 0, _("exec/tcp: Service not available"));
- result = rexec (&host, rexecserv->s_port, user, NULL,
- "/etc/rmt", (int *) NULL);
+ result = rexec (&host, rexecserv->s_port, user, 0, "/etc/rmt", 0);
if (fclose (stdin) == EOF)
error (0, errno, _("stdin"));
fdopen (saved_stdin, "r");
#endif /* WITH_REXEC */
+/* Place into BUF a string representing OFLAG, which must be suitable
+ as argument 2 of `open'. BUF must be large enough to hold the
+ result. This function should generate a string that decode_oflag
+ can parse. */
+static void
+encode_oflag (char *buf, int oflag)
+{
+ sprintf (buf, "%d ", oflag);
+
+ switch (oflag & O_ACCMODE)
+ {
+ case O_RDONLY: strcat (buf, "O_RDONLY"); break;
+ case O_RDWR: strcat (buf, "O_RDWR"); break;
+ case O_WRONLY: strcat (buf, "O_WRONLY"); break;
+ default: abort ();
+ }
+
+#ifdef O_APPEND
+ if (oflag & O_APPEND) strcat (buf, "|O_APPEND");
+#endif
+ if (oflag & O_CREAT) strcat (buf, "|O_CREAT");
+#ifdef O_DSYNC
+ if (oflag & O_DSYNC) strcat (buf, "|O_DSYNC");
+#endif
+ if (oflag & O_EXCL) strcat (buf, "|O_EXCL");
+#ifdef O_LARGEFILE
+ if (oflag & O_LARGEFILE) strcat (buf, "|O_LARGEFILE");
+#endif
+#ifdef O_NOCTTY
+ if (oflag & O_NOCTTY) strcat (buf, "|O_NOCTTY");
+#endif
+#ifdef O_NONBLOCK
+ if (oflag & O_NONBLOCK) strcat (buf, "|O_NONBLOCK");
+#endif
+#ifdef O_RSYNC
+ if (oflag & O_RSYNC) strcat (buf, "|O_RSYNC");
+#endif
+#ifdef O_SYNC
+ if (oflag & O_SYNC) strcat (buf, "|O_SYNC");
+#endif
+ if (oflag & O_TRUNC) strcat (buf, "|O_TRUNC");
+}
+
/*------------------------------------------------------------------------.
| Open a file (a magnetic tape device?) on the system specified in PATH, |
| as the given user. PATH has the form `[USER@]HOST:FILE'. OPEN_MODE is |
| O_RDONLY, O_WRONLY, etc. If successful, return the remote pipe number |
-| plus BIAS. REMOTE_SHELL may be overriden. On error, return -1. |
+| plus BIAS. REMOTE_SHELL may be overridden. On error, return -1. |
`------------------------------------------------------------------------*/
int
if (remote_pipe_number == MAXUNIT)
{
- errno = EMFILE; /* FIXME: errno should be read-only */
+ errno = EMFILE;
return -1;
}
path_copy = xstrdup (path);
remote_host = path_copy;
- remote_user = NULL;
- remote_file = NULL;
+ remote_user = 0;
+ remote_file = 0;
for (cursor = path_copy; *cursor; cursor++)
switch (*cursor)
default:
break;
+ case '\n':
+ /* Do not allow newlines in the path, since the protocol
+ uses newline delimiters. */
+ free (path_copy);
+ errno = ENOENT;
+ return -1;
+
case '@':
if (!remote_user)
{
/* FIXME: Should somewhat validate the decoding, here. */
if (remote_user && *remote_user == '\0')
- remote_user = NULL;
+ remote_user = 0;
#if WITH_REXEC
READ_SIDE (remote_pipe_number) = _rmt_rexec (remote_host, remote_user);
if (READ_SIDE (remote_pipe_number) < 0)
{
+ int e = errno;
free (path_copy);
+ errno = e;
return -1;
}
#ifdef REMOTE_SHELL
remote_shell = REMOTE_SHELL;
#else
- errno = EIO; /* FIXME: errno should be read-only */
free (path_copy);
+ errno = EIO;
return -1;
#endif
}
- remote_shell_basename = strrchr (remote_shell, '/');
- if (remote_shell_basename)
- remote_shell_basename++;
- else
- remote_shell_basename = remote_shell;
+ remote_shell_basename = base_name (remote_shell);
/* Set up the pipes for the `rsh' command, and fork. */
if (pipe (to_remote[remote_pipe_number]) == -1
|| pipe (from_remote[remote_pipe_number]) == -1)
{
+ int e = errno;
free (path_copy);
+ errno = e;
return -1;
}
status = fork ();
if (status == -1)
{
+ int e = errno;
free (path_copy);
+ errno = e;
return -1;
}
/* Attempt to open the tape device. */
{
- char command_buffer[COMMAND_BUFFER_SIZE];
-
- sprintf (command_buffer, "O%s\n%d\n", remote_file, open_mode);
+ size_t remote_file_len = strlen (remote_file);
+ char *command_buffer = xmalloc (remote_file_len + 1000);
+ sprintf (command_buffer, "O%s\n", remote_file);
+ encode_oflag (command_buffer + remote_file_len + 2, open_mode);
+ strcat (command_buffer, "\n");
if (do_command (remote_pipe_number, command_buffer) == -1
|| get_status (remote_pipe_number) == -1)
{
- _rmt_shutdown (remote_pipe_number, errno);
+ int e = errno;
+ free (command_buffer);
free (path_copy);
+ _rmt_shutdown (remote_pipe_number, e);
return -1;
}
+ free (command_buffer);
}
free (path_copy);
switch (operation)
{
default:
- errno = EOPNOTSUPP; /* FIXME: errno should be read-only */
+ errno = EOPNOTSUPP;
return -1;
#ifdef MTIOCTOP
if (((struct mtop *) argument)->mt_count < 0)
*--p = '-';
- /* MTIOCTOP is the easy one. Nothing is transfered in binary. */
+ /* MTIOCTOP is the easy one. Nothing is transferred in binary. */
sprintf (command_buffer, "I%d\n%s\n",
((struct mtop *) argument)->mt_op, p);
for (; status > 0; status -= counter, argument += counter)
{
- counter = safe_read (READ_SIDE (handle),
- argument, (size_t) status);
+ counter = safe_read (READ_SIDE (handle), argument, status);
if (counter <= 0)
{
_rmt_shutdown (handle, EIO);