]>
Dogcows Code - chaz/tar/blob - src/rmt.c
b0ec6f98c3f7a5fd2d91b62639d829081b066b3d
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. */
34 #include <sys/socket.h>
37 # define EXIT_FAILURE 1
40 # define EXIT_SUCCESS 0
43 /* Maximum size of a string from the requesting program. */
44 #define STRING_SIZE 64
46 /* Name of executing program. */
47 const char *program_name
;
49 /* File descriptor of the tape device, or negative if none open. */
52 /* Buffer containing transferred data, and its allocated size. */
53 static char *record_buffer
= NULL
;
54 static size_t allocated_size
= 0;
56 /* Buffer for constructing the reply. */
57 static char reply_buffer
[BUFSIZ
];
59 /* Debugging tools. */
61 static FILE *debug_file
= NULL
;
64 if (debug_file) fprintf(debug_file, File)
66 #define DEBUG1(File, Arg) \
67 if (debug_file) fprintf(debug_file, File, Arg)
69 #define DEBUG2(File, Arg1, Arg2) \
70 if (debug_file) fprintf(debug_file, File, Arg1, Arg2)
72 /*------------------------------------------------.
73 | Return an error string, given an error number. |
74 `------------------------------------------------*/
82 private_strerror (int errnum
)
84 extern char *sys_errlist
[];
87 if (errnum
> 0 && errnum
<= sys_nerr
)
88 return _(sys_errlist
[errnum
]);
89 return _("Unknown system error");
91 # define strerror private_strerror
99 report_error_message (const char *string
)
101 DEBUG1 ("rmtd: E 0 (%s)\n", string
);
103 sprintf (reply_buffer
, "E0\n%s\n", string
);
104 full_write (STDOUT_FILENO
, reply_buffer
, strlen (reply_buffer
));
112 report_numbered_error (int num
)
114 DEBUG2 ("rmtd: E %d (%s)\n", num
, strerror (num
));
116 sprintf (reply_buffer
, "E%d\n%s\n", num
, strerror (num
));
117 full_write (STDOUT_FILENO
, reply_buffer
, strlen (reply_buffer
));
125 get_string (char *string
)
129 for (counter
= 0; counter
< STRING_SIZE
; counter
++)
131 if (full_read (STDIN_FILENO
, string
+ counter
, 1) != 1)
134 if (string
[counter
] == '\n')
137 string
[counter
] = '\0';
145 prepare_record_buffer (size_t size
)
147 if (size
<= allocated_size
)
151 free (record_buffer
);
153 record_buffer
= malloc (size
);
155 if (record_buffer
== NULL
)
157 DEBUG (_("rmtd: Cannot allocate buffer space\n"));
159 report_error_message (N_("Cannot allocate buffer space"));
160 exit (EXIT_FAILURE
); /* exit status used to be 4 */
163 allocated_size
= size
;
166 while (size
> 1024 &&
167 (setsockopt (STDIN_FILENO
, SOL_SOCKET
, SO_RCVBUF
,
168 (char *) &size
, sizeof size
)
172 /* FIXME: I do not see any purpose to the following line... Sigh! */
173 size
= 1 + ((size
- 1) % 1024);
182 main (int argc
, char *const *argv
)
187 /* FIXME: Localisation is meaningless, unless --help and --version are
188 locally used. Localisation would be best accomplished by the calling
189 tar, on messages found within error packets. */
191 program_name
= argv
[0];
192 setlocale (LC_ALL
, "");
193 bindtextdomain (PACKAGE
, LOCALEDIR
);
194 textdomain (PACKAGE
);
196 /* FIXME: Implement --help and --version as for any other GNU program. */
201 debug_file
= fopen (*argv
, "w");
204 report_numbered_error (errno
);
207 setbuf (debug_file
, NULL
);
211 errno
= 0; /* FIXME: errno should be read-only */
213 if (full_read (STDIN_FILENO
, &command
, 1) != 1)
218 /* FIXME: Maybe 'H' and 'V' for --help and --version output? */
222 char device_string
[STRING_SIZE
];
223 char mode_string
[STRING_SIZE
];
225 get_string (device_string
);
226 get_string (mode_string
);
227 DEBUG2 ("rmtd: O %s %s\n", device_string
, mode_string
);
232 tape
= open (device_string
, atoi (mode_string
), 0666);
240 char device_string
[STRING_SIZE
];
242 get_string (device_string
); /* discard */
245 if (close (tape
) < 0)
253 char count_string
[STRING_SIZE
];
254 char position_string
[STRING_SIZE
];
260 get_string (count_string
);
261 get_string (position_string
);
262 DEBUG2 ("rmtd: L %s %s\n", count_string
, position_string
);
264 /* Parse count_string, taking care to check for overflow.
265 We can't use standard functions,
266 since off_t might be longer than long. */
268 for (p
= count_string
; *p
== ' ' || *p
== '\t'; p
++)
271 negative
= *p
== '-';
272 p
+= negative
|| *p
== '+';
276 int digit
= *p
++ - '0';
277 if (9 < (unsigned) digit
)
281 off_t c10
= 10 * count
;
282 off_t nc
= negative
? c10
- digit
: c10
+ digit
;
283 if (c10
/ 10 != count
|| (negative
? c10
< nc
: nc
< c10
))
285 report_error_message (N_("Seek offset out of range"));
292 switch (atoi (position_string
))
294 case 0: whence
= SEEK_SET
; break;
295 case 1: whence
= SEEK_CUR
; break;
296 case 2: whence
= SEEK_END
; break;
298 report_error_message (N_("Seek direction out of range"));
301 count
= lseek (tape
, count
, whence
);
305 /* Convert count back to string for reply.
306 We can't use sprintf, since off_t might be longer than long. */
307 p
= count_string
+ sizeof count_string
;
310 *--p
= '0' + (int) (count
% 10);
311 while ((count
/= 10) != 0);
313 DEBUG1 ("rmtd: A %s\n", p
);
315 sprintf (reply_buffer
, "A%s\n", p
);
316 full_write (STDOUT_FILENO
, reply_buffer
, strlen (reply_buffer
));
322 char count_string
[STRING_SIZE
];
326 get_string (count_string
);
327 size
= atol (count_string
);
328 DEBUG1 ("rmtd: W %s\n", count_string
);
330 prepare_record_buffer (size
);
331 for (counter
= 0; counter
< size
; counter
+= status
)
333 status
= full_read (STDIN_FILENO
, &record_buffer
[counter
],
337 DEBUG (_("rmtd: Premature eof\n"));
339 report_error_message (N_("Premature end of file"));
340 exit (EXIT_FAILURE
); /* exit status used to be 2 */
343 status
= full_write (tape
, record_buffer
, size
);
351 char count_string
[STRING_SIZE
];
354 get_string (count_string
);
355 DEBUG1 ("rmtd: R %s\n", count_string
);
357 size
= atol (count_string
);
358 prepare_record_buffer (size
);
359 status
= full_read (tape
, record_buffer
, size
);
362 sprintf (reply_buffer
, "A%ld\n", status
);
363 full_write (STDOUT_FILENO
, reply_buffer
, strlen (reply_buffer
));
364 full_write (STDOUT_FILENO
, record_buffer
, (size_t) status
);
370 char operation_string
[STRING_SIZE
];
371 char count_string
[STRING_SIZE
];
373 get_string (operation_string
);
374 get_string (count_string
);
375 DEBUG2 ("rmtd: I %s %s\n", operation_string
, count_string
);
384 /* Parse count_string, taking care to check for overflow.
385 We can't use standard functions,
386 since off_t might be longer than long. */
388 for (p
= count_string
; *p
== ' ' || *p
== '\t'; p
++)
391 negative
= *p
== '-';
392 p
+= negative
|| *p
== '+';
396 int digit
= *p
++ - '0';
397 if (9 < (unsigned) digit
)
401 off_t c10
= 10 * count
;
402 off_t nc
= negative
? c10
- digit
: c10
+ digit
;
403 if (c10
/ 10 != count
|| (negative
? c10
< nc
: nc
< c10
))
405 report_error_message (N_("Seek offset out of range"));
412 mtop
.mt_count
= count
;
413 if (mtop
.mt_count
!= count
)
415 report_error_message (N_("Seek offset out of range"));
418 mtop
.mt_op
= atoi (operation_string
);
420 if (ioctl (tape
, MTIOCTOP
, (char *) &mtop
) < 0)
427 case 'S': /* status */
433 struct mtget operation
;
435 if (ioctl (tape
, MTIOCGET
, (char *) &operation
) < 0)
437 status
= sizeof (operation
);
438 sprintf (reply_buffer
, "A%ld\n", status
);
439 full_write (STDOUT_FILENO
, reply_buffer
, strlen (reply_buffer
));
440 full_write (STDOUT_FILENO
, (char *) &operation
, sizeof (operation
));
447 DEBUG1 (_("rmtd: Garbage command %c\n"), command
);
449 report_error_message (N_("Garbage command"));
450 exit (EXIT_FAILURE
); /* exit status used to be 3 */
454 DEBUG1 ("rmtd: A %ld\n", status
);
456 sprintf (reply_buffer
, "A%ld\n", status
);
457 full_write (STDOUT_FILENO
, reply_buffer
, strlen (reply_buffer
));
461 report_numbered_error (errno
);
This page took 0.05108 seconds and 4 git commands to generate.