/[axel]/tags/2.0/text.c
ViewVC logotype

Contents of /tags/2.0/text.c

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.5