/[axel]/branches/2.x/text.c
ViewVC logotype

Contents of /branches/2.x/text.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 25 - (show annotations) (download)
Wed Jan 30 11:38:43 2008 UTC (5 years, 3 months ago) by appaji-guest
Original Path: trunk/text.c
File MIME type: text/plain
File size: 13013 byte(s)
Initial large file support, thanks David Turnbull
1 /********************************************************************\
2 * Axel -- A lighter download accelerator for Linux and other Unices. *
3 * *
4 * Copyright 2001 Wilmer van der Gaast *
5 \********************************************************************/
6
7 /* Text interface */
8
9 /*
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License with
21 the Debian GNU/Linux distribution in file /usr/doc/copyright/GPL;
22 if not, write to the Free Software Foundation, Inc., 59 Temple Place,
23 Suite 330, Boston, MA 02111-1307 USA
24 */
25
26 #include "axel.h"
27
28 static void stop( int signal );
29 static char *size_human( long long int value );
30 static char *time_human( int value );
31 static void print_commas( long long int bytes_done );
32 static void print_alternate_output( axel_t *axel );
33 static void print_help();
34 static void print_version();
35 static void print_messages( axel_t *axel );
36
37 int run = 1;
38
39 #ifdef NOGETOPTLONG
40 #define getopt_long( a, b, c, d, e ) getopt( a, b, c )
41 #else
42 static struct option axel_options[] =
43 {
44 /* name has_arg flag val */
45 { "max-speed", 1, NULL, 's' },
46 { "num-connections", 1, NULL, 'n' },
47 { "output", 1, NULL, 'o' },
48 { "search", 2, NULL, 'S' },
49 { "no-proxy", 0, NULL, 'N' },
50 { "quiet", 0, NULL, 'q' },
51 { "verbose", 0, NULL, 'v' },
52 { "help", 0, NULL, 'h' },
53 { "version", 0, NULL, 'V' },
54 { "alternate", 0, NULL, 'a' },
55 { NULL, 0, NULL, 0 }
56 };
57 #endif
58
59 /* For returning string values from functions */
60 static char string[MAX_STRING];
61
62
63 int main( int argc, char *argv[] )
64 {
65 char fn[MAX_STRING] = "";
66 int do_search = 0;
67 search_t *search;
68 conf_t conf[1];
69 axel_t *axel;
70 int i, j;
71 char *s;
72
73 #ifdef I18N
74 setlocale( LC_ALL, "" );
75 bindtextdomain( PACKAGE, LOCALE );
76 textdomain( PACKAGE );
77 #endif
78
79 if( !conf_init( conf ) )
80 {
81 return( 1 );
82 }
83
84 opterr = 0;
85
86 j = -1;
87 while( 1 )
88 {
89 int option;
90
91 option = getopt_long( argc, argv, "s:n:o:S::NqvhHVa", axel_options, NULL );
92 if( option == -1 )
93 break;
94
95 switch( option )
96 {
97 case 's':
98 if( !sscanf( optarg, "%i", &conf->max_speed ) )
99 {
100 print_help();
101 return( 1 );
102 }
103 break;
104 case 'n':
105 if( !sscanf( optarg, "%i", &conf->num_connections ) )
106 {
107 print_help();
108 return( 1 );
109 }
110 break;
111 case 'o':
112 strncpy( fn, optarg, MAX_STRING );
113 break;
114 case 'S':
115 do_search = 1;
116 if( optarg != NULL )
117 if( !sscanf( optarg, "%i", &conf->search_top ) )
118 {
119 print_help();
120 return( 1 );
121 }
122 break;
123 case 'a':
124 conf->alternate_output = 1;
125 break;
126 case 'N':
127 *conf->http_proxy = 0;
128 break;
129 case 'h':
130 print_help();
131 return( 0 );
132 case 'v':
133 if( j == -1 )
134 j = 1;
135 else
136 j ++;
137 break;
138 case 'V':
139 print_version();
140 return( 0 );
141 case 'q':
142 close( 1 );
143 conf->verbose = -1;
144 if( open( "/dev/null", O_WRONLY ) != 1 )
145 {
146 fprintf( stderr, _("Can't redirect stdout to /dev/null.\n") );
147 return( 1 );
148 }
149 break;
150 default:
151 print_help();
152 return( 1 );
153 }
154 }
155
156 if( j > -1 )
157 conf->verbose = j;
158
159 if( argc - optind == 0 )
160 {
161 print_help();
162 return( 1 );
163 }
164 else if( strcmp( argv[optind], "-" ) == 0 )
165 {
166 s = malloc( MAX_STRING );
167 scanf( "%1024[^\n]s", s );
168 }
169 else
170 {
171 s = argv[optind];
172 if( strlen( s ) > MAX_STRING )
173 {
174 fprintf( stderr, _("Can't handle URLs of length over %d\n" ), MAX_STRING );
175 return( 1 );
176 }
177 }
178
179 printf( _("Initializing download: %s\n"), s );
180 if( do_search )
181 {
182 search = malloc( sizeof( search_t ) * ( conf->search_amount + 1 ) );
183 memset( search, 0, sizeof( search_t ) * ( conf->search_amount + 1 ) );
184 search[0].conf = conf;
185 if( conf->verbose )
186 printf( _("Doing search...\n") );
187 i = search_makelist( search, s );
188 if( i < 0 )
189 {
190 fprintf( stderr, _("File not found\n" ) );
191 return( 1 );
192 }
193 if( conf->verbose )
194 printf( _("Testing speeds, this can take a while...\n") );
195 j = search_getspeeds( search, i );
196 search_sortlist( search, i );
197 if( conf->verbose )
198 {
199 printf( _("%i usable servers found, will use these URLs:\n"), j );
200 j = min( j, conf->search_top );
201 printf( "%-60s %15s\n", "URL", "Speed" );
202 for( i = 0; i < j; i ++ )
203 printf( "%-70.70s %5i\n", search[i].url, search[i].speed );
204 printf( "\n" );
205 }
206 axel = axel_new( conf, j, search );
207 free( search );
208 if( axel->ready == -1 )
209 {
210 print_messages( axel );
211 axel_close( axel );
212 return( 1 );
213 }
214 }
215 else if( argc - optind == 1 )
216 {
217 axel = axel_new( conf, 0, s );
218 if( axel->ready == -1 )
219 {
220 print_messages( axel );
221 axel_close( axel );
222 return( 1 );
223 }
224 }
225 else
226 {
227 search = malloc( sizeof( search_t ) * ( argc - optind ) );
228 memset( search, 0, sizeof( search_t ) * ( argc - optind ) );
229 for( i = 0; i < ( argc - optind ); i ++ )
230 strncpy( search[i].url, argv[optind+i], MAX_STRING );
231 axel = axel_new( conf, argc - optind, search );
232 free( search );
233 if( axel->ready == -1 )
234 {
235 print_messages( axel );
236 axel_close( axel );
237 return( 1 );
238 }
239 }
240 print_messages( axel );
241 if( s != argv[optind] )
242 {
243 free( s );
244 }
245
246 if( *fn )
247 {
248 struct stat buf;
249
250 if( stat( fn, &buf ) == 0 )
251 {
252 if( S_ISDIR( buf.st_mode ) )
253 {
254 strncat( fn, "/", MAX_STRING );
255 strncat( fn, axel->filename, MAX_STRING );
256 }
257 }
258 sprintf( string, "%s.st", fn );
259 if( access( fn, F_OK ) == 0 ) if( access( string, F_OK ) != 0 )
260 {
261 fprintf( stderr, _("No state file, cannot resume!\n") );
262 return( 1 );
263 }
264 if( access( string, F_OK ) == 0 ) if( access( fn, F_OK ) != 0 )
265 {
266 printf( _("State file found, but no downloaded data. Starting from scratch.\n" ) );
267 unlink( string );
268 }
269 strcpy( axel->filename, fn );
270 }
271 else
272 {
273 /* Local file existence check */
274 i = 0;
275 s = axel->filename + strlen( axel->filename );
276 while( 1 )
277 {
278 sprintf( string, "%s.st", axel->filename );
279 if( access( axel->filename, F_OK ) == 0 )
280 {
281 if( axel->conn[0].supported )
282 {
283 if( access( string, F_OK ) == 0 )
284 break;
285 }
286 }
287 else
288 {
289 if( access( string, F_OK ) )
290 break;
291 }
292 sprintf( s, ".%i", i );
293 i ++;
294 }
295 }
296
297 if( !axel_open( axel ) )
298 {
299 print_messages( axel );
300 return( 1 );
301 }
302 print_messages( axel );
303 axel_start( axel );
304 print_messages( axel );
305
306 if( conf->alternate_output )
307 {
308 putchar('\n');
309 }
310 else
311 {
312 if( axel->bytes_done > 0 ) /* Print first dots if resuming */
313 {
314 putchar( '\n' );
315 print_commas( axel->bytes_done );
316 }
317 }
318 axel->start_byte = axel->bytes_done;
319
320 /* Install save_state signal handler for resuming support */
321 signal( SIGINT, stop );
322 signal( SIGTERM, stop );
323
324 while( !axel->ready && run )
325 {
326 long long int prev, done;
327
328 prev = axel->bytes_done;
329 axel_do( axel );
330
331 if( conf->alternate_output )
332 {
333 if( !axel->message && prev != axel->bytes_done )
334 print_alternate_output( axel );
335 }
336 else
337 {
338 /* The infamous wget-like 'interface'.. ;) */
339 done = ( axel->bytes_done / 1024 ) - ( prev / 1024 );
340 if( done && conf->verbose > -1 )
341 {
342 for( i = 0; i < done; i ++ )
343 {
344 i += ( prev / 1024 );
345 if( ( i % 50 ) == 0 )
346 {
347 if( prev >= 1024 )
348 printf( " [%6.1fKB/s]", (double) axel->bytes_per_second / 1024 );
349 if( axel->size < 10240000 )
350 printf( "\n[%3lld%%] ", min( 100, 102400 * i / axel->size ) );
351 else
352 printf( "\n[%3lld%%] ", min( 100, i / ( axel->size / 102400 ) ) );
353 }
354 else if( ( i % 10 ) == 0 )
355 {
356 putchar( ' ' );
357 }
358 putchar( '.' );
359 i -= ( prev / 1024 );
360 }
361 fflush( stdout );
362 }
363 }
364
365 if( axel->message )
366 {
367 if(conf->alternate_output==1)
368 {
369 /* clreol-simulation */
370 putchar( '\r' );
371 for( i = 0; i < 79; i++ ) /* linewidth known? */
372 putchar( ' ' );
373 putchar( '\r' );
374 }
375 else
376 {
377 putchar( '\n' );
378 }
379 print_messages( axel );
380 if( !axel->ready )
381 {
382 if(conf->alternate_output!=1)
383 print_commas( axel->bytes_done );
384 else
385 print_alternate_output(axel);
386 }
387 }
388 else if( axel->ready )
389 {
390 putchar( '\n' );
391 }
392 }
393
394 strcpy( string + MAX_STRING / 2,
395 size_human( axel->bytes_done - axel->start_byte ) );
396
397 printf( _("\nDownloaded %s in %s. (%.2f KB/s)\n"),
398 string + MAX_STRING / 2,
399 time_human( gettime() - axel->start_time ),
400 (double) axel->bytes_per_second / 1024 );
401
402 i = axel->ready ? 0 : 2;
403
404 axel_close( axel );
405
406 return( i );
407 }
408
409 /* SIGINT/SIGTERM handler */
410 void stop( int signal )
411 {
412 run = 0;
413 }
414
415 /* Convert a number of bytes to a human-readable form */
416 char *size_human( long long int value )
417 {
418 if( value == 1 )
419 sprintf( string, _("%lld byte"), value );
420 else if( value < 1024 )
421 sprintf( string, _("%lld bytes"), value );
422 else if( value < 10485760 )
423 sprintf( string, _("%.1f kilobytes"), (float) value / 1024 );
424 else
425 sprintf( string, _("%.1f megabytes"), (float) value / 1048576 );
426
427 return( string );
428 }
429
430 /* Convert a number of seconds to a human-readable form */
431 char *time_human( int value )
432 {
433 if( value == 1 )
434 sprintf( string, _("%i second"), value );
435 else if( value < 60 )
436 sprintf( string, _("%i seconds"), value );
437 else if( value < 3600 )
438 sprintf( string, _("%i:%02i seconds"), value / 60, value % 60 );
439 else
440 sprintf( string, _("%i:%02i:%02i seconds"), value / 3600, ( value / 60 ) % 60, value % 60 );
441
442 return( string );
443 }
444
445 /* Part of the infamous wget-like interface. Just put it in a function
446 because I need it quite often.. */
447 void print_commas( long long int bytes_done )
448 {
449 int i, j;
450
451 printf( " " );
452 j = ( bytes_done / 1024 ) % 50;
453 if( j == 0 ) j = 50;
454 for( i = 0; i < j; i ++ )
455 {
456 if( ( i % 10 ) == 0 )
457 putchar( ' ' );
458 putchar( ',' );
459 }
460 fflush( stdout );
461 }
462
463 static void print_alternate_output(axel_t *axel)
464 {
465 long long int done=axel->bytes_done;
466 long long int total=axel->size;
467 int i,j=0;
468 double now = gettime();
469
470 printf("\r[%3ld%%] [", min(100,(long)(done*100./total+.5) ) );
471
472 for(i=0;i<axel->conf->num_connections;i++)
473 {
474 for(;j<((double)axel->conn[i].currentbyte/(total+1)*50)-1;j++)
475 putchar('.');
476
477 if(axel->conn[i].currentbyte<axel->conn[i].lastbyte)
478 {
479 if(now <= axel->conn[i].last_transfer + axel->conf->connection_timeout/2 )
480 putchar(i+'0');
481 else
482 putchar('#');
483 } else
484 putchar('.');
485
486 j++;
487
488 for(;j<((double)axel->conn[i].lastbyte/(total+1)*50);j++)
489 putchar(' ');
490 }
491
492 printf( "] [%6.1fKB/s]", (double) axel->bytes_per_second / 1024 );
493
494 if(done<total)
495 {
496 int seconds,minutes,hours,days;
497 seconds=axel->finish_time - now;
498 minutes=seconds/60;seconds-=minutes*60;
499 hours=minutes/60;minutes-=hours*60;
500 days=hours/24;hours-=days*24;
501 if(days)
502 printf(" [%2dd%2d]",days,hours);
503 else if(hours)
504 printf(" [%2dh%02d]",hours,minutes);
505 else
506 printf(" [%02d:%02d]",minutes,seconds);
507 }
508
509 fflush( stdout );
510 }
511
512 void print_help()
513 {
514 #ifdef NOGETOPTLONG
515 printf( _("Usage: axel [options] url1 [url2] [url...]\n"
516 "\n"
517 "-s x\tSpecify maximum speed (bytes per second)\n"
518 "-n x\tSpecify maximum number of connections\n"
519 "-o f\tSpecify local output file\n"
520 "-S [x]\tSearch for mirrors and download from x servers\n"
521 "-N\tJust don't use any proxy server\n"
522 "-q\tLeave stdout alone\n"
523 "-v\tMore status information\n"
524 "-a\tAlternate progress indicator\n"
525 "-h\tThis information\n"
526 "-V\tVersion information\n"
527 "\n"
528 "Visit http://axel.alioth.debian.org/ to report bugs\n") );
529 #else
530 printf( _("Usage: axel [options] url1 [url2] [url...]\n"
531 "\n"
532 "--max-speed=x\t\t-s x\tSpecify maximum speed (bytes per second)\n"
533 "--num-connections=x\t-n x\tSpecify maximum number of connections\n"
534 "--output=f\t\t-o f\tSpecify local output file\n"
535 "--search[=x]\t\t-S [x]\tSearch for mirrors and download from x servers\n"
536 "--no-proxy\t\t-N\tJust don't use any proxy server\n"
537 "--quiet\t\t\t-q\tLeave stdout alone\n"
538 "--verbose\t\t-v\tMore status information\n"
539 "--alternate\t\t-a\tAlternate progress indicator\n"
540 "--help\t\t\t-h\tThis information\n"
541 "--version\t\t-V\tVersion information\n"
542 "\n"
543 "Visit http://axel.alioth.debian.org/ to report bugs\n") );
544 #endif
545 }
546
547 void print_version()
548 {
549 printf( _("Axel version %s (%s)\n"), AXEL_VERSION_STRING, ARCH );
550 printf( "\nCopyright 2001-2002 Wilmer van der Gaast.\n" );
551 }
552
553 /* Print any message in the axel structure */
554 void print_messages( axel_t *axel )
555 {
556 message_t *m;
557
558 while( axel->message )
559 {
560 printf( "%s\n", axel->message->text );
561 m = axel->message;
562 axel->message = axel->message->next;
563 free( m );
564 }
565 }

  ViewVC Help
Powered by ViewVC 1.1.5