CoCalc Public Fileswww / onhand / fton / fton.cOpen with one click!
Author: William A. Stein
1
/* fton.c
2
* Copyright (C) 1998 N.Fukase
3
* Modified by William Stein ([email protected]), November 1999.
4
*
5
* This program is free software; you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License as published by
7
* the Free Software Foundation; either version 2 of the License, or
8
* (at your option) any later version.
9
*
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
14
*
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 59 Temple Place - Suite 330,
18
* Boston, MA 02111-1307, USA
19
*/
20
21
#include <stdio.h>
22
#include <string.h>
23
#include <stdlib.h>
24
#include <sys/types.h>
25
#include <sys/stat.h>
26
#include <sys/wait.h>
27
#include <fcntl.h>
28
#include <termios.h>
29
#include <unistd.h>
30
#include <time.h>
31
#include <utime.h>
32
#include <readline/readline.h>
33
#include <readline/history.h>
34
35
#include "rupcommand.h"
36
#include "rupserial.h"
37
38
static char rup_line[FILENAME_MAX] = {"/dev/ttyS0"};
39
static char rup_cwd[64] = {"B:\\"};
40
static char rup_cwdA[64] = {"A:\\"};
41
static char rup_cwdB[64] = {"B:\\"};
42
static char prompt[80]= {"fton> "};
43
static char ftr_version[]= {"0.1a"};
44
45
/*===== readline�ط� ========================================================*/
46
/*_____ ����̵���Τǥץ��ȥ�������� ________________________________________*/
47
int rlc_ls(char **coms);
48
int rlc_ver(char **coms);
49
int rlc_ren(char **coms);
50
int rlc_cp(char **coms);
51
int rlc_mkdir(char **coms);
52
int rlc_rmdir(char **coms);
53
int rlc_del(char **coms);
54
int rlc_lpwd(char **coms);
55
int rlc_lcd(char **coms);
56
int rlc_pwd(char **coms);
57
int rlc_put(char **coms);
58
int rlc_get(char **coms);
59
int rlc_lls(char **coms);
60
int rlc_cd(char **coms);
61
int rlc_help(char **coms);
62
/*_____ ���ޥ�ɥ����� ______________________________________________________*/
63
typedef enum {
64
ca_none = 0,
65
ca_remote,
66
ca_remote_d,
67
ca_local,
68
ca_local_d,
69
ca_line,
70
ca_command,
71
ca_valiable
72
} COMATTR;
73
/*_____ ���ޥ�ɤΥꥹ�Ȥι�¤�� ____________________________________________*/
74
typedef struct {
75
char *name;
76
COMATTR attr;
77
Function *func;
78
char *doc;
79
} COMMAND;
80
/*_____ ���ޥ�ɤΥꥹ�� ____________________________________________________*/
81
COMMAND commands[] = {
82
{ "cd", ca_remote_d, rlc_cd, "change onHand\'s current working directory"},
83
{ "close", ca_none, NULL, "close the connection to onHand"},
84
{ "cp", ca_remote_d, rlc_cp, "copy file in onHand\'s"},
85
{ "delete", ca_remote, rlc_del, "delete file in onHand"},
86
{ "get", ca_remote, rlc_get, "get a file from onHand" },
87
{ "help", ca_command, rlc_help, "display this text" },
88
{ "?", ca_command, rlc_help, "display this text"},
89
{ "lcd", ca_local_d, rlc_lcd, "change local current working directory"},
90
{ "lls", ca_local, rlc_lls, "list contents of local directory"},
91
{ "lpwd", ca_none, rlc_lpwd, "print local current working directory" },
92
{ "ls", ca_remote, rlc_ls, "list contents of onHand\'s directory" },
93
{ "mkdir", ca_remote, rlc_mkdir, "make directory in onHand" },
94
{ "mv", ca_remote, rlc_ren, "rename file in onHand" },
95
{ "open", ca_none, NULL, "open a connection to onHand"},
96
{ "put", ca_local, rlc_put, "put a file into onHand" },
97
{ "pwd", ca_none, rlc_pwd, "print the current working directory of onHand"},
98
{ "quit", ca_none, NULL, "quit this programm"},
99
{ "rename", ca_remote, rlc_ren, "rename file"},
100
{ "rm", ca_remote, rlc_del, "remove file in onHand" },
101
{ "rmdir", ca_remote, rlc_rmdir, "remove a directory in onHand" },
102
{ "ver", ca_none, rlc_ver, "print WPs-DOS\'s version"},
103
{ (char *)NULL, ca_none, (Function *)NULL, (char *)NULL }
104
};
105
/*_____ readline Ruputer�ե�����̾�䴰�ѥꥹ�ȥ����ͥ졼�� __________________*/
106
char *
107
ruputerfile_generator(char *text, int state)
108
{
109
static int list_index, len;
110
static RDENT rde = {0, NULL, ""};
111
112
if (!state) {
113
list_index = -1;
114
len = strlen(text);
115
free(rde.rfi);
116
strcpy(rde.path, rup_cwd);
117
strcat(rde.path, "*.*");
118
command_dir(&rde);
119
}
120
while ((list_index + 1) < rde.nfiles) {
121
list_index++;
122
if (strncmp(rde.rfi[list_index].name, text, len) == 0) {
123
return strdup(rde.rfi[list_index].name);
124
}
125
}
126
return ((char *)NULL);
127
}
128
/*_____ readline���ޥ���䴰�ѥꥹ�ȥ����ͥ졼�� ____________________________*/
129
char *
130
command_generator (char *text, int state)
131
{
132
static int list_index, len;
133
char *name;
134
135
if (!state) {
136
list_index = 0;
137
len = strlen(text);
138
}
139
while ((name = commands[list_index].name) != NULL) {
140
list_index++;
141
if (strncmp (name, text, len) == 0)
142
return strdup(name);
143
}
144
return ((char *)NULL);
145
}
146
/*_____ readline�䴰 ________________________________________________________*/
147
char **
148
rft_comp(char *text, int start, int end)
149
{
150
char **matches;
151
char buf[64];
152
int i;
153
154
matches = (char **)NULL;
155
if (start == 0)
156
matches = completion_matches(text, command_generator);
157
else {
158
strcpy(buf, rl_line_buffer);
159
if(strtok(buf, " \t") != NULL) {
160
for(i = 0; commands[i].name != NULL; i++) {
161
if (strcmp(commands[i].name, buf) == 0) {
162
if((commands[i].attr == ca_remote) || (commands[i].attr == ca_remote_d)) {
163
matches = completion_matches(text, ruputerfile_generator);
164
break;
165
} else if(commands[i].attr == ca_command) {
166
matches = completion_matches(text, command_generator);
167
break;
168
}
169
}
170
}
171
}
172
}
173
return (matches);
174
}
175
/*_____ readline����� ______________________________________________________*/
176
void
177
init_readline(void)
178
{
179
rl_readline_name = "rft";
180
rl_attempted_completion_function = (CPPFunction *)rft_comp;
181
}
182
/*_____ ���󥿥饯�ƥ��֥⡼�� ______________________________________________*/
183
void
184
intteruct(void)
185
{
186
char *coms[256], *name, *line;
187
int i;
188
189
init_readline();
190
for(;;) {
191
line = readline(prompt);
192
if (line && *line) {
193
add_history(line);
194
/* ���ޥ�ɤȰ����򥹥ڡ��������֤�ʬΥ */
195
if((coms[0] = strtok(line, " \t")) == NULL) {
196
free(line);
197
continue;
198
}
199
for (i = 1; (coms[i] = strtok(NULL, " \t")) != NULL; ++i)
200
;
201
/* ���ޥ�ɤ򸡺����Ƽ¹� */
202
for (i = 0; (name = commands[i].name) != NULL; i++) {
203
if (*coms[0] == 'q') {
204
free(line);
205
return;
206
}
207
if (strcmp(name, coms[0]) == 0) {
208
if(commands[i].func != NULL)
209
(*(commands[i].func))(coms);
210
else
211
printf("Sorry! this command is not available\n");
212
break;
213
}
214
}
215
if (name == NULL)
216
printf("no such command `%s\'\n", coms[0]);
217
}
218
free(line);
219
}
220
}
221
/*===== rupcom�ط� ==========================================================*/
222
/*_____ �ե��������� ________________________________________________________*/
223
void
224
send_file(char *fn, char *rp)
225
{
226
char *ptr;
227
int fd;
228
LENDAT dat; /* ž���ǡ�����Ǽ�� */
229
RFINFO rfi; /* ž���ǡ������� */
230
struct stat st;
231
struct tm *ftm;
232
233
if ((fd = open(fn, O_RDONLY)) >= 0) {
234
fstat(fd, &st);
235
if ((dat.data = (char *)malloc(st.st_size)) == NULL) {
236
fprintf(stderr, "Cannot allocate memory\n");
237
close(fd);
238
} else {
239
read(fd, dat.data, st.st_size);
240
dat.length = st.st_size;
241
ftm = localtime(&(st.st_mtime));
242
rfi.cdate = ((((ftm->tm_year - 80) & 0x7f) << 9) | \
243
(((ftm->tm_mon & 0xf) + 1) << 5) | \
244
(ftm->tm_mday & 0x1f));
245
rfi.ctime = (((ftm->tm_hour & 0x1f) << 11) | \
246
((ftm->tm_min & 0x3f) << 5) | \
247
((ftm->tm_sec >> 1) & 0x1f));
248
rfi.attr = 0;
249
rfi.size = st.st_size;
250
close(fd);
251
if((ptr = strrchr(fn, '/')) == NULL) {
252
strcpy(rfi.name, fn);
253
}else {
254
strcpy(rfi.name, ptr + 1);
255
}
256
command_upload(&dat, &rfi, rp);
257
free(dat.data);
258
}
259
} else
260
fprintf(stderr, "Cannot open file %s\n", fn);
261
}
262
/*_____ �ե�������� ________________________________________________________*/
263
void
264
recv_file(char *fn, char *rp)
265
{
266
int fd;
267
LENDAT dat; /* ž���ǡ�����Ǽ�� */
268
RFINFO rfi; /* ž���ǡ������� */
269
struct tm ftm;
270
struct utimbuf ut;
271
272
if ((fd = open(fn, O_RDWR | O_CREAT | O_EXCL, 0777)) >= 0) {
273
strncpy(rfi.name, fn, 12);
274
rfi.name[13] = '\0';
275
if (command_download(&dat, &rfi, rp) != 0) {
276
close(fd);
277
return;
278
}
279
write(fd, dat.data, dat.length);
280
close(fd);
281
ftm.tm_year = ((rfi.cdate >> 9) & 0x7f) + 80;
282
ftm.tm_mon = ((rfi.cdate >> 5) & 0xf) - 1;
283
ftm.tm_mday = (rfi.cdate & 0x1f);
284
ftm.tm_hour = ((rfi.ctime >> 11) & 0x1f);
285
ftm.tm_min = ((rfi.ctime >> 5) & 0x3f);
286
ftm.tm_sec = ((rfi.ctime & 0x1f) << 1);
287
ftm.tm_isdst = 0;
288
ut.actime = mktime(&ftm);
289
ut.modtime = ut.actime;
290
utime(rfi.name, &ut);
291
free(dat.data);
292
} else
293
fprintf(stderr, "Already have file %s\n", fn);
294
}
295
/*_____ ls _________________________________________________________________*/
296
void
297
get_file_list(char *rf, char *rp)
298
{
299
RDENT rde;
300
int i;
301
302
strcpy(rde.path, rp);
303
if (rf == NULL)
304
strcat(rde.path, "*.*");
305
else
306
strcat(rde.path, rf);
307
command_dir(&rde);
308
309
for(i = 0; i < rde.nfiles; ++i) {
310
printf("%s\n", rde.rfi[i].name);
311
}
312
free(rde.rfi);
313
}
314
/*===== �ᥤ��롼���� ======================================================*/
315
int
316
main(int argc, char *argv[])
317
{
318
char *name;
319
int i, c = 1, opts = 1;
320
int rn; /* ruputer negotiate */
321
322
for (i = 1; i < argc; i++) {
323
name = argv[i];
324
if (*name == '-') {
325
opts++;
326
for (name++; *name != '\0'; name++) {
327
argv[i] = NULL;
328
if (c == i )
329
c++;
330
switch(*name) {
331
case 'V':
332
fprintf(stderr, "%s version %s\n", argv[0], ftr_version);
333
fprintf(stderr, "Copyright (C) 1998 N.Fukase\n");
334
fprintf(stderr, "All Rigth Reserverd\n");
335
return 0;
336
case 'v':
337
fprintf(stderr, "%s version %s\n", argv[0], ftr_version);
338
return 0;
339
case 'l':
340
if (name[1] == '\0') {
341
opts++;
342
i++;
343
strcpy(rup_line, argv[i]);
344
argv[i] = NULL;
345
if (c == i)
346
c++;
347
goto exit_loop;
348
} else {
349
strcpy(rup_line, name);
350
goto exit_loop;
351
}
352
break;
353
default:
354
fprintf(stderr, "Invalid option letter %c\n", *name);
355
break;
356
}
357
358
}
359
exit_loop:
360
}
361
}
362
if (argc == opts) {
363
/* ��³ */
364
fprintf(stderr, "Connecting onHand on %s....\n", rup_line);
365
fprintf(stderr, "Trying to initialize line...\n");
366
init_line(rup_line);
367
fprintf(stderr, "Line initialized.\n");
368
while((rn = ruputer_negotiate()) < 0)
369
fprintf(stderr, "Failure: ruputer_negotiate = %d\n", rn);
370
fprintf(stderr, "Connect!\n");
371
command_chdir("b:\\");
372
intteruct();
373
/* ��λ */
374
command_end();
375
restore_line();
376
return 0;
377
} else {
378
for (i = 0; (name = commands[i].name) != NULL; i++) {
379
if ((strcmp(name, argv[c]) == 0) && (commands[i].func != NULL)){
380
init_line(rup_line);
381
while(ruputer_negotiate() < 0)
382
;
383
command_chdir("b:\\");
384
(*(commands[i].func))(&argv[c]);
385
command_end();
386
restore_line();
387
return 0;
388
}
389
}
390
return -1;
391
}
392
}
393
/*===== readline���ޥ�� ====================================================*/
394
/*_____ ls Ruputer�Υե�����ꥹ�Ȥ�ɽ�� ____________________________________*/
395
int rlc_ls(char **coms)
396
{
397
if(coms[1] == NULL)
398
get_file_list("*.*", rup_cwd);
399
else
400
get_file_list(coms[1], rup_cwd);
401
return 0;
402
}
403
/*_____ ver Ruputer��OS�С�������ɽ�� _____________________________________*/
404
int rlc_ver(char **coms)
405
{
406
int r;
407
408
r = command_ver();
409
printf("%d.%d\n", (r & 0xff), ((r & 0xff00) >> 8));
410
return 0;
411
}
412
/*_____ pwd Ruputer��CWD��ɽ�� ______________________________________________*/
413
int rlc_pwd(char **coms)
414
{
415
printf("onHand\'s Current Directory is %s\n", rup_cwd);
416
return 0;
417
}
418
/*_____ ren Ruputer��Υե�������͡��� ___________________________________*/
419
int rlc_ren(char **coms)
420
{
421
if ((coms[1] != NULL ) & (coms[2] != NULL)) {
422
command_ren(coms[2], coms[1]);
423
return 0;
424
} else {
425
printf("Too few arguement\n");
426
return -1;
427
}
428
}
429
/*_____ pwd Ruputer��Υե�����򥳥ԡ� _____________________________________*/
430
int rlc_cp(char **coms)
431
{
432
if ((coms[1] != NULL ) & (coms[2] != NULL)) {
433
command_copy(coms[2], coms[1]);
434
return 0;
435
} else {
436
printf("Too few arguement\n");
437
return -1;
438
}
439
}
440
/*_____ mkdir Ruputer��˥ǥ��쥯�ȥ���� ___________________________________*/
441
int rlc_mkdir(char **coms)
442
{
443
int i;
444
445
if (coms[1] != NULL) {
446
for (i = 1; coms[i] != NULL ; ++i) {
447
command_mkdir(coms[i]);
448
}
449
return 0;
450
} else {
451
printf("Too few arguement\n");
452
return -1;
453
}
454
}
455
/*_____ rmdir Ruputer��Υǥ��쥯�ȥ��� ___________________________________*/
456
int rlc_rmdir(char **coms)
457
{
458
int i;
459
460
if (coms[1] != NULL) {
461
for (i = 1; coms[i] != NULL ; ++i) {
462
command_rmdir(coms[i]);
463
}
464
return 0;
465
} else {
466
printf("Too few arguement\n");
467
return -1;
468
}
469
}
470
/*_____ del Ruputer��Υե������� _________________________________________*/
471
int rlc_del(char **coms)
472
{
473
int i;
474
475
if (coms[1] != NULL) {
476
for (i = 1; coms[i] != NULL ; ++i) {
477
command_del(coms[i]);
478
}
479
return 0;
480
} else {
481
printf("Too few arguement\n");
482
return -1;
483
}
484
}
485
/*_____ lpwd ��������CWDɽ��(ls�ؤ�wrapper) _________________________________*/
486
int rlc_lpwd(char **coms)
487
{
488
char buf[FILENAME_MAX];
489
490
getcwd(buf, FILENAME_MAX);
491
printf("Local current directory is %s\n", buf);
492
return 0;
493
}
494
/*_____ lcd ��������CWD��ư _________________________________________________*/
495
int rlc_lcd(char **coms)
496
{
497
char buf[FILENAME_MAX];
498
499
if (coms[1] != NULL)
500
chdir(coms[1]);
501
else
502
chdir(getenv("HOME"));
503
getcwd(buf, FILENAME_MAX);
504
printf("Now, local current directory is %s\n", buf);
505
return 0;
506
}
507
/*_____ put Ruputer�إե�����ž�� ___________________________________________*/
508
int rlc_put(char **coms)
509
{
510
if (coms[1] != NULL)
511
send_file(coms[1], rup_cwd);
512
return 0;
513
}
514
/*_____ get Ruputer����ե������ž�� _______________________________________*/
515
int rlc_get(char **coms)
516
{
517
if (coms[1] != NULL)
518
recv_file(coms[1], rup_cwd);
519
return 0;
520
}
521
/*_____ lls ��������Υե�����ꥹ�Ȥ�ɽ��(ls�ؤ�wrapper) ___________________*/
522
int rlc_lls(char **coms)
523
{
524
int pid, status;
525
526
if ((pid = fork()) < 0) {
527
perror("fork");
528
return -1;
529
}
530
if (pid == 0) {
531
strcpy(coms[0], "ls");
532
execvp(coms[0], coms);
533
perror(coms[0]);
534
exit(-1);
535
}
536
while(wait(&status) != pid)
537
;
538
return status;
539
}
540
/*_____ cd Ruputer��CWD���ѹ� _______________________________________________*/
541
int rlc_cd(char **coms)
542
{
543
char *frm, *to, *rc, *sl, *nsl, *drv;
544
RDENT rde;
545
546
rc = NULL; sl = NULL; // to stop the warnings.
547
frm = coms[1];
548
to = rde.path;
549
550
if (frm == NULL)
551
return rlc_pwd(coms);
552
if (frm[1] == ':') {
553
if ((frm[0] == 'A') || (frm[0] == 'a')) {
554
rc = drv = rup_cwdA;
555
} else if((frm[0] == 'B') || (frm[0] == 'b')) {
556
rc = drv = rup_cwdB;
557
} else {
558
printf("Invalid drive letter\n");
559
return -1;
560
}
561
frm += 2;
562
} else {
563
if (*rup_cwd == 'A') {
564
rc = drv = rup_cwdA;
565
} else if(*rup_cwd == 'B') {
566
rc = drv = rup_cwdB;
567
}
568
strncpy(to, rc, 2);
569
}
570
strncpy(to, rc, 2);
571
to += 2;
572
rc += 2;
573
nsl = NULL;
574
if ((*frm != '\\') && (*frm != '/')) {
575
/* ���Хѥ� */
576
while((*to = *rc) != '\0') {
577
if ((*to == '\\') || (*to == '/')) {
578
*to = '\\';
579
if(nsl == NULL)
580
nsl = sl = to;
581
else {
582
sl = nsl;
583
nsl = to;
584
}
585
}
586
to++;
587
rc++;
588
}
589
if (to[-1] != '\\') {
590
*to = '\\';
591
if(nsl == NULL)
592
nsl = sl = to;
593
else {
594
sl = nsl;
595
nsl = to;
596
}
597
to++;
598
}
599
} else {
600
*to = '\\';
601
nsl = sl = to;
602
frm++;
603
to++;
604
}
605
while(*frm != '\0') {
606
if ((*frm == '.') && (frm[1] == '.')){
607
frm++;
608
if (to[-1] != '\\')
609
to = nsl;
610
else {
611
to = sl;
612
*to = '\0';
613
nsl = sl;
614
sl = strrchr(rde.path, '\\');
615
*to = '\\';
616
to++;
617
if (sl == NULL)
618
sl = nsl;
619
}
620
} else {
621
if ((*frm == '/') || (*frm == '\\')) {
622
if (to[-1] == '\\') {
623
frm++;
624
continue;
625
}
626
*to = '\\';
627
if(nsl == NULL)
628
nsl = sl = to;
629
else {
630
sl = nsl;
631
nsl = to;
632
}
633
sl = to;
634
}else
635
*to = *frm;
636
to++;
637
}
638
frm++;
639
}
640
*to = '\0';
641
if((strcmp(rde.path, "A:\\") == 0) || (strcmp(rde.path, "B:\\") == 0)) {
642
printf("Now, onHand\'s current directory is %s\n", rde.path);
643
strcpy(rup_cwd, rde.path);
644
strcat(rup_cwd, "\\");
645
if (*rup_cwd == 'A')
646
strcpy(rup_cwdA, rde.path);
647
else if (*rup_cwd == 'B')
648
strcpy(rup_cwdB, rde.path);
649
} else {
650
command_dir(&rde);
651
if(rde.nfiles == 1) {
652
printf("Now, onHand\'s current directory is %s\n", rde.path);
653
strcpy(rup_cwd, rde.path);
654
strcat(rup_cwd, "\\");
655
if (*rup_cwd == 'A')
656
strcpy(rup_cwdA, rde.path);
657
else if (*rup_cwd == 'B')
658
strcpy(rup_cwdB, rde.path);
659
}
660
}
661
return 0;
662
}
663
/*_____ ����饤��إ�פ�ɽ�� ______________________________________________*/
664
int
665
rlc_help(char **coms)
666
{
667
int i;
668
669
if(coms[1] != NULL) {
670
for(i = 0; commands[i].name != NULL; i++) {
671
if (strcmp(commands[i].name, coms[1]) == 0) {
672
printf("%s\t%s\n", commands[i].name, commands[i].doc);
673
return 0;
674
}
675
}
676
}
677
for (i = 0; commands[i].name != NULL; ++i) {
678
printf("%s\t%s\n", commands[i].name, commands[i].doc);
679
}
680
return 0;
681
}
682