Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/cmd/cs/vcs_src/ifs_agent.c
1810 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 1990-2011 AT&T Intellectual Property *
5
* and is licensed under the *
6
* Eclipse Public License, Version 1.0 *
7
* by AT&T Intellectual Property *
8
* *
9
* A copy of the License is available at *
10
* http://www.eclipse.org/org/documents/epl-v10.html *
11
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12
* *
13
* Information and Software Systems Research *
14
* AT&T Research *
15
* Florham Park NJ *
16
* *
17
* Glenn Fowler <[email protected]> *
18
* *
19
***********************************************************************/
20
/*
21
* File: ifs_agent.c
22
*/
23
#include "ifs_agent.h"
24
#include <sig.h>
25
26
#define IFS_DEBUG
27
28
/*
29
*name: AgentTable
30
* A list structure records the informations about agents.
31
*/
32
struct agent_item *AgentTable;
33
34
/*
35
*name: AgentRegister
36
* Insert a new agent structure in the head of AgentTable
37
* rtn: NULL if error
38
*/
39
struct agent_item *
40
AgentRegister( name, initfunc )
41
char *name;
42
FUNC *initfunc;
43
{
44
struct agent_item *newitem;
45
46
newitem = (struct agent_item *) MallocZero( sizeof(*newitem) );
47
if( newitem != NULL ) {
48
newitem->next = AgentTable;
49
newitem->name = strdup( name );
50
(*initfunc)( newitem );
51
AgentTable = newitem;
52
}
53
return newitem;
54
}
55
56
/*
57
*name: AgentSearch
58
* Find a agent item from the AgentTable
59
* rtn: NULL if not found
60
*/
61
struct agent_item *
62
AgentSearch( name )
63
char *name;
64
{
65
struct agent_item *item;
66
67
if( name != NULL ) {
68
if( *name == 'p' )
69
name++;
70
item = AgentTable;
71
while( item != NULL ) {
72
if( strcmp( name, item->name ) == 0 )
73
return item;
74
item = item->next;
75
}
76
}
77
cserrno = E_PROTOCOL;
78
return NULL;
79
}
80
81
/*
82
* Initial functions of agents
83
*/
84
extern int FtpInit();
85
extern int GopherInit();
86
extern int HttpInit();
87
extern int NewsInit();
88
extern int RshInit();
89
90
int IfsAbortFlag;
91
/*
92
*name: IfsAbortSignal
93
*/
94
void
95
IfsAbortSignal(sig)
96
int sig;
97
{
98
IfsAbortFlag = 1;
99
}
100
101
/*
102
*name: IfsInitial
103
* Initial the agents of IFS
104
*/
105
void
106
IfsInitial()
107
{
108
signal( SIGHUP, IfsAbortSignal );
109
AgentRegister( "ftp", FtpInit );
110
AgentRegister( "gopher", GopherInit );
111
AgentRegister( "http", HttpInit );
112
AgentRegister( "news", NewsInit );
113
AgentRegister( "rsh", RshInit );
114
}
115
116
/*
117
*name: MountListTable
118
* A list structure records the mount lists of individual users.
119
*/
120
struct mount_list *MountListTable;
121
122
/*
123
*name: MountListSearch
124
* Search the mount list of a special user.
125
* Insert a new mount list if not found.
126
*/
127
struct mount_list *
128
MountListSearch( uid )
129
int uid;
130
{
131
struct mount_list *ml;
132
133
ml = MountListTable;
134
while( ml != NULL ) {
135
if( ml->uid == uid )
136
return ml;
137
ml = ml->next;
138
}
139
ml = (struct mount_list *) MallocZero( sizeof(*ml) );
140
if( ml != NULL ) {
141
ml->next = MountListTable;
142
ml->uid = uid;
143
MountListTable = ml;
144
}
145
return ml;
146
}
147
148
/*
149
*name: MountItemDump
150
* Dump the mount information
151
*/
152
#ifdef IFS_DEBUG_DUMP
153
void MountItemDump( mi )
154
struct mount_item *mi;
155
{
156
char buf[ 1024 ], *ptr;
157
int n;
158
159
logit( "mount_item: ++++++++++++++++++++\n" );
160
sfsprintf( buf, sizeof(buf), "\tlpath: %s\n\trpath: %s\n\tmode: %d, timeout: %s\n\t",
161
mi->lpath, mi->rpath, mi->mode, mi->timeout );
162
logit( buf );
163
ag_make_remote( mi, mi->rpath, buf, sizeof(buf) );
164
logit( buf );
165
logit( "\nmount_item: --------------------\n" );
166
}
167
#else
168
#define MountItemDump(mi) (0)
169
#endif
170
171
/*
172
*name: AgentMount
173
* Create a new mount point at localpath and insert to the mount list
174
* rtn: NULL if error
175
*/
176
struct mount_item *
177
AgentMount( ml, url, localpath, option )
178
struct mount_list *ml;
179
char *url;
180
char *localpath;
181
char *option;
182
{
183
struct mount_item *mi;
184
char proto[ STRLEN ];
185
char *host, *ptr, *pass;
186
187
/* url format: "proto:/user:pass@host:port/remote-path" */
188
/* split proto & user:pass@host:port, and remote-path */
189
strncpy( proto, url, sizeof(proto) );
190
if( (host = strchr( proto, '/' )) == NULL || host[-1] != ':' ) {
191
return NULL;
192
}
193
host[-1] = '\0';
194
*host++ = '\0';
195
196
/* check to protocol */
197
if( AgentSearch( proto ) == NULL ) {
198
return NULL;
199
}
200
201
/* allocate a new structure */
202
mi = (struct mount_item *) MallocZero( sizeof( *mi ) );
203
mi->lpath = strdup( localpath );
204
mi->proto = strdup( proto );
205
206
/* split the remote-path */
207
if( (ptr = strchr( host, '/' )) != NULL ) {
208
mi->rpath = strdup( ptr );
209
*ptr = '\0';
210
} else {
211
mi->rpath = strdup( "" );
212
}
213
214
/* split "user:pass" & "host:port" */
215
if( (ptr = strchr( host, '@' )) != NULL ) {
216
*ptr++ = '\0';
217
if( (pass = strchr( host, ':' )) != NULL ) {
218
*pass++ = '\0';
219
mi->passlen = strlen( pass ) + 1;
220
mi->pass = SecurityDataAccess( 0, pass, mi->passlen );
221
}
222
mi->user = strdup( host );
223
host = ptr;
224
}
225
226
/* parse the host & port number */
227
if( (ptr = strchr( host, ':' )) != NULL ) {
228
*ptr++ = '\0';
229
mi->port = (int)strtol(ptr, (char**)0, 0);
230
}
231
mi->host = strdup( host );
232
233
/* parse the timeout value */
234
sfsprintf( mi->timeout, sizeof(mi->timeout), "/%d", option ? (int)strtol(option, (char**)0, 0) : 86400 );
235
236
/* Insert the mount infomation to the mount list */
237
mi->next = ml->mitem;
238
ml->mitem = mi;
239
MakePath( localpath );
240
mkdir( localpath, 0775 );
241
242
return mi;
243
}
244
245
/*
246
*name: AgentUnmount
247
* Unmount a mount point and remove from the mount list
248
* rtn: -1 if error
249
*/
250
int
251
AgentUnmount( ml, lpath )
252
struct mount_list *ml;
253
char *lpath;
254
{
255
struct mount_item *mi, *last;
256
struct server_info srv;
257
258
mi = ml->mitem;
259
if( strcmp( mi->lpath, lpath ) == 0 ) {
260
/* remove the first mount information in mount list */
261
ml->mitem = mi->next;
262
} else {
263
while( 1 ) {
264
last = mi;
265
mi = mi->next;
266
if( mi == NULL ) {
267
/* lpath is not exists in mount list */
268
return -1;
269
}
270
if( strcmp( mi->lpath, lpath ) == 0 )
271
break;
272
}
273
/* remove the mount information after 'last' */
274
last->next = mi->next;
275
}
276
277
/* run disconnect before destroy */
278
srv.mitem = mi;
279
srv.agent = AgentSearch( mi->proto );
280
if( srv.agent != NULL ) {
281
(* (srv.agent->disconnect) )( &srv );
282
}
283
284
/* destroy the mount information */
285
free( mi->lpath );
286
free( mi->proto );
287
free( mi->user );
288
free( mi->host );
289
free( mi->rpath );
290
free( mi );
291
return 0;
292
}
293
294
/*
295
*name: AgentAutoMount
296
* Create an auto mount point and insert to the mount list
297
* rtn: -1 if error
298
*/
299
int
300
AgentAutoMount( ml, lpath )
301
struct mount_list *ml;
302
char *lpath;
303
{
304
char *ptr, *url, *urlend;
305
306
/* matching "(...):/(...)" */
307
ptr = lpath;
308
for (;;)
309
{
310
if (!(ptr = strchr(ptr, ':')))
311
return -1;
312
if (ptr[1] == '/')
313
{
314
if (ptr[2])
315
break;
316
return -1;
317
}
318
ptr++;
319
}
320
urlend = strchr( ptr+2, '/' );
321
while( *ptr != '/' )
322
if( ptr-- <= lpath ) {
323
/* not match with "(...)/proto:/(....)" */
324
return -1;
325
}
326
327
/* split localpath and url */
328
url = ptr+1;
329
if( urlend != NULL ) *urlend = '\0';
330
331
AgentMount( ml, url, lpath, NULL );
332
333
/* restore the lpath */
334
if( urlend != NULL ) *urlend = '/';
335
return 0;
336
}
337
338
struct mount_item *
339
ag_find_mount( ml, lpath, rpath )
340
struct mount_list *ml;
341
char *lpath, *rpath;
342
{
343
struct mount_item *mi;
344
char pathbuf[ STRLEN ];
345
char ch;
346
int len, n;
347
348
len = strlen( lpath );
349
ch = lpath[len-1];
350
switch( ch ) {
351
case '*':
352
if( len>=4 && strncmp(&lpath[len-4], "/*.*", 4) == 0 )
353
len -= 4;
354
else if( len >= 2 && lpath[len-2] == '/' )
355
len -= 2;
356
break;
357
case '?':
358
if( len>=13 && strncmp(&lpath[len-13], "/????????.???", 13) == 0 )
359
len -= 13;
360
break;
361
case '.':
362
if( len >= 2 && lpath[len-2] == '/' )
363
len -= 2;
364
break;
365
}
366
lpath[ len ] = '\0';
367
368
mi = ml->mitem;
369
while( 1 ) {
370
if( mi == NULL && AgentAutoMount( ml, lpath ) == 0 ) {
371
mi = ml->mitem;
372
}
373
if( mi == NULL )
374
break;
375
len = strlen( mi->lpath );
376
if( strncmp( lpath, mi->lpath, len ) == 0 &&
377
(lpath[len] == '/' || lpath[len] == '\0') ) {
378
if( (n = strlen( mi->rpath )) > 0 ) {
379
strcpy( rpath, mi->rpath );
380
}
381
strncpy( rpath + n, lpath + len, STRLEN - n );
382
return mi;
383
}
384
mi = mi->next;
385
}
386
sfsprintf( pathbuf, sizeof(pathbuf), "%s/._dir", lpath );
387
if( (n = open( pathbuf, O_RDWR|O_CREAT, 0644 )) > 0 )
388
close( n );
389
return NULL;
390
}
391
392
int
393
ag_make_remote( mi, rpath, buf, size )
394
struct mount_item *mi;
395
char *rpath, *buf;
396
int size;
397
{
398
char* end = buf + size;
399
400
buf += sfsprintf( buf, end - buf, "%s://", mi->proto ? mi->proto : "-" );
401
if( mi->user )
402
buf += sfsprintf( buf, end - buf, mi->pass ? "%s:*@" : "%s@", mi->user );
403
buf += sfsprintf( buf, end - buf, mi->port ? "%s:%d" : "%s", mi->host, mi->port );
404
if( rpath ) {
405
if( *rpath == '~' ) *buf++ = '/';
406
sfsprintf( buf, end - buf, "%s", rpath );
407
}
408
return 0;
409
}
410
411
int
412
ag_showmount( ml, lpath )
413
struct mount_list *ml;
414
char *lpath;
415
{
416
struct mount_item *item;
417
char rpath[ STRLEN ];
418
char buf[ STRLEN ];
419
int n, num;
420
421
n = sizeof(csusrmsg);
422
item = ml->mitem;
423
if( lpath == NULL || *lpath == '-' ) {
424
num = 0;
425
while( item != NULL ) {
426
num++;
427
item = item->next;
428
}
429
sfsprintf( csusrmsg, n, "0 %d entry(ies)", num );
430
} else if( *lpath != '/' ) {
431
num = (int)strtol( lpath, (char**)0, 0 );
432
while( num > 0 && item != NULL ) {
433
num--;
434
item = item->next;
435
}
436
if( item == NULL ) {
437
sfsprintf( csusrmsg, n, "1 unknown %s", lpath );
438
} else {
439
ag_make_remote( item, item->rpath, buf, sizeof(buf) );
440
sfsprintf( csusrmsg, n, "0 %s %s", buf, item->lpath );
441
}
442
} else {
443
item = ag_find_mount( ml, lpath, rpath );
444
if( item == NULL ) {
445
sfsprintf( csusrmsg, n, "1 unknown %s", lpath );
446
} else {
447
ag_make_remote( item, rpath, buf, sizeof(buf) );
448
sfsprintf( csusrmsg, n, "0 %s %s", buf, lpath );
449
}
450
}
451
return 0;
452
}
453
454
int
455
ag_parsepath( srv, uid, argc, argv, proxy )
456
struct server_info *srv;
457
int uid, argc;
458
char *argv[];
459
char *proxy;
460
{
461
struct mount_list *ml;
462
struct mount_item *mitem;
463
464
IfsAbortFlag = 0;
465
if( argc < 2 ) {
466
cserrno = E_ARGUMENT;
467
return -1;
468
}
469
ml = MountListSearch( uid );
470
if( (mitem = ag_find_mount( ml, argv[1], srv->rpath )) == NULL ) {
471
strncpy( csusrmsg, argv[1], sizeof( csusrmsg ) );
472
cserrno = E_MOUNT;
473
return -1;
474
}
475
srv->mitem = mitem;
476
srv->lpath = argv[1];
477
srv->flags = 0;
478
srv->proxy = proxy;
479
if( mitem->proto[0] == 'p' ) { /* using proxy to connect socket */
480
srv->flags |= IFS_PROXY;
481
}
482
if( (srv->agent = AgentSearch( mitem->proto )) == NULL ) {
483
strncpy( csusrmsg, mitem->proto, sizeof( csusrmsg ) );
484
cserrno = E_PROTOCOL;
485
return -1;
486
}
487
if( mitem->host == NULL ) {
488
cserrno = E_GETHOST;
489
return -1;
490
}
491
492
#ifdef DEBUG
493
if( 1 ) {
494
int flog;
495
char remote[ STRLEN ];
496
char buf[ STRLEN ];
497
498
MountItemDump( mitem );
499
ag_make_remote( mitem, srv->rpath, remote, sizeof(remote) );
500
sfsprintf( buf, STRLEN, " %s (fd=%d)\n", remote, srv->mitem->mode );
501
logit( buf );
502
}
503
#endif
504
return 0;
505
}
506
507
/*
508
*name: cserrmsg
509
*/
510
static char *
511
cserrmsg()
512
{
513
char *msg;
514
515
switch( cserrno ) {
516
case E_NIL: msg = "nil"; break;
517
case E_COMMAND: msg = "unimplement command"; break;
518
case E_ARGUMENT: msg = "invalid arguments"; break;
519
case E_MOUNT: msg = "unmounted path"; break;
520
case E_PROTOCOL: msg = "unknown protocol"; break;
521
case E_OPENDEST: msg = "dest-file open error"; break;
522
case E_GETHOST: msg = "unknown hostname"; break;
523
case E_SOCKET: msg = "can't open stream socket"; break;
524
case E_CONNECT: msg = "can't connect to server"; break;
525
case E_USERAUTH: msg = "user authentication error"; break;
526
case E_DATAXFER: msg = "data transfer error"; break;
527
default: msg = "undefined error number"; break;
528
}
529
return msg;
530
}
531
532
int
533
csputmsg( buf, bsize, rcode )
534
char *buf;
535
int bsize;
536
int rcode;
537
{
538
int len;
539
540
if( rcode < 0 ) {
541
len = sfsprintf( buf, bsize, "E %d %s %s\n",
542
cserrno, cserrmsg(), csusrmsg );
543
} else {
544
len = sfsprintf( buf, bsize, "I %d ok %s\n", E_NIL, csusrmsg );
545
}
546
logit( buf );
547
return len;
548
}
549
550
/*
551
*name: IfsCacheValid
552
*/
553
int
554
IfsCacheValid( fpath, expire )
555
char *fpath;
556
unsigned long expire;
557
{
558
struct stat st;
559
char buf[ STRLEN ];
560
unsigned long mtime;
561
562
if( stat(fpath, &st) ) {
563
return 0; /* no such file */
564
} else if( S_ISDIR( st.st_mode ) ) {
565
strcpy( buf, fpath );
566
strcat( buf, "/._dir" );
567
if( lstat(buf, &st) )
568
return 0; /* no file: fpath/._dir */
569
if( expire == CS_NEVER )
570
return 1;
571
}
572
mtime = st.st_mtime;
573
return ( mtime > cs.time || (cs.time - mtime) < expire );
574
}
575
576
/*
577
* Usage: mount url local-path option
578
* url format: protocol:/user:passwd@host:port/remote-path
579
*/
580
int
581
IfsMount( ret, retsize, uid, argc, argv )
582
char *ret;
583
int uid, argc;
584
char *argv[];
585
{
586
struct mount_list *ml;
587
struct mount_item *mi;
588
char remote[ STRLEN ], *option;
589
int n;
590
591
ml = MountListSearch( uid );
592
n = sizeof( csusrmsg );
593
if( argc < 3 ) {
594
ag_showmount( ml, argc < 2 ? NULL : argv[1] );
595
} else if( *argv[1] == '-' ) {
596
if( AgentUnmount( ml, argv[2] ) ) {
597
sfsprintf( csusrmsg, n, "1 error %s", argv[1] );
598
} else {
599
sfsprintf( csusrmsg, n, "0 unmount %s", argv[1] );
600
}
601
} else {
602
option = (argc < 4 ? NULL : argv[3]);
603
if( (mi = AgentMount( ml, argv[1], argv[2], option )) == NULL )
604
return csputmsg( ret, retsize, -1 );
605
ag_make_remote( mi, mi->rpath, remote, sizeof(remote) );
606
sfsprintf( csusrmsg, n, "0 mount %s %s", remote, argv[2] );
607
}
608
return csputmsg( ret, retsize, 0 );
609
}
610
611
/*
612
* Usage: connect protocol server user-info
613
*/
614
int
615
IfsConnect( ret, retsize, uid, argc, argv )
616
char *ret;
617
int argc;
618
char *argv[];
619
{
620
struct server_info srv;
621
622
if( ag_parsepath( &srv, uid, argc, argv, NiL ) == 0 &&
623
(* (srv.agent->connect))( &srv ) == 0 )
624
return csputmsg( ret, retsize, 0 );
625
return csputmsg( ret, retsize, -1 );
626
}
627
628
/*
629
* Usage: disconnect protocol server
630
*/
631
int
632
IfsDisconnect( ret, retsize, uid, argc, argv )
633
char *ret;
634
int argc;
635
char *argv[];
636
{
637
struct server_info srv;
638
639
if( ag_parsepath( &srv, uid, argc, argv, NiL ) == 0 &&
640
(* (srv.agent->disconnect))( &srv ) == 0 )
641
return csputmsg( ret, retsize, 0 );
642
return csputmsg( ret, retsize, -1 );
643
}
644
645
/*
646
* Usage: listdents local-path
647
*/
648
int
649
IfsListDEnts( ret, retsize, uid, argc, argv )
650
char *ret;
651
int argc;
652
char *argv[];
653
{
654
struct server_info srv;
655
656
if( ag_parsepath( &srv, uid, argc, argv, NiL ) == 0 &&
657
(* (srv.agent->listdents))( &srv ) == 0 )
658
return csputmsg( ret, retsize, 0 );
659
return csputmsg( ret, retsize, -1 );
660
}
661
662
/*
663
* Usage: getfile local-path
664
*/
665
int
666
IfsGetFile( ret, retsize, uid, argc, argv )
667
char *ret;
668
int argc;
669
char *argv[];
670
{
671
struct server_info srv;
672
673
if( ag_parsepath( &srv, uid, argc, argv, NiL ) == 0 &&
674
(* (srv.agent->getfile))( &srv ) == 0 )
675
return csputmsg( ret, retsize, 0 );
676
return csputmsg( ret, retsize, -1 );
677
}
678
679
/*
680
* Usage: open logical path [name=value] ...
681
* stat logical path [name=value] ...
682
*/
683
int
684
IfsReal(ret, retsize, uid, argc, argv)
685
char* ret;
686
int retsize;
687
int uid;
688
int argc;
689
char* argv[];
690
{
691
register int n;
692
char* physical;
693
char* proxy;
694
unsigned long expire;
695
struct server_info srv;
696
char buf[PATH_MAX];
697
698
if (argc < 3) {
699
cserrno = E_ARGUMENT;
700
return sfsprintf(ret, retsize, "%s\n", argc<2?"":argv[1]);
701
}
702
physical = argv[1];
703
expire = 86400;
704
proxy = 0;
705
for (n = 3; n < argc; n++) {
706
if (strneq(argv[n], "expire=", 7))
707
expire = strelapsed(argv[n] + 7, NiL, 1);
708
else if (strneq(argv[n], "physical=", 9))
709
physical = argv[n] + 9;
710
else if (strneq(argv[n], "proxy=", 6))
711
proxy = argv[n] + 6;
712
}
713
if( *argv[0] == 's' ) /* stat command */
714
expire = CS_NEVER;
715
if( argv[2][0] == '.' && argv[2][1] == '\0' )
716
sfsprintf(buf, sizeof(buf), "%s", physical);
717
else
718
sfsprintf(buf, sizeof(buf), "%s/%s", physical, argv[2]);
719
argv[1] = buf;
720
argv[2] = 0;
721
sfsprintf(ret, retsize, "\ncmd> %s %s\n", argv[0], buf );
722
logit(ret);
723
if ( ag_parsepath(&srv, uid, 2, argv, proxy) ) {
724
n = -1; /* unmounted path */
725
} else {
726
physical = strdup(srv.lpath);
727
if( IfsCacheValid(physical, expire) ||
728
!(*srv.agent->getfile)(&srv) )
729
n = 0; /* file validated */
730
else
731
n = -1; /* getfile failed */
732
strcpy( buf, physical );
733
free( physical );
734
}
735
csputmsg(ret, retsize, n);
736
return sfsprintf(ret, retsize, "%s\n", buf);
737
}
738
739
/*
740
* Usage: putfile [source] local-path
741
*/
742
int
743
IfsPutFile( ret, retsize, uid, argc, argv )
744
char *ret;
745
int argc;
746
char *argv[];
747
{
748
struct server_info srv;
749
char *src, *dst;
750
751
if( argc > 2 ) {
752
src = argv[1];
753
dst = argv[2];
754
CopyFile( src, dst );
755
argv[1] = dst;
756
}
757
if( ag_parsepath( &srv, uid, argc, argv, NiL ) == 0 &&
758
(* (srv.agent->putfile))( &srv ) == 0 )
759
return csputmsg( ret, retsize, 0 );
760
return csputmsg( ret, retsize, -1 );
761
}
762
763
/*
764
* Usage: userdef protocol arguments
765
*/
766
int
767
IfsUserDef( ret, retsize, uid, argc, argv )
768
char *ret;
769
int argc;
770
char *argv[];
771
{
772
struct server_info srv;
773
774
if( ag_parsepath( &srv, uid, argc, argv, NiL ) == 0 &&
775
(* (srv.agent->userdef))( &srv, argc -1, &argv[1] ) == 0 )
776
return csputmsg( ret, retsize, 0 );
777
return csputmsg( ret, retsize, -1 );
778
}
779
780
781