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

Contents of /trunk/text.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 27 - (hide annotations) (download)
Thu Apr 3 11:01:31 2008 UTC (5 years, 2 months ago) by appaji-guest
File MIME type: text/plain
File size: 13253 byte(s)
Custom header support, thanks Eli Yukelzon
1 appaji-guest 2 /********************************************************************\
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 appaji-guest 25 static char *size_human( long long int value );
30 appaji-guest 2 static char *time_human( int value );
31 appaji-guest 25 static void print_commas( long long int bytes_done );
32 appaji-guest 2 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 appaji-guest 27 { "header", 1, NULL, 'H' },
56 appaji-guest 2 { 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 appaji-guest 27 int i, j, cur_head = 0;
72 appaji-guest 2 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 appaji-guest 27 option = getopt_long( argc, argv, "s:n:o:S::NqvhHVaH:", axel_options, NULL );
93 appaji-guest 2 if( option == -1 )
94     break;
95    
96     switch( option )
97     {
98 appaji-guest 27 case 'H':
99     strncpy( conf->add_header[cur_head++], optarg, MAX_STRING );
100     break;
101 appaji-guest 2 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 appaji-guest 27 conf->add_header_count = cur_head;
160 appaji-guest 2 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 appaji-guest 7 scanf( "%1024[^\n]s", s );
172 appaji-guest 2 }
173     else
174     {
175     s = argv[optind];
176 appaji-guest 7 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 appaji-guest 2 }
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 appaji-guest 25 long long int prev, done;
331 appaji-guest 2
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 appaji-guest 25 printf( "\n[%3lld%%] ", min( 100, 102400 * i / axel->size ) );
355 appaji-guest 2 else
356 appaji-guest 25 printf( "\n[%3lld%%] ", min( 100, i / ( axel->size / 102400 ) ) );
357 appaji-guest 2 }
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 appaji-guest 25 char *size_human( long long int value )
421 appaji-guest 2 {
422     if( value == 1 )
423 appaji-guest 25 sprintf( string, _("%lld byte"), value );
424 appaji-guest 2 else if( value < 1024 )
425 appaji-guest 25 sprintf( string, _("%lld bytes"), value );
426 appaji-guest 2 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 appaji-guest 25 void print_commas( long long int bytes_done )
452 appaji-guest 2 {
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 appaji-guest 25 long long int done=axel->bytes_done;
470     long long int total=axel->size;
471 appaji-guest 2 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     printf( "] [%6.1fKB/s]", (double) axel->bytes_per_second / 1024 );
497    
498     if(done<total)
499     {
500     int seconds,minutes,hours,days;
501     seconds=axel->finish_time - now;
502     minutes=seconds/60;seconds-=minutes*60;
503     hours=minutes/60;minutes-=hours*60;
504     days=hours/24;hours-=days*24;
505     if(days)
506     printf(" [%2dd%2d]",days,hours);
507     else if(hours)
508     printf(" [%2dh%02d]",hours,minutes);
509     else
510     printf(" [%02d:%02d]",minutes,seconds);
511     }
512    
513     fflush( stdout );
514     }
515    
516     void print_help()
517     {
518     #ifdef NOGETOPTLONG
519     printf( _("Usage: axel [options] url1 [url2] [url...]\n"
520     "\n"
521     "-s x\tSpecify maximum speed (bytes per second)\n"
522     "-n x\tSpecify maximum number of connections\n"
523     "-o f\tSpecify local output file\n"
524     "-S [x]\tSearch for mirrors and download from x servers\n"
525 appaji-guest 27 "-H x\tAdd header string\n"
526 appaji-guest 2 "-N\tJust don't use any proxy server\n"
527     "-q\tLeave stdout alone\n"
528     "-v\tMore status information\n"
529     "-a\tAlternate progress indicator\n"
530     "-h\tThis information\n"
531     "-V\tVersion information\n"
532     "\n"
533 appaji-guest 20 "Visit http://axel.alioth.debian.org/ to report bugs\n") );
534 appaji-guest 2 #else
535     printf( _("Usage: axel [options] url1 [url2] [url...]\n"
536     "\n"
537     "--max-speed=x\t\t-s x\tSpecify maximum speed (bytes per second)\n"
538     "--num-connections=x\t-n x\tSpecify maximum number of connections\n"
539     "--output=f\t\t-o f\tSpecify local output file\n"
540     "--search[=x]\t\t-S [x]\tSearch for mirrors and download from x servers\n"
541 appaji-guest 27 "--header=x\t\t-H x\tAdd header string\n"
542 appaji-guest 2 "--no-proxy\t\t-N\tJust don't use any proxy server\n"
543     "--quiet\t\t\t-q\tLeave stdout alone\n"
544     "--verbose\t\t-v\tMore status information\n"
545     "--alternate\t\t-a\tAlternate progress indicator\n"
546     "--help\t\t\t-h\tThis information\n"
547     "--version\t\t-V\tVersion information\n"
548     "\n"
549 appaji-guest 20 "Visit http://axel.alioth.debian.org/ to report bugs\n") );
550 appaji-guest 2 #endif
551     }
552    
553     void print_version()
554     {
555     printf( _("Axel version %s (%s)\n"), AXEL_VERSION_STRING, ARCH );
556     printf( "\nCopyright 2001-2002 Wilmer van der Gaast.\n" );
557     }
558    
559     /* Print any message in the axel structure */
560     void print_messages( axel_t *axel )
561     {
562     message_t *m;
563    
564     while( axel->message )
565     {
566     printf( "%s\n", axel->message->text );
567     m = axel->message;
568     axel->message = axel->message->next;
569     free( m );
570     }
571     }

  ViewVC Help
Powered by ViewVC 1.1.5