1 /*file: bpl.c
2 * (c) 1989, Phinloda and SHU (FMR version)
3 *
4 * PC98, 286, J3100, FMR version
5 * Borland C++ v2.0 (Borland JAPAN)
6 * or, J3100 version
7 * Tucbo-C++ v1.0 (Borland)
8 * SunOS v4.0.3
9 * gcc v1.37.1 (FSF)
10 *
11 * 890911 v1
12 * 890912 v2 option v, t, h
13 * 890913 v3 bug fix
14 * 890915 v4 send ACK for all packet / reenter filename
15 * 890915 v5 re-enter when downloading
16 * 890916 v6 DEBUG mode modification
17 * 890916 v7 support 300, 1200 bps
18 * 890918 v8 exit when 1st B session end
19 * 890918 v9 restore messages to Japanese
20 * 890918 v10 rename b.c from bp.c
21 * 890930 v11 remove bplus.c
22 * 891001 v12 fix v11 bugs
23 * 891005 v13 fix v12 bugs, rename to bpl.exe
24 * 891007 v14 time estimate
25 * 891009 v15 estimate
26 * 891014 v16 TI packet
27 * 891014 v17 my_bplus_entry changed
28 * 900225 v18 -a, d, e options
29 * 900303 v19 -a debug, adjust file name if it is invalid
30 * 900303 v20 change -h message
31 * 900303 v21 BPL= environment bug, -d bug
32 * 900305 v22 -d bug
33 * 900306 v23 -t bug, change bytes, time message
34 * 900430 v24 -a, upload
35 * 900512 v25
36 * 900516 v26 -o Flying-B+ :-)
37 * 900520 v27 full rewriting
38 * 900525 v28 + packet bug, some messages
39 * 900526 v29 time estimation bug
40 * 900606 v30 -p option (FMR)
41 * 900607 v31 -p option (J3100)
42 * 900608 v32 -1, -3 bug
43 * 900609 v33 FMR rsraw setup
44 * 900610 v34 -i option
45 * 900623 v35 FMR debug
46 * 900628 v36 Failue packet bug
47 * 900817 v36a �@��ˑ������� (M.Aza)
48 * 900907 v37 test version (UNIX only)
49 * 901105 v38 copy_body() bug fix
50 * 901127 v39 check over-run
51 * 901229 v40 dubug!, change the method of packet allocation
52 * 901230 v41 numeric optoin, change _stklen
53 * 910103 v42 file size message
54 * 910105 v43 English version
55 * 910115 v44 initiator mode, resume upload
56 * 910122 v45 time stump, stopchar
57 * 910127 v46 pc98, RTS flow control
58 * 910129 v47 debug,
59 * 910215 v48 upload retry bug
60 * 911209 v49 resume download bug
61 * 920714 v50 resume downlodo bug
62 * 920823 v51 compiled with ..
63 * 921212 v52 -j option
64 */
65
66
67 #include <stdio.h>
68 #include <stdlib.h> /* malloc */
69 #include <string.h> /* strlen */
70
71 #include "bpl.h"
72 #include "machine.h"
73
74 #define MYBUFSIZE 4096
75 #define MYDIRSIZE 256
76
77 #define bps300 1
78 #define bps1200 4
79 #define bps2400 8
80
81 #ifdef __TURBOC__
82 extern unsigned _stklen = 10000; /* default is 4096 */
83 static char borlandc_copyright_notice[] =
84 "Compiled with Borland C++\n"
85 "(Borland C++ Version 2.0 Copyright (c) 1991 Borland International)\n";
86 #endif
87
88 extern int com_send(unsigned char ch);
89 extern int com_setup(char *s, unsigned int size);
90 extern int execute_bpl_session(APPL_PARAM *);
91 extern void com_close(void);
92
93 extern char rsraw_id_string[]; /* defined in rsraw.c */
94 extern char rsraw_writers[]; /* defined in rsraw.c */
95
96 static FNAME_LIST *last = NULL;
97 static char mybuf[MYBUFSIZE] = {
98 0, /* port number */
99 1, /* flow-control */
100 0, /* hard flow-control */
101 0, /* default = 11 (2400 bps) */
102 0 /* default = 8 (packet size = 1024 bytes) */
103 };
104
105 static APPL_PARAM my_param =
106 {1, 0, bps2400, 0xff, 4,
107 FLAGS_SKIPENQ|FLAGS_ONLY_ONCE|FLAGS_SETFTIME, NULL, NULL};
108
109 static char mydir[MYDIRSIZE];
110 static char version[] = "BPL.EXE v52, by Phinloda\n";
111 static int send_ctrlq = 0;
112 static int silent = 0;
113
114 #ifdef DEBUG
115 FILE *debug_fp = NULL;
116 #endif
117
118 #define STS_IS_NORMAL 0
119 #define NEXT_ARG_IS_DIR 1
120
121 #ifdef JAPANESE
122
123 /* set_options() */
124 #define str_unknown_opt1 "�I�v�V���� "
125 #define str_unknown_opt2 " �͉��߂ł��܂���\n"
126 #define str_usage "\n�g����: bpl [-�I�v�V����] [�t�@�C����]\n"
127
128 /* add_filename_list() */
129 #define str_out_of_memory "������������܂���\n"
130
131 /* main() */
132 #define str_bpl_start "�|BPL �����J�n�|\n"
133 #define str_bpl_end "�|BPL �����I���|\n"
134
135 #else
136
137 #define str_unknown_opt1 "Unknown option (-"
138 #define str_unknown_opt2 ")\n"
139 #define str_usage "\nUsage: bpl [-OPTIONS] [filename]\n"
140 #define str_out_of_memory "Out of memory\n"
141 #define str_bpl_start "- BPL start -\n"
142 #define str_bpl_end "- BPL end -\n"
143
144 #endif
145
146 #ifndef USE_ORIGNAL_CONSOLE_FUNC
147
148 /*--------------------------------------------------------------------*/
charwarn(int c)149 void charwarn(int c)
150 {
151 putc(c, stderr);
152 }
153
154 /*--------------------------------------------------------------------*/
strwarn(char * s)155 void strwarn(char *s)
156 {
157 fputs(s, stderr);
158 }
159
160 /*--------------------------------------------------------------------*/
charout(int c)161 void charout(int c)
162 {
163 putc(c, stderr);
164 }
165
166 /*--------------------------------------------------------------------*/
strout(char * s)167 void strout(char *s)
168 {
169 fputs(s, stderr);
170 }
171
172 /*--------------------------------------------------------------------*/
173 /* printout decimal integer
174 * not thinking about when i == -32768
175 */
decout(int i)176 void decout(int i)
177 {
178 char buf[6];
179 int j;
180
181 if (i < 0) {
182 putchar('-');
183 i = -i;
184 }
185 else if (i == 0) {
186 putchar('0');
187 return;
188 }
189
190 buf[5] = '\0';
191 for (j = 4; ; j--) {
192 buf[j] = ((i % 10) + '0');
193 i /= 10;
194 if (i == 0 || j == 0)
195 break;
196 }
197 strout(buf + j);
198 }
199
200 /*--------------------------------------------------------------------*/
201 /* printout decimal long
202 */
ldecout(unsigned long l)203 void ldecout(unsigned long l)
204 {
205 char buf[11];
206 int i;
207
208 if (l == 0) {
209 putchar('0');
210 return;
211 }
212
213 buf[10] = '\0';
214 for (i = 9; ; i--) {
215 buf[i] = ((l % 10) + '0');
216 l /= 10;
217 if (l == 0 || i == 0)
218 break;
219 }
220 strout(buf + i);
221 }
222
223 #endif
224
225 /*--------------------------------------------------------------------*/
compare_string(char * s1,char * s2)226 static int compare_string(char *s1, char *s2)
227 {
228 char c1;
229 char c2;
230
231 do {
232 c1 = *s1++;
233 if (c1 == ' ' || c1 == '\t')
234 c1 = (char) 0;
235 c2 = *s2++;
236 if (c2 == ' ' || c2 == '\t')
237 c2 = (char) 0;
238 } while ((c1 == c2) && (c1 != (char) 0));
239
240 return (int) c1 - c2;
241 }
242
243 /*--------------------------------------------------------------------*/
244 static char *speed_table[] = {
245 "1S50",
246 "1S75",
247 "1S110",
248 "1S134",
249 "1S150",
250 "1S200",
251 "1S300",
252 "2S600",
253 "4S1200",
254 "6S1800",
255 "8S2400",
256 "8S4800",
257 "8S9600",
258 "8S19200",
259 "8S38400",
260
261 "1P128",
262 "2P256",
263 "4P512",
264 "8P1024",
265 NULL
266 };
267
numeric_option(char * s)268 static int numeric_option(char *s)
269 {
270 char **table;
271 int i;
272
273 i = 0;
274 for (table = speed_table; *table != NULL; table++) {
275 if (compare_string(s, *table + 2) == 0) {
276 if (*(*table + 1) == 'S') {
277 mybuf[3] = i + 1; /* speed */
278 if (mybuf[4])
279 goto skip;
280 }
281 my_param.my_bps = mybuf[4] = **table - '0';
282 skip:
283 return 1;
284 }
285 i++;
286 }
287 return 0;
288 }
289
290 /*--------------------------------------------------------------------*/
291 /* return value
292 * 0 nothing special
293 * 1 next argument is directory name
294 */
set_options(char * s)295 static int set_options(char *s)
296 {
297 char c;
298 int i;
299 int sts = STS_IS_NORMAL;
300
301 while ((c = *s) != 0) {
302 if (c >= '0' && c <= '9') {
303 i = numeric_option(s);
304 if (i) {
305 while (*s >= '0' && *s <= '9')
306 s++;
307 continue;
308 }
309 }
310
311 s++;
312
313 if (c >= 'A' && c <= 'Z')
314 c += 'a' - 'A';
315 switch (c) {
316 #ifdef DEBUG
317 case 'z':
318 my_param.verbose = 3;
319 break;
320 #endif
321
322 case 'a': /* append mode */
323 my_param.append_mode = 1;
324 break;
325
326 case 'b': /* binary */
327 my_param.flags |= FLAGS_BINARY;
328 break;
329
330 case 'c':
331 my_param.flags &= ~FLAGS_ONLY_ONCE;
332 break;
333
334 case 'd': /* set directory */
335 case 'u': /* currently dummy .. */
336 if (*s == ' ')
337 s++; /* ? */
338
339 if (*s) {
340 for (i = 0; i < MYDIRSIZE - 1; i++) {
341 if (*s == '\0')
342 break;
343 if (*s == ' ') {
344 s++;
345 break;
346 }
347 mydir[i] = *s++;
348 }
349 mydir[i] = '\0';
350 my_param.dirname = (UCHAR *) mydir;
351 }
352 else {
353 sts = NEXT_ARG_IS_DIR;
354 }
355 break;
356
357 case 'e':
358 my_param.flags &= ~FLAGS_SKIPENQ;
359 break;
360
361 case 'f': /* force */
362 my_param.flags |= FLAGS_FORCE;
363 break;
364
365 case 'i': /* interval, or initiator */
366 if (*s >= '0' && *s <= '9') {
367 my_param.est_interval = *s - '0';
368 s++;
369 }
370 #ifdef WITH_INITIATOR
371 else {
372 my_param.flags |= FLAGS_INITIATOR;
373 if (*s == 'u') {
374 my_param.flags |= FLAGS_UPLOAD;
375 s++;
376 }
377 }
378 #endif
379 break;
380
381 case 'j': /* look */
382 my_param.flags &= ~FLAGS_SETFTIME;
383 break;
384
385 case 'l': /* look */
386 my_param.verbose |= 4;
387 break;
388
389 case 'n': /* No flow control in com_send */
390 mybuf[1] = 0;
391 break;
392
393 case 'o': /* flying CRC */
394 my_param.flags |= FLAGS_FLY;
395 break;
396
397 case 'p': /* change communication Port */
398 if (*s >= '0' && *s <= '9') { /* 920808 ���i */
399 mybuf[0] = (char) (*s - '0');
400 s++;
401 } else {
402 mybuf[0] = (char) 1;
403 }
404 break;
405
406 case 'q': /* ^Q */
407 send_ctrlq = 1;
408 break;
409
410 #ifdef WITH_RESUME
411 case 'r': /* Resume */
412 my_param.flags |= FLAGS_RESUME;
413 break;
414 #endif
415
416 case 't': /* terse */
417 my_param.verbose = 0;
418 /* fall into next case */
419
420 case 's': /* silent */
421 silent = 1;
422 break;
423
424 case 'v': /* verbose */
425 my_param.verbose |= 2;
426 break;
427
428 case '5': /* check CS */
429 mybuf[2] = 1;
430 break;
431
432 case '7': /* mask parity */
433 my_param.maskchar = 0x7f;
434 break;
435
436 case '-': /* ignore '-' */
437 case ' ': /* ignore ' ' */
438 break;
439
440 default:
441 strwarn(str_unknown_opt1);
442 charwarn(c);
443 strwarn(str_unknown_opt2);
444 /* fall into next case */
445
446 #ifdef __TURBOC__
447 case 'x':
448 strwarn(borlandc_copyright_notice);
449 #endif
450 case 'h': /* help */
451 strwarn(version);
452 strwarn("for CompuServe B Plus Protocol (SM)\n");
453 strwarn(rsraw_id_string);
454 strwarn(", rsraw.c by ");
455 strwarn(rsraw_writers);
456 strwarn(str_usage);
457 exit(1);
458 }
459 }
460
461 return sts;
462 }
463
464 /*--------------------------------------------------------------------*/
add_filename_list(char * name)465 static void add_filename_list(char *name)
466 {
467 FNAME_LIST *tmp;
468
469 tmp = (FNAME_LIST *) malloc(strlen(name) + sizeof(FNAME_LIST));
470 if (tmp == NULL) {
471 strwarn(str_out_of_memory);
472 exit(2);
473 }
474
475 tmp->next = NULL;
476 strcpy(tmp->name, name);
477
478 if (my_param.fnlist == NULL) {
479 my_param.fnlist = tmp;
480 }
481 else {
482 last->next = tmp;
483 }
484
485 last = tmp;
486 }
487
488 /*--------------------------------------------------------------------*/
options(int argc,char * argv[])489 static void options(int argc, char *argv[])
490 {
491 char *s;
492 int sts = 0;
493
494 while (--argc > 0) {
495 s = *++argv;
496 if (sts == NEXT_ARG_IS_DIR) {
497 sts = 0;
498 my_param.dirname = (UCHAR *) s;
499 }
500 else {
501 if (*s == '-') {
502 sts = set_options(s);
503 }
504 else {
505 add_filename_list(s);
506 }
507 }
508 }
509
510 if (mybuf[3] == 0)
511 mybuf[3] = 11; /* default = 2400bps */
512 if (mybuf[4] == 0)
513 my_param.my_bps = mybuf[4] = 8; /* default = 1024 bytes */
514 }
515
516 /*--------------------------------------------------------------------*/
checkenv(char * env[])517 static void checkenv(char *env[])
518 {
519 char *s;
520
521 while ((s = *env++) != 0) {
522 if (s[0] == 'B' && s[1] == 'P' && s[2] == 'L' && s[3] == '=') {
523 set_options(s + 4);
524 }
525 }
526 }
527
528 /*--------------------------------------------------------------------*/
main(int argc,char * argv[],char * env[])529 int main(int argc, char *argv[], char *env[])
530 {
531 int sts;
532
533 checkenv(env);
534 options(argc, argv);
535
536 /* com_setup �G���[���ɂ͒��f���� */
537 if (com_setup(mybuf, MYBUFSIZE)) { /* setup interrupt vector */
538 exit(1);
539 }
540
541 if (my_param.verbose) {
542 strout(str_bpl_start);
543 }
544
545 #ifdef DEBUG
546 debug_fp = NULL;
547 if (my_param.verbose > 2) {
548 debug_fp = fopen("temp.dat", "wb");
549 }
550 #endif
551
552 sts = execute_bpl_session(&my_param);
553
554 #ifdef DEBUG
555 if (my_param.verbose > 2) {
556 fclose(debug_fp);
557 }
558 #endif
559
560 if (send_ctrlq) {
561 com_send((char) ('Q'-'@')); /* oops .. */
562 }
563 com_close(); /* restore interrupt vector */
564 if (my_param.verbose > 0) {
565 if (!silent)
566 charout('G' - '@');
567 charout('\n');
568 strout(str_bpl_end);
569 }
570 exit(sts);
571 }
572