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