diff --git a/cmdgen.c b/cmdgen.c index d48b3166..12d34065 100644 --- a/cmdgen.c +++ b/cmdgen.c @@ -16,8 +16,36 @@ #include "sshkeygen.h" #include "mpint.h" -FILE *progress_fp = NULL; +static FILE *progress_fp = NULL; +static bool linear_progress_phase; +static unsigned last_progress_col; +static ProgressPhase cmdgen_progress_add_linear( + ProgressReceiver *prog, double c) +{ + ProgressPhase ph = { .n = 0 }; + return ph; +} + +static ProgressPhase cmdgen_progress_add_probabilistic( + ProgressReceiver *prog, double c, double p) +{ + ProgressPhase ph = { .n = 1 }; + return ph; +} + +static void cmdgen_progress_start_phase(ProgressReceiver *prog, + ProgressPhase p) +{ + linear_progress_phase = (p.n == 0); + last_progress_col = 0; +} +static void cmdgen_progress_report(ProgressReceiver *prog, double p) +{ + unsigned new_col = p * 64 + 0.5; + for (; last_progress_col < new_col; last_progress_col++) + fputc('+', progress_fp); +} static void cmdgen_progress_report_attempt(ProgressReceiver *prog) { if (progress_fp) { @@ -27,6 +55,8 @@ static void cmdgen_progress_report_attempt(ProgressReceiver *prog) } static void cmdgen_progress_report_phase_complete(ProgressReceiver *prog) { + if (linear_progress_phase) + cmdgen_progress_report(prog, 1.0); if (progress_fp) { fputc('\n', progress_fp); fflush(progress_fp); @@ -34,9 +64,11 @@ static void cmdgen_progress_report_phase_complete(ProgressReceiver *prog) } static const ProgressReceiverVtable cmdgen_progress_vt = { - null_progress_add_probabilistic, + cmdgen_progress_add_linear, + cmdgen_progress_add_probabilistic, null_progress_ready, - null_progress_start_phase, + cmdgen_progress_start_phase, + cmdgen_progress_report, cmdgen_progress_report_attempt, cmdgen_progress_report_phase_complete, }; diff --git a/sshkeygen.h b/sshkeygen.h index f8f3159f..a965d3a6 100644 --- a/sshkeygen.h +++ b/sshkeygen.h @@ -180,15 +180,20 @@ struct ProgressReceiver { }; struct ProgressReceiverVtable { + ProgressPhase (*add_linear)(ProgressReceiver *prog, double overall_cost); ProgressPhase (*add_probabilistic)(ProgressReceiver *prog, double cost_per_attempt, double attempt_probability); void (*ready)(ProgressReceiver *prog); void (*start_phase)(ProgressReceiver *prog, ProgressPhase phase); + void (*report)(ProgressReceiver *prog, double progress); void (*report_attempt)(ProgressReceiver *prog); void (*report_phase_complete)(ProgressReceiver *prog); }; +static inline ProgressPhase progress_add_linear(ProgressReceiver *prog, + double c) +{ return prog->vt->add_linear(prog, c); } static inline ProgressPhase progress_add_probabilistic(ProgressReceiver *prog, double c, double p) { return prog->vt->add_probabilistic(prog, c, p); } @@ -197,15 +202,20 @@ static inline void progress_ready(ProgressReceiver *prog) static inline void progress_start_phase( ProgressReceiver *prog, ProgressPhase phase) { prog->vt->start_phase(prog, phase); } +static inline void progress_report(ProgressReceiver *prog, double progress) +{ prog->vt->report(prog, progress); } static inline void progress_report_attempt(ProgressReceiver *prog) { prog->vt->report_attempt(prog); } static inline void progress_report_phase_complete(ProgressReceiver *prog) { prog->vt->report_phase_complete(prog); } +ProgressPhase null_progress_add_linear( + ProgressReceiver *prog, double c); ProgressPhase null_progress_add_probabilistic( ProgressReceiver *prog, double c, double p); void null_progress_ready(ProgressReceiver *prog); void null_progress_start_phase(ProgressReceiver *prog, ProgressPhase phase); +void null_progress_report(ProgressReceiver *prog, double progress); void null_progress_report_attempt(ProgressReceiver *prog); void null_progress_report_phase_complete(ProgressReceiver *prog); extern const ProgressReceiverVtable null_progress_vt; diff --git a/sshprime.c b/sshprime.c index 0ee435e9..4431204c 100644 --- a/sshprime.c +++ b/sshprime.c @@ -114,19 +114,25 @@ const PrimeGenerationPolicy primegen_probabilistic = { * Reusable null implementation of the progress-reporting API. */ -ProgressPhase null_progress_add_probabilistic( - ProgressReceiver *prog, double c, double p) { +static inline ProgressPhase null_progress_add(void) { ProgressPhase ph = { .n = 0 }; return ph; } +ProgressPhase null_progress_add_linear( + ProgressReceiver *prog, double c) { return null_progress_add(); } +ProgressPhase null_progress_add_probabilistic( + ProgressReceiver *prog, double c, double p) { return null_progress_add(); } void null_progress_ready(ProgressReceiver *prog) {} void null_progress_start_phase(ProgressReceiver *prog, ProgressPhase phase) {} +void null_progress_report(ProgressReceiver *prog, double progress) {} void null_progress_report_attempt(ProgressReceiver *prog) {} void null_progress_report_phase_complete(ProgressReceiver *prog) {} const ProgressReceiverVtable null_progress_vt = { + null_progress_add_linear, null_progress_add_probabilistic, null_progress_ready, null_progress_start_phase, + null_progress_report, null_progress_report_attempt, null_progress_report_phase_complete, }; diff --git a/windows/winpgen.c b/windows/winpgen.c index 435500a6..dc901ccd 100644 --- a/windows/winpgen.c +++ b/windows/winpgen.c @@ -68,6 +68,7 @@ void nonfatal(const char *fmt, ...) struct progressphase { double startpoint, total; + /* For exponential phases */ double exp_probability, exp_current_value; }; @@ -81,6 +82,19 @@ struct progress { ProgressReceiver rec; }; +static ProgressPhase win_progress_add_linear( + ProgressReceiver *prog, double overall_cost) { + struct progress *p = container_of(prog, struct progress, rec); + + assert(p->nphases < MAXPHASE); + int phase = p->nphases++; + + p->phases[phase].total = overall_cost; + + ProgressPhase ph = { .n = phase }; + return ph; +} + static ProgressPhase win_progress_add_probabilistic( ProgressReceiver *prog, double cost_per_attempt, double probability) { struct progress *p = container_of(prog, struct progress, rec); @@ -133,6 +147,13 @@ static void win_progress_update(struct progress *p, double phasepos) SendMessage(p->progbar, PBM_SETPOS, (WPARAM)position, 0); } +static void win_progress_report(ProgressReceiver *prog, double progress) +{ + struct progress *p = container_of(prog, struct progress, rec); + + win_progress_update(p, progress); +} + static void win_progress_report_attempt(ProgressReceiver *prog) { struct progress *p = container_of(prog, struct progress, rec); @@ -149,9 +170,11 @@ static void win_progress_report_phase_complete(ProgressReceiver *prog) } static const ProgressReceiverVtable win_progress_vt = { + win_progress_add_linear, win_progress_add_probabilistic, win_progress_ready, win_progress_start_phase, + win_progress_report, win_progress_report_attempt, win_progress_report_phase_complete, };