]>
Dogcows Code - chaz/tar/blob - src/rmt.c
1 /* Remote connection server.
2 Copyright 1994, 1995, 1996, 1997, 1999 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or modify it
5 under the terms of the GNU General Public License as published by the
6 Free Software Foundation; either version 2, or (at your option) any later
9 This program is distributed in the hope that it will be useful, but
10 WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
12 Public License for more details.
14 You should have received a copy of the GNU General Public License along
15 with this program; if not, write to the Free Software Foundation, Inc.,
16 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
18 /* Copyright (C) 1983 Regents of the University of California.
21 Redistribution and use in source and binary forms are permitted provided
22 that the above copyright notice and this paragraph are duplicated in all
23 such forms and that any documentation, advertising materials, and other
24 materials related to such distribution and use acknowledge that the
25 software was developed by the University of California, Berkeley. The
26 name of the University may not be used to endorse or promote products
27 derived from this software without specific prior written permission.
28 THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
29 WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
30 MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */
33 #include "safe-read.h"
35 #include <sys/socket.h>
38 # define EXIT_FAILURE 1
41 # define EXIT_SUCCESS 0
44 /* Maximum size of a string from the requesting program. */
45 #define STRING_SIZE 64
47 /* Name of executing program. */
48 const char *program_name
;
50 /* File descriptor of the tape device, or negative if none open. */
53 /* Buffer containing transferred data, and its allocated size. */
54 static char *record_buffer
= NULL
;
55 static size_t allocated_size
= 0;
57 /* Buffer for constructing the reply. */
58 static char reply_buffer
[BUFSIZ
];
60 /* Debugging tools. */
62 static FILE *debug_file
= NULL
;
65 if (debug_file) fprintf(debug_file, File)
67 #define DEBUG1(File, Arg) \
68 if (debug_file) fprintf(debug_file, File, Arg)
70 #define DEBUG2(File, Arg1, Arg2) \
71 if (debug_file) fprintf(debug_file, File, Arg1, Arg2)
73 /*------------------------------------------------.
74 | Return an error string, given an error number. |
75 `------------------------------------------------*/
83 private_strerror (int errnum
)
85 extern char *sys_errlist
[];
88 if (errnum
> 0 && errnum
<= sys_nerr
)
89 return _(sys_errlist
[errnum
]);
90 return _("Unknown system error");
92 # define strerror private_strerror
100 report_error_message (const char *string
)
102 DEBUG1 ("rmtd: E 0 (%s)\n", string
);
104 sprintf (reply_buffer
, "E0\n%s\n", string
);
105 full_write (STDOUT_FILENO
, reply_buffer
, strlen (reply_buffer
));
113 report_numbered_error (int num
)
115 DEBUG2 ("rmtd: E %d (%s)\n", num
, strerror (num
));
117 sprintf (reply_buffer
, "E%d\n%s\n", num
, strerror (num
));
118 full_write (STDOUT_FILENO
, reply_buffer
, strlen (reply_buffer
));
126 get_string (char *string
)
130 for (counter
= 0; counter
< STRING_SIZE
; counter
++)
132 if (safe_read (STDIN_FILENO
, string
+ counter
, 1) != 1)
135 if (string
[counter
] == '\n')
138 string
[counter
] = '\0';
146 prepare_record_buffer (size_t size
)
148 if (size
<= allocated_size
)
152 free (record_buffer
);
154 record_buffer
= malloc (size
);
156 if (record_buffer
== NULL
)
158 DEBUG (_("rmtd: Cannot allocate buffer space\n"));
160 report_error_message (N_("Cannot allocate buffer space"));
161 exit (EXIT_FAILURE
); /* exit status used to be 4 */
164 allocated_size
= size
;
167 while (size
> 1024 &&
168 (setsockopt (STDIN_FILENO
, SOL_SOCKET
, SO_RCVBUF
,
169 (char *) &size
, sizeof size
)
173 /* FIXME: I do not see any purpose to the following line... Sigh! */
174 size
= 1 + ((size
- 1) % 1024);
183 main (int argc
, char *const *argv
)
188 /* FIXME: Localisation is meaningless, unless --help and --version are
189 locally used. Localisation would be best accomplished by the calling
190 tar, on messages found within error packets. */
192 program_name
= argv
[0];
193 setlocale (LC_ALL
, "");
194 bindtextdomain (PACKAGE
, LOCALEDIR
);
195 textdomain (PACKAGE
);
197 /* FIXME: Implement --help and --version as for any other GNU program. */
202 debug_file
= fopen (*argv
, "w");
205 report_numbered_error (errno
);
208 setbuf (debug_file
, NULL
);
212 errno
= 0; /* FIXME: errno should be read-only */
214 if (safe_read (STDIN_FILENO
, &command
, 1) != 1)
219 /* FIXME: Maybe 'H' and 'V' for --help and --version output? */
223 char device_string
[STRING_SIZE
];
224 char mode_string
[STRING_SIZE
];
226 get_string (device_string
);
227 get_string (mode_string
);
228 DEBUG2 ("rmtd: O %s %s\n", device_string
, mode_string
);
233 tape
= open (device_string
, atoi (mode_string
), 0666);
241 char device_string
[STRING_SIZE
];
243 get_string (device_string
); /* discard */
246 if (close (tape
) < 0)
254 char count_string
[STRING_SIZE
];
255 char position_string
[STRING_SIZE
];
261 get_string (count_string
);
262 get_string (position_string
);
263 DEBUG2 ("rmtd: L %s %s\n", count_string
, position_string
);
265 /* Parse count_string, taking care to check for overflow.
266 We can't use standard functions,
267 since off_t might be longer than long. */
269 for (p
= count_string
; *p
== ' ' || *p
== '\t'; p
++)
272 negative
= *p
== '-';
273 p
+= negative
|| *p
== '+';
277 int digit
= *p
++ - '0';
278 if (9 < (unsigned) digit
)
282 off_t c10
= 10 * count
;
283 off_t nc
= negative
? c10
- digit
: c10
+ digit
;
284 if (c10
/ 10 != count
|| (negative
? c10
< nc
: nc
< c10
))
286 report_error_message (N_("Seek offset out of range"));
293 switch (atoi (position_string
))
295 case 0: whence
= SEEK_SET
; break;
296 case 1: whence
= SEEK_CUR
; break;
297 case 2: whence
= SEEK_END
; break;
299 report_error_message (N_("Seek direction out of range"));
302 count
= lseek (tape
, count
, whence
);
306 /* Convert count back to string for reply.
307 We can't use sprintf, since off_t might be longer than long. */
308 p
= count_string
+ sizeof count_string
;
311 *--p
= '0' + (int) (count
% 10);
312 while ((count
/= 10) != 0);
314 DEBUG1 ("rmtd: A %s\n", p
);
316 sprintf (reply_buffer
, "A%s\n", p
);
317 full_write (STDOUT_FILENO
, reply_buffer
, strlen (reply_buffer
));
323 char count_string
[STRING_SIZE
];
327 get_string (count_string
);
328 size
= atol (count_string
);
329 DEBUG1 ("rmtd: W %s\n", count_string
);
331 prepare_record_buffer (size
);
332 for (counter
= 0; counter
< size
; counter
+= status
)
334 status
= safe_read (STDIN_FILENO
, &record_buffer
[counter
],
338 DEBUG (_("rmtd: Premature eof\n"));
340 report_error_message (N_("Premature end of file"));
341 exit (EXIT_FAILURE
); /* exit status used to be 2 */
344 status
= full_write (tape
, record_buffer
, size
);
352 char count_string
[STRING_SIZE
];
355 get_string (count_string
);
356 DEBUG1 ("rmtd: R %s\n", count_string
);
358 size
= atol (count_string
);
359 prepare_record_buffer (size
);
360 status
= safe_read (tape
, record_buffer
, size
);
363 sprintf (reply_buffer
, "A%ld\n", status
);
364 full_write (STDOUT_FILENO
, reply_buffer
, strlen (reply_buffer
));
365 full_write (STDOUT_FILENO
, record_buffer
, (size_t) status
);
371 char operation_string
[STRING_SIZE
];
372 char count_string
[STRING_SIZE
];
374 get_string (operation_string
);
375 get_string (count_string
);
376 DEBUG2 ("rmtd: I %s %s\n", operation_string
, count_string
);
385 /* Parse count_string, taking care to check for overflow.
386 We can't use standard functions,
387 since off_t might be longer than long. */
389 for (p
= count_string
; *p
== ' ' || *p
== '\t'; p
++)
392 negative
= *p
== '-';
393 p
+= negative
|| *p
== '+';
397 int digit
= *p
++ - '0';
398 if (9 < (unsigned) digit
)
402 off_t c10
= 10 * count
;
403 off_t nc
= negative
? c10
- digit
: c10
+ digit
;
404 if (c10
/ 10 != count
|| (negative
? c10
< nc
: nc
< c10
))
406 report_error_message (N_("Seek offset out of range"));
413 mtop
.mt_count
= count
;
414 if (mtop
.mt_count
!= count
)
416 report_error_message (N_("Seek offset out of range"));
419 mtop
.mt_op
= atoi (operation_string
);
421 if (ioctl (tape
, MTIOCTOP
, (char *) &mtop
) < 0)
428 case 'S': /* status */
434 struct mtget operation
;
436 if (ioctl (tape
, MTIOCGET
, (char *) &operation
) < 0)
438 status
= sizeof (operation
);
439 sprintf (reply_buffer
, "A%ld\n", status
);
440 full_write (STDOUT_FILENO
, reply_buffer
, strlen (reply_buffer
));
441 full_write (STDOUT_FILENO
, (char *) &operation
, sizeof (operation
));
448 DEBUG1 (_("rmtd: Garbage command %c\n"), command
);
450 report_error_message (N_("Garbage command"));
451 exit (EXIT_FAILURE
); /* exit status used to be 3 */
455 DEBUG1 ("rmtd: A %ld\n", status
);
457 sprintf (reply_buffer
, "A%ld\n", status
);
458 full_write (STDOUT_FILENO
, reply_buffer
, strlen (reply_buffer
));
462 report_numbered_error (errno
);
This page took 0.052733 seconds and 4 git commands to generate.