~ubuntu-branches/ubuntu/vivid/cctools/vivid

« back to all changes in this revision

Viewing changes to parrot/src/pfs_main.cc

  • Committer: Bazaar Package Importer
  • Author(s): Michael Hanke
  • Date: 2011-05-07 09:05:00 UTC
  • Revision ID: james.westby@ubuntu.com-20110507090500-lqpmdtwndor6e7os
Tags: upstream-3.3.2
ImportĀ upstreamĀ versionĀ 3.3.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
Copyright (C) 2003-2004 Douglas Thain and the University of Wisconsin
 
3
Copyright (C) 2005- The University of Notre Dame
 
4
This software is distributed under the GNU General Public License.
 
5
See the file COPYING for details.
 
6
*/
 
7
 
 
8
#include "pfs_channel.h"
 
9
#include "pfs_process.h"
 
10
#include "pfs_dispatch.h"
 
11
#include "pfs_poll.h"
 
12
#include "pfs_service.h"
 
13
#include "pfs_critical.h"
 
14
 
 
15
extern "C" {
 
16
#include "tracer.h"
 
17
#include "stringtools.h"
 
18
#include "auth_all.h"
 
19
#include "xmalloc.h"
 
20
#include "create_dir.h"
 
21
#include "file_cache.h"
 
22
#include "md5.h"
 
23
#include "sort_dir.h"
 
24
#include "password_cache.h"
 
25
#include "debug.h"
 
26
#include "getopt.h"
 
27
#include "pfs_resolve.h"
 
28
#include "chirp_filesystem.h"
 
29
#include "chirp_local.h"
 
30
#include "chirp_acl.h"
 
31
#include "chirp_global.h"
 
32
#include "ftp_lite.h"
 
33
}
 
34
 
 
35
#include <stdlib.h>
 
36
#include <stdio.h>
 
37
#include <errno.h>
 
38
#include <string.h>
 
39
#include <unistd.h>
 
40
#include <signal.h>
 
41
#include <time.h>
 
42
#include <limits.h>
 
43
#include <sys/wait.h>
 
44
#include <fcntl.h>
 
45
#include <sys/utsname.h>
 
46
#include <termio.h>
 
47
#include <termios.h>
 
48
 
 
49
pid_t trace_this_pid = -1;
 
50
 
 
51
int pfs_master_timeout = 300;
 
52
struct file_cache *pfs_file_cache = 0;
 
53
struct password_cache *pfs_password_cache = 0;
 
54
int pfs_trap_after_fork = 0;
 
55
int pfs_force_stream = 0;
 
56
int pfs_force_cache = 0;
 
57
int pfs_force_sync = 0;
 
58
int pfs_follow_symlinks = 1;
 
59
int pfs_session_cache = 0;
 
60
int pfs_use_helper = 1;
 
61
int pfs_checksum_files = 1;
 
62
int pfs_auto_gzip = 0;
 
63
int pfs_write_rval = 0;
 
64
const char *pfs_write_rval_file = "parrot.rval";
 
65
int pfs_enable_small_file_optimizations = 1;
 
66
char pfs_temp_dir[PFS_PATH_MAX];
 
67
 
 
68
int *pfs_syscall_totals32 = 0;
 
69
int *pfs_syscall_totals64 = 0;
 
70
 
 
71
const char *pfs_root_checksum=0;
 
72
const char *pfs_initial_working_directory=0;
 
73
 
 
74
char *pfs_false_uname = 0;
 
75
char *pfs_ccurl = 0;
 
76
char *pfs_ldso_path = 0;
 
77
uid_t pfs_uid = 0;
 
78
gid_t pfs_gid = 0;
 
79
const char * pfs_username = 0;
 
80
 
 
81
INT64_T pfs_syscall_count = 0;
 
82
INT64_T pfs_read_count = 0;
 
83
INT64_T pfs_write_count = 0;
 
84
 
 
85
/*
 
86
This process at the very top of the traced tree
 
87
and its final exit status, which we use to determine
 
88
our own exit status
 
89
*/
 
90
 
 
91
static pid_t root_pid = -1;
 
92
static int root_exitstatus = 0;
 
93
static int channel_size = 10;
 
94
 
 
95
struct chirp_filesystem *cfs = &chirp_local_fs;
 
96
const char *chirp_transient_path = "./";
 
97
 
 
98
static void show_version( const char *cmd )
 
99
{
 
100
        printf("%s version %d.%d.%d built by %s@%s on %s at %s\n",cmd,CCTOOLS_VERSION_MAJOR,CCTOOLS_VERSION_MINOR,CCTOOLS_VERSION_MICRO,BUILD_USER,BUILD_HOST,__DATE__,__TIME__);
 
101
        exit(1);
 
102
}
 
103
 
 
104
static void get_linux_version()
 
105
{
 
106
        struct utsname name;
 
107
        int major,minor,micro,fields;
 
108
 
 
109
        debug(D_DEBUG,"%s version %d.%d.%d built by %s@%s on %s at %s\n","parrot",CCTOOLS_VERSION_MAJOR,CCTOOLS_VERSION_MINOR,CCTOOLS_VERSION_MICRO,BUILD_USER,BUILD_HOST,__DATE__,__TIME__);
 
110
 
 
111
        uname(&name);
 
112
 
 
113
#ifdef CCTOOLS_CPU_I386
 
114
        if(!strcmp(name.machine,"x86_64")) {
 
115
                fatal("Sorry, you need to download a Parrot built specifically for an x86_64 CPU");
 
116
        }
 
117
#endif
 
118
 
 
119
        if(!strcmp(name.sysname,"Linux")) {
 
120
                debug(D_DEBUG,"kernel is %s %s",name.sysname,name.release);
 
121
                fields = sscanf(name.release,"%d.%d.%d",&major,&minor,&micro);
 
122
                if(fields==3) {
 
123
                        if(major==2) {
 
124
                                if(minor==4) {
 
125
                                        pfs_trap_after_fork = 1;
 
126
                                        return;
 
127
                                } else if(minor==6) {
 
128
                                        pfs_trap_after_fork = 0;
 
129
                                        return;
 
130
                                }
 
131
                        }
 
132
                }
 
133
        }
 
134
 
 
135
        debug(D_NOTICE,"parrot_run %d.%d.%d has not been tested on %s %s yet, this may not work",CCTOOLS_VERSION_MAJOR,CCTOOLS_VERSION_MINOR,CCTOOLS_VERSION_MICRO,name.sysname,name.release);
 
136
}
 
137
 
 
138
static void pfs_helper_init( const char *argv0 ) 
 
139
{
 
140
        char helper_path[PFS_PATH_MAX];
 
141
 
 
142
        debug(D_DEBUG,"locating helper library...");
 
143
 
 
144
        sprintf(helper_path,"%s/lib/libparrot_helper.so",INSTALL_PATH);
 
145
 
 
146
        char * s = getenv("PARROT_HELPER");
 
147
        if(s) {
 
148
                debug(D_DEBUG,"PARROT_HELPER=%s",s);
 
149
                strcpy(helper_path,s);
 
150
        } else {
 
151
                debug(D_DEBUG,"PARROT_HELPER is not set");
 
152
        }
 
153
 
 
154
        if(access(helper_path,R_OK)==0) {
 
155
                debug(D_DEBUG,"found helper in %s",helper_path);
 
156
                setenv("LD_PRELOAD",helper_path,1);
 
157
        } else {
 
158
                debug(D_DEBUG,"couldn't find helper library %s but continuing anyway.",helper_path);
 
159
        }
 
160
}
 
161
 
 
162
static void show_use( const char *cmd )
 
163
{
 
164
                /* 80-column text marker */
 
165
                /******************************************************************************/
 
166
        printf("Use: %s [options] <command> ...\n",cmd);
 
167
        printf("Where options and environment variables are:\n");
 
168
        printf("  -a <list>  Use these Chirp authentication methods.   (PARROT_CHIRP_AUTH)\n");
 
169
        printf("  -A <file>  Use this file as a default ACL.          (PARROT_DEFAULT_ACL)\n");
 
170
        printf("  -b <bytes> Set the I/O block size hint.              (PARROT_BLOCK_SIZE)\n");
 
171
        printf("  -c <file>  Print exit status information to <file>.\n");
 
172
        printf("  -C         Enable data channel authentication in GridFTP.\n");
 
173
        printf("  -d <name>  Enable debugging for this sub-system.    (PARROT_DEBUG_FLAGS)\n");
 
174
        printf("  -D         Disable small file optimizations.\n");
 
175
        printf("  -F         Enable file snapshot caching for all protocols.\n");
 
176
        printf("  -f         Disable following symlinks.\n");
 
177
        printf("  -E <url>   Endpoint for gLite combined catalog ifc. (PARROT_GLITE_CCURL)\n");
 
178
        printf("  -G <num>   Fake this gid; Real gid stays the same.          (PARROT_GID)\n");
 
179
        printf("  -H         Disable use of helper library.\n");
 
180
        printf("  -h         Show this screen.\n");
 
181
        printf("  -i <files> Comma-delimited list of tickets to use for authentication.\n");
 
182
        printf("  -K         Checksum files where available.\n");
 
183
        printf("  -k         Do not checksum files.\n");
 
184
        printf("  -l <path>  Path to ld.so to use.                      (PARROT_LDSO_PATH)\n");
 
185
        printf("  -m <file>  Use this file as a mountlist.             (PARROT_MOUNT_FILE)\n");
 
186
        printf("  -M/foo=/bar Mount (redirect) /foo to /bar.         (PARROT_MOUNT_STRING)\n");
 
187
        printf("  -N <name>  Pretend that this is my hostname.          (PARROT_HOST_NAME)\n");
 
188
        printf("  -o <file>  Send debugging messages to this file.     (PARROT_DEBUG_FILE)\n");
 
189
        printf("  -O <bytes> Rotate debug files of this size.     (PARROT_DEBUG_FILE_SIZE)\n");
 
190
        printf("  -p <hst:p> Use this proxy server for HTTP requests.         (HTTP_PROXY)\n");
 
191
        printf("  -Q         Inhibit catalog queries to list /chirp.\n");
 
192
        printf("  -R <cksum> Enforce this root filesystem checksum, where available.\n");
 
193
        printf("  -s         Use streaming protocols without caching.(PARROT_FORCE_STREAM)\n");
 
194
        printf("  -S         Enable whole session caching for all protocols.\n");
 
195
        printf("  -t <dir>   Where to store temporary files.             (PARROT_TEMP_DIR)\n");
 
196
        printf("  -T <time>  Maximum amount of time to retry failures.    (PARROT_TIMEOUT)\n");
 
197
        printf("  -U <num>   Fake this unix uid; Real uid stays the same.     (PARROT_UID)\n");
 
198
        printf("  -u <name>  Use this extended username.                 (PARROT_USERNAME)\n");
 
199
        printf("  -v         Display version number.\n");
 
200
        printf("  -w         Initial working directory.\n");
 
201
        printf("  -W         Display table of system calls trapped.\n");
 
202
        printf("  -Y         Force sYnchronous disk writes.            (PARROT_FORCE_SYNC)\n");
 
203
        printf("  -Z         Enable automatic decompression on .gz files.\n");
 
204
        printf("\n");
 
205
        printf("Known debugging sub-systems are: ");
 
206
        debug_flags_print(stdout);
 
207
        printf("\n");
 
208
        printf("Enabled filesystems are:");
 
209
        if(pfs_service_lookup("http"))          printf(" http");
 
210
        if(pfs_service_lookup("grow"))          printf(" grow");
 
211
        if(pfs_service_lookup("ftp"))           printf(" ftp");
 
212
        if(pfs_service_lookup("anonftp"))       printf(" anonftp");
 
213
        if(pfs_service_lookup("gsiftp"))        printf(" gsiftp");
 
214
        if(pfs_service_lookup("nest"))          printf(" nest");
 
215
        if(pfs_service_lookup("chirp"))         printf(" chirp");
 
216
        if(pfs_service_lookup("gfal"))          printf(" gfal lfn guid srm");
 
217
        if(pfs_service_lookup("rfio"))          printf(" rfio");
 
218
        if(pfs_service_lookup("dcap"))          printf(" dcap");
 
219
        if(pfs_service_lookup("glite"))         printf(" glite");
 
220
        if(pfs_service_lookup("lfc"))           printf(" lfc");
 
221
        if(pfs_service_lookup("irods"))         printf(" irods");
 
222
        if(pfs_service_lookup("hdfs"))          printf(" hdfs");
 
223
        if(pfs_service_lookup("bxgrid"))        printf(" bxgrid");
 
224
        if(pfs_service_lookup("s3"))            printf(" s3");
 
225
        if(pfs_service_lookup("root"))          printf(" root");
 
226
        if(pfs_service_lookup("xrootd"))        printf(" xrootd");
 
227
        printf("\n");
 
228
        exit(1);
 
229
}
 
230
 
 
231
/*
 
232
For all of the signals that we handle, we want to
 
233
run the handler without interruption from other signals.
 
234
*/
 
235
 
 
236
void install_handler( int sig, void (*handler)(int sig))
 
237
{
 
238
        struct sigaction s;
 
239
 
 
240
        s.sa_handler = handler;
 
241
        sigfillset(&s.sa_mask);
 
242
        s.sa_flags = 0; 
 
243
 
 
244
        sigaction(sig,&s,0);
 
245
}
 
246
 
 
247
static void ignore_signal( int sig )
 
248
{
 
249
}
 
250
 
 
251
/*
 
252
It would be nice if we could clean up everyone quietly and then
 
253
some time later, kill hard.  However, on Linux, if someone kills
 
254
us before we have a chance to clean up, then due to a "feature"
 
255
of ptrace, all our children will be left stuck in a debug-wait
 
256
state.  So, rather than chance ourselves getting killed, we
 
257
will be very agressive about cleaning up.  Upon receiving any
 
258
shutdown signal, we immediately blow away everyone involved,
 
259
and then kill ourselves.
 
260
*/
 
261
 
 
262
static void kill_everyone( int sig )
 
263
{
 
264
        debug(D_NOTICE,"received signal %d (%s), killing all my children...",sig,string_signal(sig));
 
265
        pfs_process_killall();
 
266
        debug(D_NOTICE,"sending myself %d (%s), goodbye!",sig,string_signal(sig));
 
267
        while(1) {
 
268
                signal(sig,SIG_DFL);
 
269
                sigsetmask(~sigmask(sig));
 
270
                kill(getpid(),sig);
 
271
                kill(getpid(),SIGKILL);
 
272
        }
 
273
}
 
274
 
 
275
void pfs_abort()
 
276
{
 
277
        kill(getpid(),SIGTERM);
 
278
        exit(1);
 
279
}
 
280
 
 
281
/*
 
282
Other less deadly signals we simply pass through to the root
 
283
of our children for its consideration.
 
284
*/
 
285
 
 
286
static void pass_through( int sig )
 
287
{
 
288
        pfs_process_raise(root_pid,sig,1);
 
289
}
 
290
 
 
291
/*
 
292
We will be fighting with our child processes for control of 
 
293
the terminal.  Whenever a we want to write to the terminal,
 
294
we will get a SIGTTOU or SIGTTIN instructing us that its
 
295
not our turn.  But, we are in charge!  So, upon receipt
 
296
of these signals, grab control of the terminal.
 
297
*/
 
298
 
 
299
static void control_terminal( int sig )
 
300
{
 
301
        if(sig==SIGTTOU) {
 
302
                tcsetpgrp(1,getpid());
 
303
                tcsetpgrp(2,getpid());
 
304
        } else {
 
305
                tcsetpgrp(0,getpid());
 
306
        }
 
307
}
 
308
 
 
309
/*
 
310
Here is the meat and potatoes.  We have discovered that
 
311
something interesting has happened to this pid. Decode
 
312
the event and take the appropriate action.
 
313
*/
 
314
 
 
315
static void handle_event( pid_t pid, int status, struct rusage usage )
 
316
{
 
317
        struct pfs_process *p;
 
318
        int signum;
 
319
 
 
320
        p = pfs_process_lookup(pid);
 
321
        if(!p) {
 
322
                debug(D_PROCESS,"killing unexpected pid %d",pid);
 
323
                kill(pid,SIGKILL);
 
324
                return;
 
325
        }
 
326
 
 
327
        if(WIFEXITED(status)) {
 
328
                debug(D_PROCESS,"pid %d exited normally with code %d",pid,WEXITSTATUS(status));
 
329
                pfs_process_stop(p,status,usage);
 
330
                if(pid==root_pid) root_exitstatus = status;
 
331
        } else if(WIFSIGNALED(status)) {
 
332
                signum = WTERMSIG(status);
 
333
                debug(D_PROCESS,"pid %d exited abnormally with signal %d (%s)",pid,signum,string_signal(signum));
 
334
                pfs_process_stop(p,status,usage);
 
335
                if(pid==root_pid) root_exitstatus = status;
 
336
        } else if(WIFSTOPPED(status)) {
 
337
                signum = WSTOPSIG(status);
 
338
                if(signum==SIGTRAP) {
 
339
                        p->nsyscalls++;
 
340
                        pfs_dispatch(p,0);
 
341
                } else {
 
342
                        debug(D_PROCESS,"pid %d received signal %d (%s) (state %d)",pid,signum,string_signal(signum),p->state);
 
343
                        if(signum==SIGTTIN) {
 
344
                                tcsetpgrp(0,pid);
 
345
                                tracer_continue(p->tracer,SIGCONT);
 
346
                        } else if(signum==SIGTTOU) {
 
347
                                tcsetpgrp(1,pid);
 
348
                                tcsetpgrp(2,pid);
 
349
                                tracer_continue(p->tracer,SIGCONT);
 
350
                        } else {
 
351
                                tracer_continue(p->tracer,signum);
 
352
                                if(signum==SIGSTOP && p->nsyscalls==0) {
 
353
                                        kill(p->pid,SIGCONT);
 
354
                                }
 
355
                        }
 
356
                }
 
357
        } else {
 
358
                fatal("pid %d stopped with strange status %d",pid,status);
 
359
        }
 
360
}
 
361
 
 
362
struct timeval clock_to_timeval( clock_t c )
 
363
{
 
364
        struct timeval result;
 
365
        result.tv_sec = c/CLOCKS_PER_SEC;
 
366
        result.tv_usec = (c - result.tv_sec)*1000000/CLOCKS_PER_SEC;
 
367
        return result;
 
368
}
 
369
 
 
370
void handle_sigchld( int sig  )
 
371
{
 
372
        pfs_poll_abort();
 
373
}
 
374
 
 
375
static void handle_sigio( int sig )
 
376
{
 
377
        pfs_process_sigio();
 
378
}
 
379
 
 
380
void write_rval(const char* message, int status) {
 
381
        FILE *file = fopen(pfs_write_rval_file, "w+");
 
382
        if(file) {
 
383
                fprintf(file, "%s\n%d\n", message, status);
 
384
                fclose(file);
 
385
        }
 
386
 
 
387
}
 
388
 
 
389
int main( int argc, char *argv[] )
 
390
{
 
391
        pid_t pid=0;
 
392
        int signum;
 
393
        int status;
 
394
        struct pfs_process *p;
 
395
        char *s;
 
396
        int i;
 
397
        int chose_auth=0;
 
398
        struct rusage usage;
 
399
        char c;
 
400
        int did_ticket=0;
 
401
 
 
402
        srand(time(0)*(getpid()+getuid()));
 
403
 
 
404
        debug_config(argv[0]);
 
405
        debug_config_file_size(0);
 
406
 
 
407
        if(getenv("PARROT_ENABLED")) {
 
408
                fprintf(stderr,"sorry, parrot_run cannot be run inside of itself.\n");
 
409
                exit(1);
 
410
        }
 
411
 
 
412
        debug_config_fatal(pfs_process_killall);
 
413
        debug_config_getpid(pfs_process_getpid);
 
414
 
 
415
        install_handler(SIGQUIT,kill_everyone);
 
416
        install_handler(SIGILL,kill_everyone);
 
417
        install_handler(SIGABRT,kill_everyone);
 
418
        install_handler(SIGIOT,kill_everyone);
 
419
        install_handler(SIGBUS,kill_everyone);
 
420
        install_handler(SIGFPE,kill_everyone);
 
421
        install_handler(SIGSEGV,kill_everyone);
 
422
        install_handler(SIGTERM,kill_everyone);
 
423
        install_handler(SIGHUP,pass_through);
 
424
        install_handler(SIGINT,pass_through);
 
425
        install_handler(SIGTTIN,control_terminal);
 
426
        install_handler(SIGTTOU,control_terminal);
 
427
        install_handler(SIGCHLD,handle_sigchld);
 
428
        install_handler(SIGIO,handle_sigio);
 
429
        install_handler(SIGXFSZ,ignore_signal);
 
430
 
 
431
        if(isatty(0)) {
 
432
                pfs_master_timeout = 300;
 
433
        } else {
 
434
                pfs_master_timeout = 3600;
 
435
        }
 
436
        
 
437
        pfs_uid = getuid();
 
438
        pfs_gid = getgid();
 
439
 
 
440
        putenv((char *)"PARROT_ENABLED=TRUE");
 
441
 
 
442
        s = getenv("PARROT_BLOCK_SIZE");
 
443
        if(s) pfs_service_set_block_size(string_metric_parse(s));
 
444
 
 
445
        s = getenv("PARROT_MOUNT_FILE");
 
446
        if(s) pfs_resolve_file_config(s);
 
447
 
 
448
        s = getenv("PARROT_MOUNT_STRING");
 
449
        if(s) pfs_resolve_manual_config(s);
 
450
 
 
451
        s = getenv("PARROT_FORCE_STREAM");
 
452
        if(s) pfs_force_stream = 1;
 
453
 
 
454
        s = getenv("PARROT_FORCE_CACHE");
 
455
        if(s) pfs_force_cache = 1;
 
456
        
 
457
        s = getenv("PARROT_FOLLOW_SYMLINKS");
 
458
        if(s) pfs_follow_symlinks = atoi(s);
 
459
 
 
460
        s = getenv("PARROT_SESSION_CACHE");
 
461
        if(s) pfs_session_cache = 1;
 
462
 
 
463
        s = getenv("PARROT_HOST_NAME");
 
464
        if(s) pfs_false_uname = s;
 
465
 
 
466
        s = getenv("PARROT_UID");
 
467
        if(s) pfs_uid = atoi(s);
 
468
 
 
469
        s = getenv("PARROT_GID");
 
470
        if(s) pfs_gid = atoi(s);
 
471
 
 
472
        s = getenv("PARROT_TIMEOUT");
 
473
        if(s) pfs_master_timeout = string_time_parse(s);
 
474
 
 
475
        s = getenv("PARROT_GLITE_CCURL");
 
476
        if(s) pfs_ccurl = s;
 
477
 
 
478
        s = getenv("PARROT_FORCE_SYNC");
 
479
        if(s) pfs_force_sync = 1;
 
480
 
 
481
        s = getenv("PARROT_LDSO_PATH");
 
482
        if(s) pfs_ldso_path = s;
 
483
 
 
484
        s = getenv("PARROT_DEBUG_FLAGS");
 
485
        if(s) {
 
486
                char *x = xstrdup(s);
 
487
                int nargs;
 
488
                char **args;
 
489
                if(string_split(x,&nargs,&args)) {
 
490
                        for(int i=0;i<nargs;i++) {
 
491
                                debug_flags_set(args[i]);
 
492
                        }
 
493
                }
 
494
                free(x);
 
495
        }
 
496
 
 
497
        s = getenv("PARROT_CHIRP_AUTH");
 
498
        if(s) {
 
499
                char *x = xstrdup(s);
 
500
                int nargs;
 
501
                char **args;
 
502
                if(string_split(x,&nargs,&args)) {
 
503
                        for(int i=0;i<nargs;i++) {
 
504
                                auth_register_byname(args[i]);
 
505
                                chose_auth = 1;
 
506
                        }
 
507
                }
 
508
                free(x);
 
509
        }
 
510
 
 
511
        s = getenv("PARROT_USER_PASS");
 
512
        if(s) {
 
513
                char *x = xstrdup(s);
 
514
                int nargs;
 
515
                char **args;
 
516
                if(string_split(x,&nargs,&args)) {
 
517
                        pfs_password_cache = password_cache_init(args[0], args[1]);
 
518
                }
 
519
        }
 
520
 
 
521
        sprintf(pfs_temp_dir,"/tmp/parrot.%d",getuid());
 
522
 
 
523
        while((c=getopt(argc,argv,"+hA:a:b:B:c:Cd:DE:FfG:Hi:kKl:m:M:N:o:O:p:QR:sSt:T:U:u:vw:WYZ"))!=(char)-1) {
 
524
                switch(c) {
 
525
                case 'a':
 
526
                        if(!auth_register_byname(optarg)) {
 
527
                                fprintf(stderr,"unknown auth type: %s\n",optarg);
 
528
                                return 1;
 
529
                        }
 
530
                        chose_auth = 1;
 
531
                        break;
 
532
                case 'A':
 
533
                        chirp_acl_default(optarg);
 
534
                        break;
 
535
                case 'b':
 
536
                        pfs_service_set_block_size(string_metric_parse(optarg));
 
537
                        break;
 
538
                case 'B':
 
539
                        pfs_service_set_block_size(string_metric_parse(optarg));
 
540
                        break;
 
541
                case 'c':
 
542
                        pfs_write_rval = 1;
 
543
                        pfs_write_rval_file = optarg;
 
544
                        break;
 
545
                case 'C':
 
546
                        ftp_lite_data_channel_authentication = 1;
 
547
                        break;
 
548
                case 'd':
 
549
                        if(!debug_flags_set(optarg)) show_use(argv[0]);
 
550
                        break;
 
551
                case 'D':
 
552
                        pfs_enable_small_file_optimizations = 0;
 
553
                        break;
 
554
                case 'E':
 
555
                        pfs_ccurl = optarg;
 
556
                        break;
 
557
                case 'F':
 
558
                        pfs_force_cache = 1;
 
559
                        break;  
 
560
                case 'f':
 
561
                        pfs_follow_symlinks = 0;
 
562
                        break;
 
563
                case 'G':
 
564
                        pfs_gid = atoi(optarg);
 
565
                        break;
 
566
                case 'H':
 
567
                        pfs_use_helper = 0;
 
568
                        break;
 
569
                case 'i':
 
570
                        setenv(CHIRP_CLIENT_TICKETS, optarg, 1);
 
571
                        did_ticket = 1;
 
572
                        break;
 
573
                case 'k':
 
574
                        pfs_checksum_files = 0;
 
575
                        break;
 
576
                case 'K':
 
577
                        pfs_checksum_files = 1;
 
578
                        break;
 
579
                case 'l':
 
580
                        pfs_ldso_path = optarg;
 
581
                        break;
 
582
                case 'm':
 
583
                        pfs_resolve_file_config(optarg);
 
584
                        break;
 
585
                case 'M':
 
586
                        pfs_resolve_manual_config(optarg);
 
587
                        break;
 
588
                case 'N':
 
589
                        pfs_false_uname = optarg;
 
590
                        break;
 
591
                case 'o':
 
592
                        debug_config_file(optarg);
 
593
                        break;
 
594
                case 'O':
 
595
                        debug_config_file_size(string_metric_parse(optarg));
 
596
                        break;
 
597
                case 'p':
 
598
                        setenv("HTTP_PROXY",optarg,1);
 
599
                        break;
 
600
                case 'Q':
 
601
                        chirp_global_inhibit_catalog(1);
 
602
                        break;
 
603
                case 'R':
 
604
                        pfs_root_checksum = optarg;
 
605
                        pfs_checksum_files = 1;
 
606
                        break;
 
607
                case 's':
 
608
                        pfs_force_stream = 1;
 
609
                        break;
 
610
                case 'S':
 
611
                        pfs_force_cache = 1;
 
612
                        pfs_session_cache = 1;
 
613
                        break;
 
614
                case 't':
 
615
                        strcpy(pfs_temp_dir,optarg);
 
616
                        break;
 
617
                case 'T':
 
618
                        pfs_master_timeout = string_time_parse(optarg);
 
619
                        break;
 
620
                case 'U':
 
621
                        pfs_uid = atoi(optarg);
 
622
                        break;
 
623
                case 'u':
 
624
                        pfs_username = optarg;
 
625
                        break;
 
626
                case 'Y':
 
627
                        pfs_force_sync = 1;
 
628
                        break;
 
629
                case 'v':
 
630
                        show_version(argv[0]);
 
631
                        break;
 
632
                case 'w':
 
633
                        pfs_initial_working_directory = optarg;
 
634
                        break;
 
635
                case 'W':
 
636
                        pfs_syscall_totals32 = (int*) calloc(SYSCALL32_MAX,sizeof(int));
 
637
                        pfs_syscall_totals64 = (int*) calloc(SYSCALL64_MAX,sizeof(int));
 
638
                        break;
 
639
                case 'Z':
 
640
                        pfs_auto_gzip = 1;
 
641
                        break;
 
642
                default:
 
643
                        show_use(argv[0]);
 
644
                        break;
 
645
        }
 
646
        }
 
647
    cfs = &chirp_local_fs;
 
648
 
 
649
        if(optind>=argc) show_use(argv[0]);
 
650
 
 
651
        get_linux_version();
 
652
 
 
653
        pfs_file_cache = file_cache_init(pfs_temp_dir);
 
654
        if(!pfs_file_cache) fatal("couldn't setup cache in %s: %s\n",pfs_temp_dir,strerror(errno));
 
655
        file_cache_cleanup(pfs_file_cache);
 
656
 
 
657
        if(!did_ticket && getenv(CHIRP_CLIENT_TICKETS) == NULL) {
 
658
                /* populate a list with tickets in the current directory */
 
659
                int i;
 
660
                char **list;
 
661
                char *tickets = xstrdup("");
 
662
                sort_dir(".", &list, strcmp);
 
663
                for (i = 0; list[i]; i++) {
 
664
                        if (strncmp(list[i], "ticket.", strlen("ticket.")) == 0 && (strlen(list[i]) == (strlen("ticket.")+(MD5_DIGEST_LENGTH<<1)))) {
 
665
                                debug(D_CHIRP, "adding ticket %s", list[i]);
 
666
                                tickets = (char *) xxrealloc(tickets, strlen(tickets)+1+strlen(list[i])+1);
 
667
                if (*tickets != '\0') /* non-empty? */
 
668
                                        strcat(tickets, ",");
 
669
                                strcat(tickets, list[i]);
 
670
                        }
 
671
                }
 
672
                setenv(CHIRP_CLIENT_TICKETS, tickets, 1);
 
673
                free(tickets);
 
674
                sort_dir_free(list);
 
675
        }
 
676
 
 
677
        if(!chose_auth) auth_register_all();
 
678
 
 
679
        if(!pfs_channel_init(channel_size*1024*1024)) fatal("couldn't establish I/O channel");  
 
680
 
 
681
        if(pfs_use_helper) pfs_helper_init(argv[0]);
 
682
 
 
683
        pfs_poll_init();
 
684
 
 
685
        /*
 
686
        For reasons I don't understand yet, parrot gets very confused when
 
687
        it is the session leader.  This happens when it is run as the first
 
688
        process in a pty, for example in an xterm or when run from a server.
 
689
        So, when we are the session leader, disconnect from the terminal .
 
690
        This disables features such as line editing and job control, but
 
691
        prevents triggering some ugly bugs.
 
692
        */
 
693
 
 
694
        if(getsid(0)==getpid()) {
 
695
                ::ioctl(0,TIOCNOTTY,0);
 
696
        }
 
697
 
 
698
        if(pid==0) {
 
699
                pid = fork();
 
700
                if(pid>0) {
 
701
                        debug(D_PROCESS,"pid %d started",pid);
 
702
                } else if(pid==0) {
 
703
                        for(i=0;i<sysconf(_SC_OPEN_MAX);i++) {
 
704
                                if(i!=pfs_channel_fd()) close(i);
 
705
                        }
 
706
                        setpgrp();
 
707
                        tracer_prepare();
 
708
                        kill(getpid(),SIGSTOP);
 
709
                        getpid();
 
710
                        // This call is necessary to force the kernel to report the current heap
 
711
                        // size, so that Parrot can observe it in order to rewrite the following exec.
 
712
                        sbrk(4096);
 
713
                        execvp(argv[optind],&argv[optind]);
 
714
                        debug(D_NOTICE,"unable to execute %s: %s",argv[optind],strerror(errno));
 
715
                        if(pfs_write_rval) {
 
716
                                write_rval("noexec", 0);
 
717
                        }
 
718
                        _exit(1);
 
719
                } else {
 
720
                        debug(D_NOTICE,"unable to fork %s: %s",argv[optind],strerror(errno));
 
721
                        if(pfs_write_rval) {
 
722
                                write_rval("nofork", 0);
 
723
                        }
 
724
                        exit(1);
 
725
                }
 
726
        }
 
727
 
 
728
        CRITICAL_BEGIN
 
729
 
 
730
        root_pid = pid;
 
731
        debug(D_PROCESS,"attaching to pid %d",pid);
 
732
        p = pfs_process_create(pid,getpid(),getpid(),0,SIGCHLD);
 
733
        if(!p) {
 
734
                if(pfs_write_rval) {
 
735
                        write_rval("noattach", 0);
 
736
                }
 
737
                kill(pid,SIGKILL);
 
738
                fatal("unable to attach to pid %d: %s",pid,strerror(errno));
 
739
        }
 
740
 
 
741
        p->state = PFS_PROCESS_STATE_USER;
 
742
        strcpy(p->name,argv[optind]);
 
743
 
 
744
        while(pfs_process_count()>0) {
 
745
                while(1) {
 
746
                        int flags;
 
747
                        if(trace_this_pid!=-1) {
 
748
                                flags = WUNTRACED|__WALL;
 
749
                        } else {
 
750
                                flags = WUNTRACED|__WALL|WNOHANG;
 
751
                        }
 
752
                        pid = wait4(trace_this_pid,&status,flags,&usage);
 
753
                        if(pid>0) {
 
754
                                handle_event(pid,status,usage);
 
755
                        } else {
 
756
                                break;
 
757
                        }
 
758
                }
 
759
                if(pid==-1 && errno==ECHILD) break;
 
760
                if(pfs_process_count()>0) pfs_poll_sleep();
 
761
        }
 
762
 
 
763
        if(pfs_syscall_totals32) {
 
764
                printf("\nParrot System Call Summary:\n");
 
765
                printf("%lld syscalls\n",pfs_syscall_count);
 
766
                printf("%lld bytes read\n",pfs_read_count);
 
767
                printf("%lld bytes written\n",pfs_write_count);
 
768
 
 
769
                printf("\n32-bit System Calls:\n");
 
770
                for(i=0;i<SYSCALL32_MAX;i++) {
 
771
                        if(pfs_syscall_totals32[i]) {
 
772
                                printf("%-20s %d\n",tracer_syscall32_name(i),pfs_syscall_totals32[i]);
 
773
                        }
 
774
                }
 
775
 
 
776
                #ifdef CCTOOLS_CPU_X86_64
 
777
 
 
778
                printf("\n64-bit System Calls:\n");
 
779
                for(i=0;i<SYSCALL64_MAX;i++) {
 
780
                        if(pfs_syscall_totals64[i]) {
 
781
                                printf("%-20s %d\n",tracer_syscall64_name(i),pfs_syscall_totals64[i]);
 
782
                        }
 
783
                }
 
784
 
 
785
                #endif
 
786
        }
 
787
 
 
788
        if(WIFEXITED(root_exitstatus)) {
 
789
                status = WEXITSTATUS(root_exitstatus);
 
790
                debug(D_PROCESS,"%s exited normally with status %d",argv[optind],status);
 
791
                if(pfs_write_rval) {
 
792
                        write_rval("normal", status);
 
793
                }
 
794
                return status;
 
795
        } else {
 
796
                signum = WTERMSIG(root_exitstatus);
 
797
                debug(D_PROCESS,"%s exited abnormally with signal %d (%s)",argv[optind],signum,string_signal(signum));
 
798
                if(pfs_write_rval) {
 
799
                        write_rval("abnormal", signum);
 
800
                }
 
801
                return 1;
 
802
        }
 
803
}
 
804