]>
Dogcows Code - chaz/tar/blob - src/rmt.c
1 /* Remote connection server.
2 Copyright (C) 1994, 1995, 1996 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 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 const char *const sys_errlist
[];
87 if (errnum
> 0 && errnum
<= sys_nerr
)
88 return sys_errlist
[errnum
];
89 return N_("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 write (1, 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 write (1, reply_buffer
, strlen (reply_buffer
));
125 get_string (char *string
)
129 for (counter
= 0; counter
< STRING_SIZE
; counter
++)
131 if (read (0, 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 (0, SOL_SOCKET
, SO_RCVBUF
, (char *) &size
, sizeof (size
)) < 0)
170 /* FIXME: I do not see any purpose to the following line... Sigh! */
171 size
= 1 + ((size
- 1) % 1024);
180 main (int argc
, char *const *argv
)
185 /* FIXME: Localisation is meaningless, unless --help and --version are
186 locally used. Localisation would be best accomplished by the calling
187 tar, on messages found within error packets. */
189 program_name
= argv
[0];
190 setlocale (LC_ALL
, "");
191 bindtextdomain (PACKAGE
, LOCALEDIR
);
192 textdomain (PACKAGE
);
194 /* FIXME: Implement --help and --version as for any other GNU program. */
199 debug_file
= fopen (*argv
, "w");
202 report_numbered_error (errno
);
205 setbuf (debug_file
, NULL
);
209 errno
= 0; /* FIXME: errno should be read-only */
211 if (read (0, &command
, 1) != 1)
216 /* FIXME: Maybe 'H' and 'V' for --help and --version output? */
220 char device_string
[STRING_SIZE
];
221 char mode_string
[STRING_SIZE
];
223 get_string (device_string
);
224 get_string (mode_string
);
225 DEBUG2 ("rmtd: O %s %s\n", device_string
, mode_string
);
230 #if defined (i386) && defined (AIX)
232 /* This is alleged to fix a byte ordering problem. I'm quite
233 suspicious if it's right. -- mib. */
236 mode_t old_mode
= atol (mode_string
);
239 if ((old_mode
& 3) == 0)
240 new_mode
|= O_RDONLY
;
242 new_mode
|= O_WRONLY
;
245 if (old_mode
& 0x0008)
246 new_mode
|= O_APPEND
;
247 if (old_mode
& 0x0200)
249 if (old_mode
& 0x0400)
251 if (old_mode
& 0x0800)
253 tape
= open (device_string
, new_mode
, 0666);
256 tape
= open (device_string
, atoi (mode_string
), 0666);
265 char device_string
[STRING_SIZE
];
267 get_string (device_string
); /* discard */
270 if (close (tape
) < 0)
278 char count_string
[STRING_SIZE
];
279 char position_string
[STRING_SIZE
];
284 get_string (count_string
);
285 get_string (position_string
);
286 DEBUG2 ("rmtd: L %s %s\n", count_string
, position_string
);
288 /* Parse count_string, taking care to check for overflow.
289 We can't use standard functions,
290 since off_t might be longer than long. */
292 for (p
= count_string
; *p
== ' ' || *p
== '\t'; p
++)
295 negative
= *p
== '-';
296 p
+= negative
|| *p
== '+';
300 int digit
= *p
++ - '0';
301 if (9 < (unsigned) digit
)
305 off_t c10
= 10 * count
;
306 off_t nc
= negative
? c10
- digit
: c10
+ digit
;
307 if (c10
/ 10 != count
|| (negative
? c10
< nc
: nc
< c10
))
309 report_error_message (N_("Seek offset out of range"));
316 count
= lseek (tape
, count
, atoi (position_string
));
320 /* Convert count back to string for reply.
321 We can't use sprintf, since off_t might be longer than long. */
322 p
= count_string
+ sizeof count_string
;
325 *--p
= '0' + (int) (count
% 10);
326 while ((count
/= 10) != 0);
328 DEBUG1 ("rmtd: A %s\n", p
);
330 sprintf (reply_buffer
, "A%s\n", p
);
331 write (1, reply_buffer
, strlen (reply_buffer
));
337 char count_string
[STRING_SIZE
];
341 get_string (count_string
);
342 size
= atol (count_string
);
343 DEBUG1 ("rmtd: W %s\n", count_string
);
345 prepare_record_buffer (size
);
346 for (counter
= 0; counter
< size
; counter
+= status
)
348 status
= read (0, &record_buffer
[counter
], size
- counter
);
351 DEBUG (_("rmtd: Premature eof\n"));
353 report_error_message (N_("Premature end of file"));
354 exit (EXIT_FAILURE
); /* exit status used to be 2 */
357 status
= write (tape
, record_buffer
, size
);
365 char count_string
[STRING_SIZE
];
368 get_string (count_string
);
369 DEBUG1 ("rmtd: R %s\n", count_string
);
371 size
= atol (count_string
);
372 prepare_record_buffer (size
);
373 status
= read (tape
, record_buffer
, size
);
376 sprintf (reply_buffer
, "A%ld\n", status
);
377 write (1, reply_buffer
, strlen (reply_buffer
));
378 write (1, record_buffer
, (size_t) status
);
384 char operation_string
[STRING_SIZE
];
385 char count_string
[STRING_SIZE
];
387 get_string (operation_string
);
388 get_string (count_string
);
389 DEBUG2 ("rmtd: I %s %s\n", operation_string
, count_string
);
398 /* Parse count_string, taking care to check for overflow.
399 We can't use standard functions,
400 since off_t might be longer than long. */
402 for (p
= count_string
; *p
== ' ' || *p
== '\t'; p
++)
405 negative
= *p
== '-';
406 p
+= negative
|| *p
== '+';
410 int digit
= *p
++ - '0';
411 if (9 < (unsigned) digit
)
415 off_t c10
= 10 * count
;
416 off_t nc
= negative
? c10
- digit
: c10
+ digit
;
417 if (c10
/ 10 != count
|| (negative
? c10
< nc
: nc
< c10
))
419 report_error_message (N_("Seek offset out of range"));
426 mtop
.mt_count
= count
;
427 if (mtop
.mt_count
!= count
)
429 report_error_message (N_("Seek offset out of range"));
432 mtop
.mt_op
= atoi (operation_string
);
434 if (ioctl (tape
, MTIOCTOP
, (char *) &mtop
) < 0)
441 case 'S': /* status */
447 struct mtget operation
;
449 if (ioctl (tape
, MTIOCGET
, (char *) &operation
) < 0)
451 status
= sizeof (operation
);
452 sprintf (reply_buffer
, "A%ld\n", status
);
453 write (1, reply_buffer
, strlen (reply_buffer
));
454 write (1, (char *) &operation
, sizeof (operation
));
461 DEBUG1 (_("rmtd: Garbage command %c\n"), command
);
463 report_error_message (N_("Garbage command"));
464 exit (EXIT_FAILURE
); /* exit status used to be 3 */
468 DEBUG1 ("rmtd: A %ld\n", status
);
470 sprintf (reply_buffer
, "A%ld\n", status
);
471 write (1, reply_buffer
, strlen (reply_buffer
));
475 report_numbered_error (errno
);
This page took 0.057046 seconds and 5 git commands to generate.