/* cssh - cluster secure shell Copyright (C) 2015-2021 Andreas Baumann This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "progressbar.h" #include #include #include #include #include int create_progressbar( cssh_progressbar_t *progressbar, uint64_t min_value, uint64_t max_value, size_t size, const char *label_fmt, ... ) { progressbar->min_value = min_value; progressbar->max_value = max_value; va_list va; va_start( va, label_fmt ); progressbar->label = (char *)malloc( size ); if( progressbar->label == NULL ) { return -1; } (void)vsnprintf( progressbar->label, size, label_fmt, va ); progressbar->value = progressbar->min_value; progressbar->total_steps = 0; progressbar->current_step = 0; progressbar->buf = NULL; va_end( va ); return 0; } void free_progressbar( cssh_progressbar_t *progressbar ) { free( progressbar->buf ); progressbar->buf = NULL; free( progressbar->label ); progressbar->label = NULL; progressbar->value = progressbar->min_value; progressbar->total_steps = 0; progressbar->current_step = 0; } void set_value_of_progressbar( cssh_progressbar_t *progressbar, uint64_t value ) { progressbar->value = value; } static int compute_progressbar_steps( cssh_progressbar_t *progressbar ) { cssh_progressbar_pool_t *pool = progressbar->pool; if( strlen( progressbar->label ) + 2 < pool->cols ) { progressbar->total_steps = pool->cols - strlen( progressbar->label ) - 2; } else { progressbar->total_steps = 0; } progressbar->buf = (char *)malloc( progressbar->total_steps + 1 ); if( progressbar->buf == NULL ) { return -1; } return 0; } void redraw_progressbar( cssh_progressbar_t *progressbar ) { if( progressbar->total_steps == 0 ) { (void)compute_progressbar_steps( progressbar ); } unsigned int new_step = progressbar->value * ( (double)progressbar->total_steps / ( progressbar->max_value - progressbar->min_value ) ); if( new_step == progressbar->current_step ) { printf( "\n" ); return; } progressbar->buf[progressbar->total_steps] = '\0'; memset( progressbar->buf, (int)' ', progressbar->total_steps ); memset( progressbar->buf, (int)'#', progressbar->current_step ); fprintf( stderr, "%s [%s]\n", progressbar->label, progressbar->buf ); progressbar->current_step = new_step; } int create_progressbar_pool( cssh_progressbar_pool_t *pool, size_t initial_size ) { pool->N = 0; pool->capacity = initial_size; pool->progressbar = (cssh_progressbar_t **)malloc( pool->capacity * sizeof( cssh_progressbar_t * ) ); if( pool->progressbar == NULL ) { return -1; } pool->termbuf = (char *)malloc( TERMBUF_SIZE ); if( pool->termbuf == NULL ) { free( pool->progressbar ); return -1; } char *termtype = getenv( "TERM" ); if( termtype == NULL ) { pool->cols = DEFAULT_COLS; } int rc = tgetent( pool->termbuf, termtype ); if( rc < 0 ) { pool->cols = DEFAULT_COLS; } else { pool->cols = tgetnum( "co" ) - 2; } return 0; } void free_progressbar_pool( cssh_progressbar_pool_t *pool ) { for( size_t i = 0; i < pool->N; i++ ) { free_progressbar( pool->progressbar[i] ); } free( pool->progressbar ); free( pool->termbuf ); } int append_progressbar_to_pool( cssh_progressbar_pool_t *pool, cssh_progressbar_t *progressbar ) { if( pool->N + 1 > pool->capacity ) { return -1; } pool->progressbar[pool->N] = progressbar; pool->N++; progressbar->pool = pool; return 0; } int remove_progressbar_from_pool( cssh_progressbar_pool_t *pool, cssh_progressbar_t *progressbar ) { if( pool->N == 0 ) { return -1; } for( size_t i = 0; i < pool->N; i++ ) { if( pool->progressbar[i] == progressbar ) { for( size_t j = i; j < pool->N - 1; j++ ) { pool->progressbar[j] = pool->progressbar[j+1]; } pool->N--; pool->progressbar[pool->N] = NULL; return 0; } } return -1; } void redraw_progressbars( cssh_progressbar_pool_t *pool ) { for( size_t i = 0; i < pool->N; i++ ) { redraw_progressbar( pool->progressbar[i] ); } printf( "\33[%zuF\n", pool->N + 1 ); }