home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Geek Gadgets 1
/
ADE-1.bin
/
ade-dist
/
tar-1.11.8-src.tgz
/
tar.out
/
fsf
/
tar
/
src
/
rmt.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-09-28
|
7KB
|
322 lines
/* Remote connection server.
Copyright (C) 1994 Free Software Foundation, Inc.
This file is part of GNU tar.
GNU tar 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; either version 2, or (at your option)
any later version.
GNU tar is distributed in the hope that it will 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 GNU tar; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* Copyright (c) 1983 Regents of the University of California. All
rights reserved.
Redistribution and use in source and binary forms are permitted
provided that the above copyright notice and this paragraph are
duplicated in all such forms and that any documentation, advertising
materials, and other materials related to such distribution and use
acknowledge that the software was developed by the University of
California, Berkeley. The name of the University may not be used to
endorse or promote products derived from this software without
specific prior written permission. THIS SOFTWARE IS PROVIDED ``AS
IS'' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
A PARTICULAR PURPOSE. */
#include "system.h"
#ifndef lint
static char copyright[] =
"@(#) Copyright (c) 1983 Regents of the University of California.\n\
All rights reserved.\n";
#endif /* not lint */
#include <sgtty.h>
#include <sys/socket.h>
#ifndef EXIT_FAILURE
# define EXIT_FAILURE 1
#endif
#ifndef EXIT_SUCCESS
# define EXIT_SUCCESS 0
#endif
int tape = -1;
char *record = 0;
int maxrecsize = -1;
#define STRING_SIZE 64
char device[STRING_SIZE];
char count[STRING_SIZE], mode[STRING_SIZE], pos[STRING_SIZE], op[STRING_SIZE];
extern char *sys_errlist[];
char resp[BUFSIZ];
FILE *debug;
#define DEBUG(File) \
if (debug) fprintf(debug, File)
#define DEBUG1(File, Arg) \
if (debug) fprintf(debug, File, Arg)
#define DEBUG2(File, Arg1, Arg2) \
if (debug) fprintf(debug, File, Arg1, Arg2)
/*---.
| ? |
`---*/
static void
string_error (const char *string)
{
DEBUG1 ("rmtd: E 0 (%s)\n", string);
sprintf (resp, "E0\n%s\n", string);
write (1, resp, strlen (resp));
}
/*---.
| ? |
`---*/
static void
numeric_error (int num)
{
DEBUG2 ("rmtd: E %d (%s)\n", num, sys_errlist[num]);
sprintf (resp, "E%d\n%s\n", num, sys_errlist[num]);
write (1, resp, strlen (resp));
}
/*---.
| ? |
`---*/
static void
getstring (char *bp)
{
int i;
char *cp = bp;
for (i = 0; i < STRING_SIZE; i++)
{
if (read (0, cp + i, 1) != 1)
exit (EXIT_SUCCESS);
if (cp[i] == '\n')
break;
}
cp[i] = '\0';
}
/*---.
| ? |
`---*/
static void
checkbuf (int size)
{
if (size <= maxrecsize)
return;
if (record)
free (record);
record = malloc ((size_t) size);
if (record == 0)
{
DEBUG (_("rmtd: Cannot allocate buffer space\n"));
string_error (_("Cannot allocate buffer space"));
exit (EXIT_FAILURE); /* status used to be 4 */
}
maxrecsize = size;
#ifdef SO_RCVBUF
while (size > 1024 &&
setsockopt (0, SOL_SOCKET, SO_RCVBUF, (char *) &size, sizeof (size)) < 0)
size -= 1024;
#else
size = 1 + ((size - 1) % 1024);
#endif
}
/*---.
| ? |
`---*/
const char *program_name;
int
main (int argc, char *const *argv)
{
int rval;
char c;
int n, i, cc;
program_name = argv[0];
setlocale (LC_ALL, "");
argc--, argv++;
if (argc > 0)
{
debug = fopen (*argv, "w");
if (debug == 0)
{
numeric_error (errno);
exit (EXIT_FAILURE);
}
setbuf (debug, (char *) 0);
}
top:
errno = 0;
rval = 0;
if (read (0, &c, 1) != 1)
exit (EXIT_SUCCESS);
switch (c)
{
case 'O':
if (tape >= 0)
close (tape);
getstring (device);
getstring (mode);
DEBUG2 ("rmtd: O %s %s\n", device, mode);
#if defined (i386) && defined (AIX)
/* This is alleged to fix a byte ordering problem. I'm quite
suspicious if it's right. -- mib. */
{
int oflag = atoi (mode);
int nflag = 0;
if ((oflag & 3) == 0)
nflag |= O_RDONLY;
if (oflag & 1)
nflag |= O_WRONLY;
if (oflag & 2)
nflag |= O_RDWR;
if (oflag & 0x0008)
nflag |= O_APPEND;
if (oflag & 0x0200)
nflag |= O_CREAT;
if (oflag & 0x0400)
nflag |= O_TRUNC;
if (oflag & 0x0800)
nflag |= O_EXCL;
tape = open (device, nflag, 0666);
}
#else
tape = open (device, atoi (mode), 0666);
#endif
if (tape < 0)
goto ioerror;
goto respond;
case 'C':
DEBUG ("rmtd: C\n");
getstring (device); /* discard */
if (close (tape) < 0)
goto ioerror;
tape = -1;
goto respond;
case 'L':
getstring (count);
getstring (pos);
DEBUG2 ("rmtd: L %s %s\n", count, pos);
rval = lseek (tape, (off_t) atol (count), atoi (pos));
if (rval < 0)
goto ioerror;
goto respond;
case 'W':
getstring (count);
n = atoi (count);
DEBUG1 ("rmtd: W %s\n", count);
checkbuf (n);
for (i = 0; i < n; i += cc)
{
cc = read (0, &record[i], n - i);
if (cc <= 0)
{
DEBUG (_("rmtd: Premature eof\n"));
string_error (_("Premature end of file"));
exit (EXIT_FAILURE); /* status used to be 2 */
}
}
rval = write (tape, record, n);
if (rval < 0)
goto ioerror;
goto respond;
case 'R':
getstring (count);
DEBUG1 ("rmtd: R %s\n", count);
n = atoi (count);
checkbuf (n);
rval = read (tape, record, n);
if (rval < 0)
goto ioerror;
sprintf (resp, "A%d\n", rval);
write (1, resp, strlen (resp));
write (1, record, rval);
goto top;
case 'I':
getstring (op);
getstring (count);
DEBUG2 ("rmtd: I %s %s\n", op, count);
#ifdef MTIOCTOP
{
struct mtop mtop;
mtop.mt_op = atoi (op);
mtop.mt_count = atoi (count);
if (ioctl (tape, MTIOCTOP, (char *) &mtop) < 0)
goto ioerror;
rval = mtop.mt_count;
}
#endif
goto respond;
case 'S': /* status */
DEBUG ("rmtd: S\n");
{
#ifdef MTIOCGET
struct mtget mtget;
if (ioctl (tape, MTIOCGET, (char *) &mtget) < 0)
goto ioerror;
rval = sizeof (mtget);
sprintf (resp, "A%d\n", rval);
write (1, resp, strlen (resp));
write (1, (char *) &mtget, sizeof (mtget));
#endif
goto top;
}
default:
DEBUG1 (_("rmtd: Garbage command %c\n"), c);
string_error (_("Garbage command"));
exit (EXIT_FAILURE); /* status used to be 3 */
}
respond:
DEBUG1 ("rmtd: A %d\n", rval);
sprintf (resp, "A%d\n", rval);
write (1, resp, strlen (resp));
goto top;
ioerror:
numeric_error (errno);
goto top;
}