/[axel]/trunk/text.c
ViewVC logotype

Contents of /trunk/text.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 47 - (show annotations) (download)
Mon Sep 15 12:52:45 2008 UTC (4 years, 8 months ago) by phihag-guest
File MIME type: text/plain
File size: 13655 byte(s)
+ Option to set the HTTP user agent (#311073)
+ Documentation for -H

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

  ViewVC Help
Powered by ViewVC 1.1.5