Kaikki oikeudet pidätetään. Tässä versiossa ressusta on uusi yksinkertaisempi keskiarvoon perustuva tapa luokitella ketjut laskettaviin ja ei laskettaviin. Lisäksi –sample kytkimeen on lisätty status rivi, joka kertoo tällä hetkellä kirjoitettavan 1MB blokin, generaattorin nopeuden, tämän hetkisen kellonajan, jäljellä olevan ajoajan ja valmistumisajan. Lisäksi ohjelmaan on lisätty “naapureiden” ja muiden kirjainmerkistöjä.
Edit: lisätty kappaleita postin loppuun, ennen kokonaista sorsaa. Endedit.
Aloitetaan tärkeimmästä, eli varsinaisesta generaattorista: Ressu_clockbyte() antaa generaattorille kellojonon, josta satunnaisuus luodaan.
static unsigned char ressu_clockbyte() /* JariK 2013 */
{
struct timeval tv;
gettimeofday(&tv, NULL);
return(tv.tv_usec & 0xff);
}
Seuraavana ressun ydin ressu_genbytes_single(), joka luo varsinnaisen satunnaisbittipuskurin: Rutiinin nimi on muuten vaihdettu _fast-loppuisesta _single-loppuiseen fast ja single toimintojen selventämiseksi.
Satunnaisbitit luodaan kahdessa vaiheessa, ensimmäisessä xorataan koko puskuri kellobiteillä, ja toisessa vaihdetaan puskurin merkkejä satunnaisesti. Satunnaisuus itseasiassa muodostuu siitä, missä puskurin paikassa merkki on kun sitä xorataan kellojonolla.
void ressu_genbytes_single(int size, unsigned char *buffer)
{
int c, d, e, byte;
static int f = 0, prevbyte = -1, count = 0;
for(c=0; c<8; c++) {
for(d=0; d<size; d++) {
e = buffer[d];
e = ((e&0x80)>>7) | ((e&0x7f)<<1); // rotate left 1
//e = ((e&0xe0)>>5) | ((e&0x1f)<<3); // rotate left 3
//e = ((e&0xfe)>>1) | ((e&0x1)<<7); // rotate right 1
byte = ressu_clockbyte();
if(prevbyte==-1)
prevbyte=byte;
buffer[d] = e^byte;
if(prevbyte!=byte) {
periods[count]++;
clockbytes+=count;
count=0;
prevbyte=byte;
}
count++;
}
for(d=0; d<size; d++) {
f = (f + buffer[d]) % size;
e = buffer[d];
buffer[d] = buffer[f];
buffer[f] = e;
}
}
}
Seuraava rutiini on varsinainen asiakkaan kutsuttava rutiini, ja se yrittää löytää tarvittavien bittien määrän perusteella oikean määrän edellisen _single rutiinin kutsukertoja. Olennaisia asioita ovat se, että _single suorituksia on tarpeeksi että tulee mahdottomaksi arvata kellojonoa, tai sen perusteella satunnaisbittijonoa. Toinen asia on se, että tämä rutiini erottaa satunnaislukupuskurin asiakkaasta, että asiakas ei saa puskurin rakennetta, eikä näin voi arvata kellojonoa tai puskuria.
Ressun –stat riveillä on nyt ketjut myös lajitellussa (sorted) listassa, jolloin eri limitit on helpompi paikallistaa.
void ressu_genbytes(int size, unsigned char *buffer) // 6.5.2021 JariK
{
int c, d, e, f;
static int ressut_first=1,
ressut_pos = 0,
ressut_f = 0;
static unsigned char ressut[RESSUT_BYTES];
unsigned long prevperiods[1024];
for(c=0; c<size; c++) {
if(ressut_pos == 0) {
if(ressut_first) {
memset(ressut,0,ressut_bytes);
ressut_first=0;
}
clockbytes=0;
for(d=0;d<1024;d++) {
periods[d]=0;
}
int rndbits=0;
int lim, lim1=0, lim2=0;
int lim1a, lim1b;
int high1, high2;
for(d=0; rndbits<ressu_bits_needed ||
d<RESSU_MIN_ROUNDS ||
clockbytes < RESSU_MIN_CLOCKBYTES; d++) {
// save previous round
for(e=0;e<1024;e++) {
prevperiods[e]=periods[e];
}
ressu_genbytes_single(ressut_bytes,ressut);
// find new lim1
lim=lim1;
f=-1;
for(e=0;e<1024;e++) {
if(prevperiods[e]>0 && prevperiods[e]==lim) {
if(f==-1 || (periods[e]>0 && f<periods[e])) {
f=periods[e];
}
}
}
if(f!=-1)
lim=f;
lim1a=lim;
// find highest amount of chains
high1=-1;
for(e=0;e<1024;e++) {
if(high1==-1 || high1<periods[e]) {
high1=periods[e];
}
}
// and second highest
high2=-1;
for(e=0;e<1024;e++) {
if( (high2==-1 && periods[e]<high1) ||
(high2<periods[e] && periods[e]<high1) ) {
high2=periods[e];
}
}
// and average
int psum=0;
int pcnt=0;
for(e=0;e<1024;e++) {
if(periods[e]>0) {
psum+=periods[e];
pcnt++;
}
}
lim1b=(int)((double)psum/pcnt);
// find next smaller than average
f=-1;
for(e=0;e<1024;e++) {
if( (f==-1 && periods[e]<lim1b) ||
(f<periods[e] && periods[e]<lim1b) ) {
f=periods[e];
}
}
if(f!=-1)
lim1b=f;
if(lim==0 || lim>lim1b)
lim=lim1b;
// if lim greater that second highest,
// set to second highest
if(lim>high2) {
lim=high2;
}
lim1=lim;
// find next greater than lim
f=-1;
for(e=0;e<1024;e++) {
if(periods[e]>lim &&
(f==-1 || periods[e]<f))
f=periods[e];
}
if(f!=-1)
lim=f;
lim2=lim;
// calculate bits
rndbits=0;
for(e=0;e<1024;e++) {
if(periods[e]>0 && periods[e]<lim) {
rndbits+=periods[e];
}
}
} // for(d=0;
if(stats) {
fprintf(stdout,"rounds: %d",d);
for(e=0;e<1024;e++) {
if(periods[e]>0)
fprintf(stdout," %d:%lu",e,periods[e]);
}
#ifdef DEBUG_SORTED
fprintf(stdout,", sorted:");
int g=0;
for(;;) {
f=-1;
for(e=0;e<1024;e++) {
if( (f==-1 && periods[e]>g) ||
(periods[e]>g && f>periods[e]) )
f=periods[e];
}
if(f==-1)
break;
g=f;
fprintf(stdout," %d",g);
}
#endif
fprintf(stdout,", high1:%d",high1);
fprintf(stdout,", high2:%d",high2);
fprintf(stdout,", lim1a:%d",lim1a);
fprintf(stdout,", lim1b:%d",lim1b);
fprintf(stdout,", lim1:%d",lim1);
fprintf(stdout,", lim2:%d",lim2);
fprintf(stdout,", div:%f",(double)lim2/lim1);
fprintf(stdout,", clockbytes:%ld",clockbytes);
fprintf(stdout,", rndbits:%d",rndbits);
fprintf(stdout,"\n");
fflush(stdout);
}
} // if(ressut_pos == 0)
ressut_f = (ressut_f + ressut[ressut_pos]) % ressut_bytes;
buffer[c] ^= ressut[ressut_f];
ressut_pos = (ressut_pos+1) % ressut_bytes;
} // for(c=0; c<size; c++)
genbytes+=size;
}
Seuraavassa apurutiinit –sample option tilarivin tulostukseen. stat_line_begin() aloittaa tilarivin tulostuksen, stat_line_printf() tulostaa tilarivin elementin, stat_line_readable() tulostaa luvun pyöristettynä merkkeihin, kiloihin, megoihin tai gigoihin stat_line_end() lopettaa rivin tulostuksen ja poistaa edellisen rivin jäämät rivin lopusta.
#include <stdarg.h>
#define aDEBUG31
static int stat_line_chars=0;
static int stat_line_edchars=0;
static void stat_line_begin()
{
#ifdef DEBUG31
fprintf(stderr,"\n");
#else
fprintf(stderr,"\r");
#endif
stat_line_edchars=stat_line_chars;
stat_line_chars=0;
}
static void stat_line_printf(const unsigned char *format, ...)
{
int count;
va_list args;
static unsigned char *stat_line_buf;
static size_t stat_line_buf_length;
va_start(args, format);
count = vsnprintf(stat_line_buf, stat_line_buf_length, format, args) + 1;
va_end(args);
if(stat_line_buf_length < count) {
stat_line_buf_length=count;
stat_line_buf=realloc(stat_line_buf, stat_line_buf_length);
va_start(args, format);
count = vsnprintf(stat_line_buf, stat_line_buf_length, format, args) + 1;
va_end(args);
}
fprintf(stderr,"%s",stat_line_buf);
stat_line_chars+=strlen(stat_line_buf);
}
#define READABLE_NUMBER_BIN 2
#ifdef READABLE_NUMBER_BIN
#define READABLE_NUMBER_HIGH 1023
#define READABLE_NUMBER_DIVIDER 1024
#else
#define READABLE_NUMBER_HIGH 999
#define READABLE_NUMBER_DIVIDER 1000
#endif
#define READABLE_NUMBER_WIDTH 32
static void stat_line_readable(unsigned long length)
{
int c, low;
double length2;
unsigned char buf10[10];
// B = byte
// K = kilo 10^3 2^10
// M = mega 10^6 2^20
// G = giga 10^9 2^30
// T = tera 10^12 2^40
// P = peta 10^15 2^50
// E = exa 10^18 2^60
// Z = zetta 10^21 2^70
// Y = yotta 10^24 2^80
char units[] = "BKMGTPEZY";
strcpy(buf10,"***");
low=0;
for(c=0; length>=low &&
c<sizeof(units)-1; c++) {
if(length>=low &&
length<=READABLE_NUMBER_HIGH) {
if(units[c]=='B')
sprintf(buf10,"%ld", length);
else if(units[c]=='K')
sprintf(buf10,"%ld%cB", length, units[c]);
else if(length==length2)
sprintf(buf10,"%ld%cB", length, units[c]);
else
sprintf(buf10,"%.1f%cB", length2, units[c]);
break;
}
length2=(double)length/READABLE_NUMBER_DIVIDER;
length/=READABLE_NUMBER_DIVIDER;
low=1;
}
stat_line_printf("%s",buf10);
}
void stat_line_end()
{
int c,d;
// previous line longer than this one,
// overwrite with spaces and backspace to
// end
if(stat_line_edchars>stat_line_chars) {
d=stat_line_edchars-stat_line_chars;
for(c=0;c<d;c++) {
#ifdef DEBUG31
fprintf(stderr,"*");
#else
fprintf(stderr," ");
#endif
}
for(c=0;c<d;c++)
fprintf(stderr,"\b");
}
fflush(stderr);
}
Ensin esimerkki tilarivin tulostuksesta: (rullaa loppurivin nähdäksesi oikealle). Olen lisännyt väleihin crlf:iä saadakseni näkyviin useampia rivejä. Rivien loppuihin on jäänyt tuo animoitu kursori.
./newressu --fast --sample
blk 0, written 0 |/
blk 1, written 1MB, 1MB/sec, now Sat 20:50 UTC, left 2h 16m, ready at 23:06 UTC /-
blk 327, written 327MB, 860KB/sec, now Sat 20:56 UTC, left 2h 35m, ready at 23:32 UTC \|/
blk 667, written 667MB, 854KB/sec, now Sat 21:03 UTC, left 2h 30m, ready at 23:33 UTC \|/
blk 945, written 945MB, 856KB/sec, now Sat 21:09 UTC, left 2h 24m, ready at 23:33 UTC /-
blk 1024, written 1GB, 855KB/sec, now Sat 21:10 UTC, left 2h 22m, ready at 23:33 UTC \|
blk 1025, written 1.0GB, 856KB/sec, now Sat 21:10 UTC, left 2h 22m, ready at 23:33 UTC |/
blk 1685, written 1.6GB, 858KB/sec, now Sat 21:23 UTC, left 2h 9m, ready at 23:33 UTC |/
blk 2048, written 2GB, 860KB/sec, now Sat 21:30 UTC, left 2h 1m, ready at 23:32 UTC \|
blk 2229, written 2.2GB, 862KB/sec, now Sat 21:34 UTC, left 1h 58m, ready at 23:32 UTC -\
blk 2725, written 2.7GB, 866KB/sec, now Sat 21:43 UTC, left 1h 47m, ready at 23:31 UTC /-
blk 3133, written 3.1GB, 869KB/sec, now Sat 21:51 UTC, left 1h 39m, ready at 23:31 UTC /-
blk 3569, written 3.5GB, 871KB/sec, now Sat 22:00 UTC, left 1h 30m, ready at 23:30 UTC \|
blk 4096, written 4GB, 869KB/sec, now Sat 22:10 UTC, left 1h 20m, ready at 23:31 UTC \|
blk 4226, written 4.1GB, 870KB/sec, now Sat 22:13 UTC, left 1h 17m, ready at 23:30 UTC |/
blk 4864, written 4.8GB, 873KB/sec, now Sat 22:25 UTC, left 1h 5m, ready at 23:30 UTC /-\
blk 5380, written 5.3GB, 874KB/sec, now Sat 22:35 UTC, left 54m, ready at 23:30 UTC -\|
blk 5482, written 5.4GB, 874KB/sec, now Sat 22:37 UTC, left 52m, ready at 23:30 UTC /-
blk 5992, written 5.9GB, 875KB/sec, now Sat 22:47 UTC, left 42m, ready at 23:30 UTC -\
blk 6110, written 6.0GB, 876KB/sec, now Sat 22:49 UTC, left 40m, ready at 23:29 UTC \|
blk 6379, written 6.2GB, 876KB/sec, now Sat 22:54 UTC, left 35m, ready at 23:29 UTC /-
blk 7117, written 7.0GB, 873KB/sec, now Sat 23:09 UTC, left 20m, ready at 23:30 UTC /-
blk 7854, written 7.7GB, 870KB/sec, now Sat 23:24 UTC, left 6m, ready at 23:30 UTC -\
blk 8144, written 8.0GB, 870KB/sec, now Sat 23:30 UTC, left 56 seconds, ready at 23:30 UTC /-\
blk 8171, written 8.0GB, 869KB/sec, now Sat 23:30 UTC, left 24 seconds, ready at 23:31 UTC -\
blk 8187, written 8.0GB, 869KB/sec, now Sat 23:30 UTC, left 5 seconds, ready at 23:31 UTC /-
blk 8188, written 8.0GB, 869KB/sec, now Sat 23:30 UTC, left 4 seconds, ready at 23:31 UTC -\
blk 8189, written 8.0GB, 869KB/sec, now Sat 23:30 UTC, left 3 seconds, ready at 23:31 UTC \|
blk 8190, written 8.0GB, 869KB/sec, now Sat 23:30 UTC, left 2 seconds, ready at 23:31 UTC |/-
blk 8191, written 8.0GB, 869KB/sec, now Sat 23:31 UTC, left 1 seconds, ready at 23:31 UTC -\
Done!
Seuraavassa tulostetaan –sample kytkimellä satunnaislukutiedosto. Edellisestä versiosta on lisätty tilarivi animoituva kursori, kytkimet eri satunnaislukulähteille (–ressu, –debug. –single, –fast, –urandom, –random). Lisäksi sample rivillä on kenttä, jossa on bittigeneraattorin nopeus (esim 700Kb/sec).
. if(sample) {
//sample file size = CLIM*DLIM*BLKSIZE
#define CLIM 8192 // outer loop
#define DLIM 256 // inner loop
#define BLKSIZE 4096 // block size
#define STAT_LINE_READY 2
#define STAT_LINE_NOW 2
#define STAT_LINE_ANIM 2
#define TIMEFORMAT "%H:%M %Z"
#define TIMEFORMAT2 "%a %H:%M %Z"
#define DATEFORMAT "%a %d %b %Y"
unsigned int c, d;
unsigned char buffer[BLKSIZE];
FILE *fp1;
time_t secondsstart, secondsnow;
#ifdef STAT_LINE_ANIM
long int secs, prev_secs=-1;
int crs=0;
#endif
if((fp1=fopen(samplefilename,"a")) != NULL) {
secondsstart=time(NULL);
for(c=0;c<CLIM;c++) {
secondsnow=time(NULL);
// print status line:
// blk 8171, written 8.0GB, 869KB/sec, now Sat 23:30 UTC, left 24 seconds, ready at 23:31 UTC
stat_line_begin();
stat_line_printf("\rblk %d, written ",c);
stat_line_readable((unsigned long)c*DLIM*BLKSIZE);
if(c>0) {
stat_line_printf(", ");
stat_line_readable((unsigned long)((double)c*DLIM*BLKSIZE/(secondsnow-secondsstart)) );
stat_line_printf("/sec");
char timebuf[128], timebuf2[128];
#ifdef STAT_LINE_NOW
// print now
stat_line_printf(", now");
strftime(timebuf,sizeof(timebuf),TIMEFORMAT2,
localtime((time_t *)&secondsnow));
stat_line_printf(" %s",timebuf);
#endif
// print left
long int secondsleft=(int)((((double)secondsnow-secondsstart)/c)*(CLIM-c) );
long int secondsleft2;
long int temp,timeprinted=0;
secondsleft2=secondsleft;
stat_line_printf(", left");
temp=secondsleft2/(24*3600);
if(temp>0) {
timeprinted=1;
stat_line_printf(" %dd",temp);
secondsleft2-=temp*(24*3600);
}
temp=secondsleft2/3600;
if(temp>0) {
timeprinted=1;
stat_line_printf(" %dh",temp);
secondsleft2-=temp*3600;
}
temp=secondsleft2/60;
if(temp>0) {
timeprinted=1;
stat_line_printf(" %dm",temp);
secondsleft2-=temp*60;
}
temp=secondsleft2;
if(!timeprinted) {
stat_line_printf(" %d seconds",temp);
}
#ifdef STAT_LINE_READY
long int secondsend=(int)secondsstart+((((double)secondsnow-secondsstart)/c)*CLIM);
// print end date if different
stat_line_printf(", ready at");
strftime(timebuf,sizeof(timebuf),DATEFORMAT,
localtime((time_t *)&secondsend));
strftime(timebuf2,sizeof(timebuf2),DATEFORMAT,
localtime((time_t *)&secondsnow));
if(strcmp(timebuf,timebuf2)) {
stat_line_printf(" %s",timebuf);
}
// print end time
strftime(timebuf,sizeof(timebuf),TIMEFORMAT,
localtime((time_t *)&secondsend));
stat_line_printf(" %s",timebuf);
#endif
}
stat_line_end();
// do the work
#ifdef STAT_LINE_ANIM
unsigned char cursor[4] = { '|', '/', '-', '\\' };
fprintf(stderr," ");
#endif
for(d=0;d<DLIM;d++) {
#ifdef STAT_LINE_ANIM
secs=time(NULL)%sizeof(cursor);
if(prev_secs!=secs) {
if(prev_secs!=-1)
crs=(crs+1)%sizeof(cursor);
fprintf(stderr,"\b%c",cursor[crs]);
fflush(stderr);
prev_secs=secs;
}
#endif
if(input==0) // ressu prod
ressu_genbytes(sizeof(buffer),buffer);
else if(input==1) // ressu debug
ressu_genbytes_debug(sizeof(buffer),buffer);
else if(input==2) { // ressu fast
clockbytes=0;
for(e=0; e<RESSU_MIN_ROUNDS ||
clockbytes < RESSU_MIN_CLOCKBYTES;e++) {
ressu_genbytes_single(sizeof(buffer),buffer);
}
} else if(input==3) // ressu single
ressu_genbytes_single(sizeof(buffer),buffer);
else if(input==8) // urandom
readfile_xor(sizeof(buffer),buffer,urandomfilename);
else if(input==9) // random
readfile_xor(sizeof(buffer),buffer,randomfilename);
#ifdef WRITE_SAMPLE
fwrite(buffer,1,sizeof(buffer),fp1);
#endif
}
#ifdef STAT_LINE_ANIM
fprintf(stderr,"\b \b");
prev_secs=-1;
#endif
}
fclose(fp1);
}
// remove last status line
stat_line_begin();
stat_line_printf("Done!");
stat_line_end();
fprintf(stdout,"\n");
fflush(stdout);
exit(0);
}
Vielä joukko “naapureiden” ja muiden merkistöjä:
} else if(!strcmp("--rus",argv[c])) { // russian alphabet
digits=
"АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ" \
"абвгдеёжзийклмнопрстуфхцчшщъыьэюя";
size=8;
} else if(!strcmp("--dnk",argv[c]) || // danish alphabet
!strcmp("--nor",argv[c])) { // norwegian alphabet
digits=
"ABCDEFGHIJKLMNOPQRSTUVWXYZÆØÅ" \
"abcdefghijklmnopqrstuvwxyzæøå";
size=8;
} else if(!strcmp("--fin",argv[c]) || // finnish alphabet
!strcmp("--swe",argv[c])) { // swedish alphabet
digits=
"ABCDEFGHIJKLMNOPQRSTUVWXYZÅÄÖ" \
"abcdefghijklmnopqrstuvwxyzåäö";
size=8;
} else if(!strcmp("--est",argv[c])) { // estonian alphabet
digits=
"ABCDEFGHIJKLMNOPQRSŠZŽTUVWÕÄÖÜXY" \
"abcdefghijklmnopqrsšzžtuvwõäöüxy";
size=8;
} else if(!strcmp("--ltu",argv[c])) { // lithuanian alphabet
digits=
"AĄBCČDEĘĖFGHIĮYJKLMNOPRSŠTUŲŪVZŽ" \
"aąbcčdeęėfghiįyjklmnoprsštuųūvzž";
size=8;
} else if(!strcmp("--lva",argv[c])) { // latvian alphabet
digits=
"AĀBCČDEĒFGĢHIĪJKĶLĻMNŅOPRSŠTUŪVZŽ" \
"aābcčdeēfgģhiījkķlļmnņoprsštuūvzž";
size=8;
} else if(!strcmp("--fra",argv[c]) // french alphabet
||!strcmp("--gbr",argv[c]) // great britain alphabet
||!strcmp("--usa",argv[c]) // united states alphabet
||!strcmp("--ita",argv[c]) // italian alphabet
) {
digits=
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
"abcdefghijklmnopqrstuvwxyz";
size=8;
} else if(!strcmp("--deu",argv[c])) { // deutche alphabet
digits=
"ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜẞ" \
"abcdefghijklmnopqrstuvwxyzäöüß";
size=8;
} else if(!strcmp("--grc",argv[c])) { // greek alphabet
digits=
"ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ" \
"αβγδεζηθικλμνξοπρστυφχψω";
size=8;
}
...
Seuraavassa satunnaismerkkejä suomalaisella merkistöllä:
$ newressu --fin
00000 gaClJUiÖLFyyzKOKShäIwhpäyckfsITLjpIåCbPjZgfoNMqpKäuwäYyJYeqYaWBO
00001 CuhaxfbcefEsCwdAHuTMrcLqhkzÄSäCNicgDsNÄqekVläÅStgZiKuDVNÅkfhuaåT
00002 häOhuzNOQuBSoCAjPufäAlRAhtRGzbGMoöäPSgÅzöBWQAGiÖSctäTSuLwxTuxhff
00003 yryQRXiDQVåkKÅbivTBulywRzGÅpUaTåJäcboZCqÅvskCcÄUCtnbJLHOWeÄÅxÅGV
00004 MÅöVxnCbÄäböSmjjGVDpÄTFSEUCVÄxMRÅiqAäzpctsuaNvkbgkLTUXwpbNhMblLh
00005 oLUwEgvÅVVSÅåJvhmZDKUäKksÄjaåwRdzEhPeöqUyZYPDöezupmÅägkHmzoHÖbIc
00006 xNYbbKucMktDQlWcPxDJåYEOaHMoäfyQLEUdQxkIjKcXydQVJPjRJdUshdZjÅBur
00007 pWvxTCqAbnjsTJhkQtSDphJumoUogeIhKmVåAYSrLqÖoHsVrKrDFOmåPRÄiRRTbD
00008 GiöDRÖÄezäwFgäwuFcpApInTdXYbMvOpwscbQyrZPdmBbCRVqgkeZBpALsxQPäeG
00009 rTrMöxjWöuFMZASgGjrlrÖÅäoZrvAWvTpaöVIEIZxPFPHzFyGeIMäBrVlIQsOhFF
Ja vielä satunnaismerkkejä kreikkalaisella merkistöllä:
$ ./newressu --grc
00000 ΧΙμΘΗζζηΓλΨΥλΔυσΤΒΒηλΨγτΕσΦθΜκΣμψψδιΒψΗωρβΚΟΡΦΔΟΗσαλΤΑΧΧρωεγΜΥΒΓ
00001 ΤβΚΒΘΣΚγΞΦηΗγοΦοφγΒζβπΣΜδΙζπψδψεΞηΖΒΔΖηοΜνΠΒτγΠΗρηΜΣξηρΤΡνΖΞοφαλ
00002 ΒΔΗαορΙΚΦΥηοφΤηΦΝρΜΙμΞπΡβδδΝβΩΚυΙοΝΗιΡΖΓΤΥππΘΔλΥΙΣΩΛΒζξλθΛχΒηψΨΛ
00003 σΧΛΥγξΠΠΒριΚιΔπΘΨΓαΣΤεεξΝοΗπΔΨνΠνΜηΠλφΒπΣΞξβρΑΩΨΙΠρθδπαξψθωΟΠΦΝλ
00004 ΚΨΝτπβσαΥΨΚηδΔΖβΩΦΜμψλΤΔεχΞΑυΡνΓεκιΙαβΧμΕβΤεΩηβΝεΩΘΣμΕΟΙεΘαφΑΡυθ
00005 υΨχνΔΥΜΝκηωφΙΜΑΜΧΧΕρυξυΝτωλΞρΟθψρχΩωΚΜΒΧνΓΗΔΒαυΟνψΗωμσδΗσρσΞΔπΩΥ
00006 εγΜτζγσμΕΝΟγφνδΔμΙλξκΞζδιΓηλΘθζυοΗΦψπδΠΦΗηΗψΜωθαιΣπΘυψΥΤλΣμΝΦοΓυ
00007 ΤΕεΛΙυΔΤμΟΗωΡΔτππΜΔΑΔογγκσλΠΒΛΟΚραΓΔΛμπβξωξΚζΣοηποΝχΗωΡγΨθωΞΚΡηγ
00008 ΝΓΘφΓτΣλΠιαΨεΨΛΚΑΗφβζΠΦΩΜφφΨΞαΣξδθΠΕΑωζΑΛΜζωωΓξΩπΘΟδθδΓΑμλΥΞΡΚχΝ
00009 εΠΙβΒΚηΘΣΚΨτβΨΗΧΑΚΦαξΨιααδΘιμνΖπΦΒνΔχρζΓομγγζυγΔζΘΑπΔΝμΛΟοΚΕΗΒΦξ
Edit: Lisätty #define määritykset eri input tyypeille:
#define INPUT_RESSU 0
#define INPUT_DEBUG 1
#define INPUT_FAST 2
#define INPUT_SINGLE 3
#define INPUT_URANDOM 8
#define INPUT_RANDOM 9
static int input=0;
char *randomgen[] = { "ressu", "debug","fast","single","4","5","6","7","urandom","random" };
Eri input:tien käsittely parametreissa:
} else if(!strcmp("--ressu",argv[c])) {
input=INPUT_RESSU;
} else if(!strcmp("--debug",argv[c])) {
input=INPUT_DEBUG;
} else if(!strcmp("--fast",argv[c])) {
input=INPUT_FAST;
} else if(!strcmp("--single",argv[c])) {
input=INPUT_SINGLE;
} else if(!strcmp("--urandom",argv[c])) {
input=INPUT_URANDOM;
#ifdef USE_RANDOM
} else if(!strcmp("--random",argv[c])) {
input=INPUT_RANDOM;
#endif
Eri inputtien käsittely Ressu_genbyte():ssä:
int ressu_genbyte()
{
static unsigned char gent[GENT_SIZE];
static unsigned int gent_pos=0;
unsigned char ch;
if(input==INPUT_RESSU) { // ressu prod
ressu_genbytes(sizeof(ch), &ch);
} else if(input==INPUT_DEBUG) { // ressu debug
ressu_genbytes_debug(sizeof(ch), &ch);
} else {
if(gent_pos==0) {
if(input==INPUT_FAST) { // ressu_fast
ressu_genbytes_fast(sizeof(gent),gent);
} else if(input==INPUT_SINGLE) { // ressu single
ressu_genbytes_single(sizeof(gent),gent);
} else if(input==INPUT_URANDOM) { // urandom
readfile_xor(sizeof(gent),gent,urandomfilename);
#ifdef USE_RANDOM
} else if(input==INPUT_RANDOM) { // random
readfile_xor(sizeof(gent),gent,randomfilename);
#endif
}
} // if(gent_pos==0
ch=gent[gent_pos];
gent_pos=(gent_pos+1)%sizeof(gent);
}
return(ch);
}
Inputtien käsittely –sample rutiinissa:
...
if(input==INPUT_RESSU) // ressu prod
ressu_genbytes(sizeof(buffer),buffer);
else if(input==INPUT_DEBUG) // ressu debug
ressu_genbytes_debug(sizeof(buffer),buffer);
else if(input==INPUT_FAST) // ressu fast
ressu_genbytes_fast(sizeof(buffer),buffer);
else if(input==INPUT_SINGLE) // ressu single
ressu_genbytes_single(sizeof(buffer),buffer);
else if(input==INPUT_URANDOM) // urandom
readfile_xor(sizeof(buffer),buffer,urandomfilename);
#ifdef USE_RANDOM
else if(input==INPUT_RANDOM) // random
readfile_xor(sizeof(buffer),buffer,randomfilename);
#endif
...
–space parametria muutettu siten että sillä voidaan ryhmitellä rivit kuinka monen sanan ryhmäksi tahansa. Lisätty myös –newline parametri, jolla kerrotaan kuinka monen rivin välin tulostetaan tyhjä rivi. Aluksi –space ja –newline parametrin käsittely:
} else if(!strncmp("--space",argv[c],7)) {
if(*(argv[c]+7)!='\0' && atoi(argv[c]+7)>1) {
sspace=atoi(argv[c]+7);
} else if(c+1<argc && atoi(argv[c+1])>1) {
sspace=atoi(argv[c+1]);
c++;
} else {
sspace=!sspace;
}
} else if(!strncmp("--newline",argv[c],9)) {
if(*(argv[c]+9)!='\0' && atoi(argv[c]+9)>1) {
snewline=atoi(argv[c]+9);
} else if(c+1<argc && atoi(argv[c+1])>1) {
snewline=atoi(argv[c+1]);
c++;
} else {
snewline=!snewline;
}
Muutos –rand toimintoon (ennen sspace asetettiin kolmoseksi, nyt kakkoseksi, eli kahden sanan ryhmät, ja newline asetetaan viitoseksi, tyhjä rivi viiden rivin välein):
} else if(!strcmp("--rand",argv[c])) {
digits = "0123456789";
sspace=2;
snewline=5;
slineno=1;
words=10;
chars=0;
limit=100000;
//size=5;
//lines=20000;
Seuraavassa esimerkkejä –space toiminnosta:
$ newressu --space2 -w12
00000 40576 19224 31061 56270 17558 40937 34594 10659 74339 12974 22074 55552
00001 16458 38377 11774 16585 22914 91334 07864 56857 67861 21625 60387 19236
00002 89247 64778 70347 88680 18056 41666 21943 54933 98467 47080 72261 75113
00003 85600 85785 21279 60961 44469 44224 07816 05428 12713 47709 00767 21351
00004 44610 12782 36115 18451 35002 32467 57140 45450 52562 19903 23200 42600
00005 41334 49165 43451 22812 35567 97697 33419 54424 99249 73074 78173 33494
00006 46004 49866 74092 88375 66402 06470 84535 42922 19028 54769 40706 56304
00007 23769 33368 34626 62956 76015 13668 63460 88936 16224 07373 95768 58904
00008 69892 32434 47599 52513 59030 96318 71762 83897 84475 66329 97716 37462
00009 49860 55143 28166 55053 24563 70116 81067 09653 68256 69821 35928 62961
$ newressu --space3 -w12
00000 17152 43421 73154 88356 08724 22361 98840 58719 38530 71759 99457 54797
00001 34274 64843 30530 09491 75975 09179 07263 28982 07386 42666 87893 42997
00002 79771 40056 80666 48071 95604 53112 11807 43640 97394 83588 99039 15051
00003 24446 20612 27304 39014 61616 12134 66611 26373 08435 10287 76092 84674
00004 51142 23682 70818 15506 33787 87524 27784 70951 40143 93128 05481 37800
00005 92343 56280 49333 63783 87591 69719 91171 03362 25838 51097 71197 07878
00006 37752 74753 85191 70998 41906 76664 03094 36603 26754 63766 35271 66881
00007 30308 55030 36917 91142 83198 72776 56947 07046 01347 91820 34930 46188
00008 76167 95789 56123 00234 68842 55135 01123 61807 36224 10612 53782 58296
00009 60449 49813 78428 13318 35303 92252 76849 68503 27659 21438 20675 24302
$ newressu --space4 -w12
00000 20742 22650 28906 31905 47341 04150 50584 13183 17049 80113 91663 72823
00001 18451 62550 03962 72838 70153 04558 04736 05078 32753 58747 59763 85999
00002 13546 21343 80647 86450 08986 70814 52073 89482 16833 69109 83168 74567
00003 43312 08071 10380 79643 05954 04207 79686 58144 32362 12612 49240 77737
00004 09080 40197 19063 83600 71642 53301 42849 13056 24062 84903 99760 74049
00005 58252 03578 26906 69699 54557 99905 97538 10684 48060 11384 36784 22614
00006 62784 41888 44974 92600 54416 74768 04900 40537 21423 48921 05873 87655
00007 79264 95285 31512 88833 95410 48463 18757 65606 47583 62909 61778 98167
00008 21430 53643 59374 10165 66253 18774 52714 97702 66947 83793 96488 74019
00009 19585 27211 43086 98500 78116 97613 11368 97086 07767 75589 49746 85101
$ newressu --space6 -w12
00000 54562 43657 61862 90326 06376 68543 13187 74217 34102 99570 00506 08494
00001 43796 71105 76359 36295 05082 17566 83453 67076 01490 85085 89075 90791
00002 96623 74591 02669 84605 35980 77577 48690 37794 52479 63557 22829 04179
00003 62797 50805 37389 27107 88850 70272 90188 75741 81854 59182 87981 04882
00004 13869 45007 30936 83500 77868 82829 94888 97847 91576 45645 82972 11360
00005 69896 87217 37225 57165 46607 05168 26226 57438 52827 74413 74600 41372
00006 13930 89230 03171 90853 79694 61314 08778 82186 92948 66862 70041 66197
00007 53014 51311 04614 80982 78052 99464 30259 68724 10193 26498 36534 33548
00008 36716 94076 88796 12946 17293 42641 89329 14410 66266 92296 49736 20468
00009 89022 22758 19994 67680 20271 33398 90060 85101 31617 11169 89386 62883
Seuraavassa esimerkkejä –newline toiminnosta:
$ newressu --newline2
00000 12813454512274517122425130115329366202515091666002172505025708446
00001 71096917961720806622398424293094570593626081571407468856782029942
00002 31047589039493088825514190891802272638960735378240661287270814933
00003 44089360986269804268430685930815151891798848432529601113180624795
00004 19569055111387376033524341992010566706684305745782920146962411455
00005 40925179314794580859485054809954191393015027380242681571601836439
00006 39004105241760250328315129737539505105940903109668904054251135855
00007 14587962370655169678732121574908360695089442013629060386702741659
00008 86993427583498077107114114430973231820885984160751028895695538981
00009 99373782264354982010189723728714999104059933148883694576500989637
$ newressu --newline3
00000 38623820473984903715490633923035337747665655115872184341824384094
00001 11547415184513070913520251785473334799146294338887127786659410999
00002 15410172629583358480662649136383040138410387647765016582268881965
00003 00863451030577367274360418081943523452940675438253783662606719532
00004 01250079675066865757517649726995679792198002260657201736023787837
00005 94042313276943376689259878147623444882366379288007965386275558839
00006 23468210585440511486572986161349224492165783119937326761815799604
00007 75580944804404621982050962301318881792685082315718928756343655877
00008 97838780101007189801544198322649565267631399973289857678700275243
00009 00363356898906130839164602585292709158234658394677097875319319258
$ newressu --newline4
00000 72786849533113500677581727520646514466992947738841761551460659422
00001 17424406153258926055361193709969183192241783314364747963252396187
00002 62974292705081577883093518402663586933467293523840132980383941609
00003 09632535989837189578312034432800371535312445316521384541985342710
00004 58019241328566825267006667886417218528388447275955778929489919053
00005 25858380015274227163548822248333717139214276930655496085958767633
00006 58319515459516655356787764450762739262081023905149877752114500182
00007 71846494587648754437205332298599954664694916723684381200029099175
00008 71730873837817666232939724815562175781809864537799316370685741021
00009 62465837514841138083445025234974607020150852582309301951684391272
Muotoiltu tulostus luuppia uudestaan, seuraavassa uusi koodi(aluksi apurutiinit): (vähennetty !quiet if lauseita, vähennetty pchars muuttelua)
static void print_spaces()
{
if(sspace>=2 &&
// rand space between double words
( (pwords>0 && pwords%sspace==0) ||
// rand space after linenumber
(slineno && pwords==0) ) )
fprintf(stdout," ");
if(sspace &&
// space between words
( (pwords>0) ||
// space after linenumber
(slineno && pwords==0) ) )
fprintf(stdout," ");
}
#ifdef OLD1
static void print_spaces()
{
if(sspace && pchars>0 && !quiet) {
if(sspace==3 && pwords%2==0) {
fprintf(stdout," ");
pchars++;
}
fprintf(stdout," ");
pchars++;
}
}
#endif
static void print_word(unsigned char *buf)
{
if(size!=0) {
fprintf(stdout,"%*s",size,buf);
} else {
fprintf(stdout,"%s",buf);
}
}
Ja varsinainen selkiytetty/lyhennetty tulostusluuppi:
for(;;) {
if(!sort) { // also lotto
pwords=0;
while(pwords<linew) {
readword(wordbuf);
if(!quiet) {
// in beginning of line, print line number
print_line_number();
// want to print spaces between "words"?
print_spaces();
// print word
print_word(wordbuf);
}
pwords++;
} // while(pwords<linew) {
} else { // if(!sort)
pwords=0;
line_clear(&linecnt,&line);
// fetch and save words on this row
while(pwords<linew) {
readword(wordbuf);
if(line_add_string_sort(&linecnt,&line,wordbuf)) {
pwords++;
}
} // while(pwords<linew) {
pwords=0;
// print words on this row
while(pwords<linew) {
line_get_string(sizeof(wordbuf),wordbuf,pwords,line);
if(!quiet) {
// in beginning of line, print line number
print_line_number();
// want to print spaces between "words"?
print_spaces();
// print word
print_word(wordbuf);
}
pwords++;
} // while(pwords<linew) {
} // if(!sort)
if(!quiet) {
fprintf(stdout,"\n");
}
plines++;
if(!quiet && snewline>1 &&
plines<lines &&
plines%snewline==0)
fprintf(stdout,"\n");
// all needed lines printed?
if(plines >= lines)
break;
} // for(;;)
Lopuksi vielä koko ohjelma:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <malloc.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#include <sys/time.h>
#include <time.h>
static unsigned char *procname;
static char *programname = "Newressu version 2.3 ©";
static unsigned char *copyright = "Copyright (c) 2013-2021 Jari Kuivaniemi, Helsinki, Finland. Kaikki oikeudet pidätetään!";
static unsigned long periods[1024];
static unsigned long genbytes=0;
static unsigned long clockbytes=0;
#define RESSUT_BYTES 1024
#define RESSU_BITS_NEEDED 128
#define RESSU_MIN_ROUNDS 2
#define RESSU_MIN_CLOCKBYTES 16384+1024
#define aWRITE_SAMPLE 2
#define USE_RANDOM 2
#define aDEBUG1
#define aDEBUG2 2
#define aDEBUG4 2
#define DEBUG_SORTED 2
static char samplefilename[128]="newressusample.rnd";
static char urandomfilename[128]="/dev/urandom";
static char randomfilename[128]="/dev/random";
#ifdef DEBUG4
static char debugfilename[128]="newressu.deb";
#endif
static int ressu_bits_needed = RESSU_BITS_NEEDED;
static int ressut_bytes = RESSUT_BYTES;
static int stats=0;
static unsigned char ressu_clockbyte() /* JariK 2013 */
{
struct timeval tv;
gettimeofday(&tv, NULL);
return(tv.tv_usec & 0xff);
}
void ressu_genbytes_single(int size, unsigned char *buffer)
{
int c, d, e, byte;
static int f = 0, prevbyte = -1, count = 0;
for(c=0; c<8; c++) {
for(d=0; d<size; d++) {
e = buffer[d];
e = ((e&0x80)>>7) | ((e&0x7f)<<1); // rotate left 1
//e = ((e&0xe0)>>5) | ((e&0x1f)<<3); // rotate left 3
//e = ((e&0xfe)>>1) | ((e&0x1)<<7); // rotate right 1
byte = ressu_clockbyte();
if(prevbyte==-1)
prevbyte=byte;
buffer[d] = e^byte;
if(prevbyte!=byte) {
periods[count]++;
clockbytes+=count;
count=0;
prevbyte=byte;
}
count++;
}
for(d=0; d<size; d++) {
f = (f + buffer[d]) % size;
e = buffer[d];
buffer[d] = buffer[f];
buffer[f] = e;
}
}
}
void ressu_genbytes_fast(int size, unsigned char *buffer)
{
int c;
clockbytes=0;
for(c=0; c<RESSU_MIN_ROUNDS ||
clockbytes < RESSU_MIN_CLOCKBYTES;c++) {
ressu_genbytes_single(size,buffer);
}
}
void ressu_genbytes(int size, unsigned char *buffer) // 6.5.2021 JariK
{
int c, d, e, f;
static int ressut_first=1,
ressut_pos = 0,
ressut_f = 0;
static unsigned char ressut[RESSUT_BYTES];
unsigned long prevperiods[1024];
for(c=0; c<size; c++) {
if(ressut_pos == 0) {
if(ressut_first) {
memset(ressut,0,ressut_bytes);
ressut_first=0;
}
clockbytes=0;
for(d=0;d<1024;d++) {
periods[d]=0;
}
int rndbits=0;
int lim, lim1=0, lim2=0;
int lim1a, lim1b;
int high1, high2;
for(d=0; rndbits<ressu_bits_needed ||
d<RESSU_MIN_ROUNDS ||
clockbytes < RESSU_MIN_CLOCKBYTES; d++) {
// save previous round
for(e=0;e<1024;e++) {
prevperiods[e]=periods[e];
}
ressu_genbytes_single(ressut_bytes,ressut);
// find new lim1
lim=lim1;
f=-1;
for(e=0;e<1024;e++) {
if(prevperiods[e]>0 && prevperiods[e]==lim) {
if(f==-1 || (periods[e]>0 && f<periods[e])) {
f=periods[e];
}
}
}
if(f!=-1)
lim=f;
lim1a=lim;
// find highest amount of chains
high1=-1;
for(e=0;e<1024;e++) {
if(high1==-1 || high1<periods[e]) {
high1=periods[e];
}
}
// and second highest
high2=-1;
for(e=0;e<1024;e++) {
if( (high2==-1 && periods[e]<high1) ||
(high2<periods[e] && periods[e]<high1) ) {
high2=periods[e];
}
}
// and average
int psum=0;
int pcnt=0;
for(e=0;e<1024;e++) {
if(periods[e]>0) {
psum+=periods[e];
pcnt++;
}
}
lim1b=(int)((double)psum/pcnt);
// find next smaller than average
f=-1;
for(e=0;e<1024;e++) {
if( (f==-1 && periods[e]<lim1b) ||
(f<periods[e] && periods[e]<lim1b) ) {
f=periods[e];
}
}
if(f!=-1)
lim1b=f;
if(lim==0 || lim>lim1b)
lim=lim1b;
// if lim greater that second highest,
// set to second highest
if(lim>high2) {
lim=high2;
}
lim1=lim;
// find next greater than lim
f=-1;
for(e=0;e<1024;e++) {
if(periods[e]>lim &&
(f==-1 || periods[e]<f))
f=periods[e];
}
if(f!=-1)
lim=f;
lim2=lim;
// calculate bits
rndbits=0;
for(e=0;e<1024;e++) {
if(periods[e]>0 && periods[e]<lim) {
rndbits+=periods[e];
}
}
} // for(d=0;
if(stats) {
fprintf(stdout,"rounds: %d",d);
for(e=0;e<1024;e++) {
if(periods[e]>0)
fprintf(stdout," %d:%lu",e,periods[e]);
}
#ifdef DEBUG_SORTED
fprintf(stdout,", sorted:");
int g=0;
for(;;) {
f=-1;
for(e=0;e<1024;e++) {
if( (f==-1 && periods[e]>g) ||
(periods[e]>g && f>periods[e]) )
f=periods[e];
}
if(f==-1)
break;
g=f;
fprintf(stdout," %d",g);
}
#endif
fprintf(stdout,", high1:%d",high1);
fprintf(stdout,", high2:%d",high2);
fprintf(stdout,", lim1a:%d",lim1a);
fprintf(stdout,", lim1b:%d",lim1b);
fprintf(stdout,", lim1:%d",lim1);
fprintf(stdout,", lim2:%d",lim2);
fprintf(stdout,", div:%f",(double)lim2/lim1);
fprintf(stdout,", clockbytes:%ld",clockbytes);
fprintf(stdout,", rndbits:%d",rndbits);
fprintf(stdout,"\n");
fflush(stdout);
}
} // if(ressut_pos == 0)
ressut_f = (ressut_f + ressut[ressut_pos]) % ressut_bytes;
buffer[c] ^= ressut[ressut_f];
ressut_pos = (ressut_pos+1) % ressut_bytes;
} // for(c=0; c<size; c++)
genbytes+=size;
}
#ifdef DEBUG4
static unsigned char cc[256*1048576]; // clock_chain
static unsigned char *ccp;
static int cc_bytes;
#endif
static unsigned char ressu_clockbyte_debug() /* JariK 2013 */
{
unsigned char c;
struct timeval tv;
gettimeofday(&tv, NULL);
c=tv.tv_usec & 0xff;
#ifdef DEBUG4
if(cc_bytes<sizeof(cc)) {
*ccp++ = c;
cc_bytes++;
}
#endif
return(c);
}
void ressu_genbytes_single_debug(int size, unsigned char *buffer)
{
int c, d, e, byte;
static int f = 0, prevbyte = -1, count = 0;
for(c=0; c<8; c++) {
for(d=0; d<size; d++) {
e = buffer[d];
e = ((e&0x80)>>7) | ((e&0x7f)<<1); // rotate left 1
//e = ((e&0xe0)>>5) | ((e&0x1f)<<3); // rotate left 3
//e = ((e&0xfe)>>1) | ((e&0x1)<<7); // rotate right 1
byte = ressu_clockbyte_debug();
if(prevbyte==-1)
prevbyte=byte;
buffer[d] = e^byte;
if(prevbyte!=byte) {
periods[count]++;
clockbytes+=count;
count=0;
prevbyte=byte;
}
count++;
}
for(d=0; d<size; d++) {
f = (f + buffer[d]) % size;
e = buffer[d];
buffer[d] = buffer[f];
buffer[f] = e;
}
}
}
void ressu_genbytes_debug(int size, unsigned char *buffer) // 6.5.2021 JariK
{
int c, d, e, f;
static int ressut_first=1,
ressut_pos = 0,
ressut_f = 0;
static unsigned char ressut[RESSUT_BYTES];
unsigned long prevperiods[1024];
for(c=0; c<size; c++) {
if(ressut_pos == 0) {
if(ressut_first) {
memset(ressut,0,ressut_bytes);
ressut_first=0;
}
clockbytes=0;
for(d=0;d<1024;d++)
periods[d]=0;
#ifdef DEBUG4
ccp=cc;
cc_bytes=0;
while(ressu_clockbyte_debug()!=0);
while(ressu_clockbyte_debug()==0);
ccp=cc;
cc_bytes=0;
#endif
int rndbits=0;
int lim, lim1=0, lim2=0;
int lim1a, lim1b;
int high1, high2;
for(d=0; rndbits<ressu_bits_needed ||
d<RESSU_MIN_ROUNDS; d++) {
// save previous round
for(e=0;e<1024;e++) {
prevperiods[e]=periods[e];
}
ressu_genbytes_single_debug(ressut_bytes,ressut);
// find new lim1
lim=lim1;
f=-1;
for(e=0;e<1024;e++) {
if(prevperiods[e]>0 && prevperiods[e]==lim) {
if(f==-1 || (periods[e]>0 && f<periods[e])) {
f=periods[e];
}
}
}
if(f!=-1)
lim=f;
lim1a=lim;
// find highest amount of chains
high1=-1;
for(e=0;e<1024;e++) {
if(high1==-1 || high1<periods[e]) {
high1=periods[e];
}
}
// and second highest
high2=-1;
for(e=0;e<1024;e++) {
if( (high2==-1 && periods[e]<high1) ||
(high2<periods[e] && periods[e]<high1) ) {
high2=periods[e];
}
}
// and average
int psum=0;
int pcnt=0;
for(e=0;e<1024;e++) {
if(periods[e]>0) {
psum+=periods[e];
pcnt++;
}
}
lim1b=(int)((double)psum/pcnt);
// find next smaller than average
f=-1;
for(e=0;e<1024;e++) {
if( (f==-1 && periods[e]<lim1b) ||
(f<periods[e] && periods[e]<lim1b) ) {
f=periods[e];
}
}
if(f!=-1)
lim1b=f;
if(lim==0 || lim>lim1b)
lim=lim1b;
// if lim greater that second highest,
// set to second highest
if(lim>high2) {
lim=high2;
}
lim1=lim;
// find next greater than lim
f=-1;
for(e=0;e<1024;e++) {
if(periods[e]>lim &&
(f==-1 || periods[e]<f))
f=periods[e];
}
if(f!=-1)
lim=f;
lim2=lim;
// calculate bits
rndbits=0;
for(e=0;e<1024;e++) {
if(periods[e]>0 && periods[e]<lim) {
rndbits+=periods[e];
}
}
if(stats) {
fprintf(stdout," round: %d",d);
for(e=0;e<1024;e++) {
if(periods[e]>0)
fprintf(stdout," %d:%lu",e,periods[e]);
}
#ifdef DEBUG_SORTED
fprintf(stdout,", sorted:");
int g=0;
for(;;) {
f=-1;
for(e=0;e<1024;e++) {
if( (f==-1 && periods[e]>g) ||
(periods[e]>g && f>periods[e]) )
f=periods[e];
}
if(f==-1)
break;
g=f;
fprintf(stdout," %d",g);
}
#endif
fprintf(stdout," high1:%d",high1);
fprintf(stdout," high2:%d",high2);
fprintf(stdout," lim1a:%d",lim1a);
fprintf(stdout," lim1b:%d",lim1b);
fprintf(stdout," lim1:%d",lim1);
fprintf(stdout," lim2:%d",lim2);
fprintf(stdout," clockbytes:%ld",clockbytes);
fprintf(stdout," rndbits:%d",rndbits);
fprintf(stdout,"\n");
fflush(stdout);
}
} // for(d=0;
if(stats) {
fprintf(stdout,"rounds: %d",d);
for(e=0;e<1024;e++) {
if(periods[e]>0)
fprintf(stdout," %d:%lu",e,periods[e]);
}
#ifdef DEBUG_SORTED
fprintf(stdout,", sorted:");
int g=0;
for(;;) {
f=-1;
for(e=0;e<1024;e++) {
if( (f==-1 && periods[e]>g) ||
(periods[e]>g && f>periods[e]) )
f=periods[e];
}
if(f==-1)
break;
g=f;
fprintf(stdout," %d",g);
}
#endif
fprintf(stdout," high1:%d",high1);
fprintf(stdout," high2:%d",high2);
fprintf(stdout," lim1a:%d",lim1a);
fprintf(stdout," lim1b:%d",lim1b);
fprintf(stdout," lim1:%d",lim1);
fprintf(stdout," lim2:%d",lim2);
fprintf(stdout," clockbytes:%ld",clockbytes);
fprintf(stdout," rndbits:%d",rndbits);
fprintf(stdout,"\n");
fflush(stdout);
}
#ifdef DEBUG4
FILE *fp1;
if((fp1=fopen(debugfilename,"a"))!=NULL) {
//if(lim1==-1 || lim2==-1 || lim1==lim2) {
for(e=0;e<32;e++)
fprintf(fp1,"%02x",ressut[e]);
fprintf(fp1,", ressut_bytes: %d",ressut_bytes);
fprintf(fp1,", ressu_bits_needed: %d",ressu_bits_needed);
fprintf(fp1,", ressu_min_rounds: %d",RESSU_MIN_ROUNDS);
fprintf(fp1,", clockbytes: %ld",clockbytes);
unsigned long total=0;
fprintf(fp1,", fluctuations:");
for(e=0;e<1024;e++) {
if(periods[e]!=0) {
fprintf(fp1," %d:%lu",e,periods[e]);
total+=(periods[e]*e);
}
}
fprintf(fp1,", total: %lu",total);
fprintf(fp1,", high1: %d",high1);
fprintf(fp1,", high2: %d",high2);
fprintf(fp1,", limit1: %d",lim1);
fprintf(fp1,", limit2: %d",lim2);
fprintf(fp1,", limit: %d",lim);
fprintf(fp1,", skipped:");
for(e=0;e<1024;e++) {
if(periods[e]>=lim) {
fprintf(fp1," %d:%lu",e,periods[e]);
}
}
fprintf(fp1,", counted:");
for(e=0;e<1024;e++) {
if(periods[e]>0 && periods[e]<lim) {
fprintf(fp1," %d:%lu",e,periods[e]);
}
}
fprintf(fp1,", rndbits: %d",rndbits);
fprintf(fp1,", rounds: %d",d);
int prevbyte=-1, count=0, count2=0;
unsigned char byte, small=-1;
fprintf(fp1,", small chains:");
for(e=0;e<cc_bytes;e++) {
byte=cc[e];
if(prevbyte==-1) {
prevbyte=byte;
count=1;
}
if(prevbyte!=byte) {
if(periods[count]>=lim) {
if(small==1 || small==-1)
fprintf(fp1," *");
small=0;
} else small=1;
if(small) {
fprintf(fp1," %d",count);
count2++;
}
count=0;
prevbyte=byte;
}
count++;
}
if(small) {
fprintf(fp1," %d",count);
count2++;
}
fprintf(fp1,", count: %d",count2);
fprintf(fp1,"\n");
fflush(fp1);
//}
fclose(fp1);
} // if((fp1=fopen
#endif
} // if(ressut_pos == 0)
ressut_f = (ressut_f + ressut[ressut_pos]) % ressut_bytes;
buffer[c] ^= ressut[ressut_f];
ressut_pos = (ressut_pos+1) % ressut_bytes;
} // for(c=0; c<size; c++)
genbytes+=size;
}
static void readfile_xor(int len,
unsigned char *buf,
unsigned char *filename)
{
int c, n, n2;
unsigned char temp[64];
FILE *fp1;
if((fp1 = fopen(filename, "rb"))
!= NULL) {
while(len != 0) {
n = (len < sizeof(temp)) ?
len : sizeof(temp);
n2=fread(temp, 1, n, fp1);
for(c = 0; c < n2; c++)
buf[c] ^= temp[c];
len -= n2;
buf += n2;
}
fclose(fp1);
}
}
#define INPUT_RESSU 0
#define INPUT_DEBUG 1
#define INPUT_FAST 2
#define INPUT_SINGLE 3
#define INPUT_URANDOM 8
#define INPUT_RANDOM 9
static int input=0;
#define GENT_SIZE 2048
#define aDEBUG9 2
char *randomgen[] = { "ressu", "debug","fast","single","4","5","6","7","urandom","random" };
int ressu_genbyte()
{
static unsigned char gent[GENT_SIZE];
static unsigned int gent_pos=0;
unsigned char ch;
if(input==INPUT_RESSU) { // ressu prod
ressu_genbytes(sizeof(ch), &ch);
} else if(input==INPUT_DEBUG) { // ressu debug
ressu_genbytes_debug(sizeof(ch), &ch);
} else {
if(gent_pos==0) {
if(input==INPUT_FAST) // ressu_fast
ressu_genbytes_fast(sizeof(gent),gent);
else if(input==INPUT_SINGLE) // ressu single
ressu_genbytes_single(sizeof(gent),gent);
else if(input==INPUT_URANDOM) // urandom
readfile_xor(sizeof(gent),gent,urandomfilename);
#ifdef USE_RANDOM
else if(input==INPUT_RANDOM) // random
readfile_xor(sizeof(gent),gent,randomfilename);
#endif
} // if(gent_pos==0
ch=gent[gent_pos];
gent_pos=(gent_pos+1)%sizeof(gent);
}
return(ch);
}
int ressu_genbyte_limit(int limit)
{
int c;
while((c=ressu_genbyte()) >= (256/limit)*limit);
return(c%limit);
}
int ressu_genshort()
{
return(ressu_genbyte() | ressu_genbyte()<<8);
}
int ressu_genshort_limit(int limit)
{
int c;
while((c=ressu_genshort()) >= (65536/limit)*limit);
return(c%limit);
}
unsigned int ressu_genint()
{
return(ressu_genshort() | ressu_genshort()<<16);
}
unsigned int ressu_genint_limit(unsigned long limit)
{
unsigned int c;
while((c=ressu_genint()) >= (((unsigned long)65536*65536)/limit)*limit);
return(c%limit);
}
unsigned long ressu_genlong()
{
return(((unsigned long)ressu_genint()) | ((unsigned long)ressu_genint())<<32);
}
unsigned long ressu_genlong_limit(unsigned long limit)
{
unsigned long c;
while((c=ressu_genlong()) >= (((unsigned long)0xffffffffffffffff)/limit)*limit);
return(c%limit);
}
unsigned long ressu_gen_limit(unsigned long limit)
{
if(limit<=256)
return(ressu_genbyte_limit(limit));
else if(limit<=65536)
return(ressu_genshort_limit(limit));
else if(limit<=(unsigned long)65536*65536)
return(ressu_genint_limit(limit));
else if(limit<=(unsigned long)0xffffffffffffffff)
return(ressu_genlong_limit(limit));
else
return(-1);
}
#define MAIN 2
#ifdef MAIN
#include <stdarg.h>
#define aDEBUG31
static int stat_line_chars=0;
static int stat_line_edchars=0;
static void stat_line_begin()
{
#ifdef DEBUG31
fprintf(stderr,"\n");
#else
fprintf(stderr,"\r");
#endif
stat_line_edchars=stat_line_chars;
stat_line_chars=0;
}
static void stat_line_printf(const unsigned char *format, ...)
{
int count;
va_list args;
static unsigned char *stat_line_buf;
static size_t stat_line_buf_length;
va_start(args, format);
count = vsnprintf(stat_line_buf, stat_line_buf_length, format, args) + 1;
va_end(args);
if(stat_line_buf_length < count) {
stat_line_buf_length=count;
stat_line_buf=realloc(stat_line_buf, stat_line_buf_length);
va_start(args, format);
count = vsnprintf(stat_line_buf, stat_line_buf_length, format, args) + 1;
va_end(args);
}
fprintf(stderr,"%s",stat_line_buf);
stat_line_chars+=strlen(stat_line_buf);
}
#define READABLE_NUMBER_BIN 2
#ifdef READABLE_NUMBER_BIN
#define READABLE_NUMBER_HIGH 1023
#define READABLE_NUMBER_DIVIDER 1024
#else
#define READABLE_NUMBER_HIGH 999
#define READABLE_NUMBER_DIVIDER 1000
#endif
#define READABLE_NUMBER_WIDTH 32
static void stat_line_readable(unsigned long length)
{
int c, low;
double length2;
unsigned char buf10[10];
// B = byte
// K = kilo 10^3 2^10
// M = mega 10^6 2^20
// G = giga 10^9 2^30
// T = tera 10^12 2^40
// P = peta 10^15 2^50
// E = exa 10^18 2^60
// Z = zetta 10^21 2^70
// Y = yotta 10^24 2^80
char units[] = "BKMGTPEZY";
strcpy(buf10,"***");
low=0;
for(c=0; length>=low &&
c<sizeof(units)-1; c++) {
if(length>=low &&
length<=READABLE_NUMBER_HIGH) {
if(units[c]=='B')
sprintf(buf10,"%ld", length);
else if(units[c]=='K')
sprintf(buf10,"%ld%cB", length, units[c]);
else if(length==length2)
sprintf(buf10,"%ld%cB", length, units[c]);
else
sprintf(buf10,"%.1f%cB", length2, units[c]);
break;
}
length2=(double)length/READABLE_NUMBER_DIVIDER;
length/=READABLE_NUMBER_DIVIDER;
low=1;
}
stat_line_printf("%s",buf10);
}
#ifdef OLD1
static void stat_line_readable(unsigned long length)
{
int c, low;
unsigned char buf10[10];
// B = byte
// K = kilo 10^3 2^10
// M = mega 10^6 2^20
// G = giga 10^9 2^30
// T = tera 10^12 2^40
// P = peta 10^15 2^50
// E = exa 10^18 2^60
// Z = zetta 10^21 2^70
// Y = yotta 10^24 2^80
char units[] = "BKMGTPEZY";
strcpy(buf10,"***");
low=0;
for(c=0; length>=low &&
c<sizeof(units)-1; c++) {
if(length>=low &&
length<=READABLE_NUMBER_HIGH) {
if(units[c]!='B')
sprintf(buf10,"%ld%cB", length, units[c]);
else
sprintf(buf10,"%ld", length);
break;
}
length/=READABLE_NUMBER_DIVIDER;
low=1;
}
stat_line_printf("%s",buf10);
}
#endif
void stat_line_end()
{
int c,d;
// previous line longer than this one,
// overwrite with spaces and backspace to
// end
if(stat_line_edchars>stat_line_chars) {
d=stat_line_edchars-stat_line_chars;
for(c=0;c<d;c++) {
#ifdef DEBUG31
fprintf(stderr,"*");
#else
fprintf(stderr," ");
#endif
}
for(c=0;c<d;c++)
fprintf(stderr,"\b");
}
fflush(stderr);
}
int help=0;
static int utf8len(unsigned char *buf)
{
int len;
unsigned char *p;
p=buf;
len=0;
while(*p!='\0') {
if(*p<0x80 || // ascii char
*p>0xbf) // first utf8 byte
len++;
p++;
}
return(len);
}
#define aDEBUG38 2
static void utf8getchar(int size, unsigned char *buf, int n, unsigned char *string)
{
int d;
unsigned char *p,*q;
d=0;
p=string;
q=buf;
// find first byte of character
while(*p!='\0') {
if(*p<0x80 || // ascii char
*p>0xbf) { // first utf8 char
if(d==n)
break;
d++;
}
p++;
}
// copy first byte and rest
// of character
if(*p!='\0') {
*q++=*p; // copy first byte
if(*p>0xbf) { // if first is utf8 char
p++;
for(;;) {
if(*p>0xbf || // first utf8 char
*p<0x80 || // ascii char
*p=='\0') // end of file
break;
*q++=*p++; // copy rest of the bytes
}
}
}
*q='\0';
#ifdef DEBUG38
fprintf(stdout,"%s: utf8getchar:",procname);
fprintf(stdout," string: %s",string);
fprintf(stdout,", n: %d",n);
fprintf(stdout,", character: %s",buf);
fprintf(stdout,"\n");
#endif
}
#define aDEBUG45
static void out_word(int size, unsigned char *buf, unsigned char *digits, unsigned long word2) // 8.5.2021 JariK
{
int c, d, len, digitslen;
unsigned long word;
unsigned char string[132], character[32];
digitslen = utf8len(digits);
word=word2;
len=0;
string[0]='\0';
if(word==0 || digitslen<2) {
// zero
utf8getchar(sizeof(character),character,0,digits);
if(len+strlen(character)<sizeof(string)) {
strcat(string,character);
len+=strlen(character);
}
} else {
// non zero
while(word>0) {
utf8getchar(sizeof(character),character,word%digitslen,digits);
if(len+strlen(character)<sizeof(string)) {
strcat(string,character);
len+=strlen(character);
}
word/=digitslen;
}
}
// reverse string
*buf='\0';
len=0;
d=utf8len(string);
for(c=d-1;c>=0;c--) {
utf8getchar(sizeof(character),character,c,string);
if(len+strlen(character)<size) {
strcat(buf,character);
len+=strlen(character);
}
}
#ifdef DEBUG45
fprintf(stdout,"]\n%s: out_word: ",procname);
fprintf(stdout," reverse string: %s",string);
fprintf(stdout,", digits: %s",digits);
fprintf(stdout,", int: %lu",word2);
fprintf(stdout,"\n[");
#endif
}
#define aDEBUG58 2
static void in_word(unsigned long *word, unsigned char *digits, unsigned char *buf)
{
int c,d,e,f,ok;
unsigned char character[32], character2[32];
*word=0;
d=utf8len(buf);
f=utf8len(digits);
for(c=0;c<d;c++) {
utf8getchar(sizeof(character2),character2,c,buf);
ok=0;
for(e=0;e<f;e++) {
utf8getchar(sizeof(character),character,e,digits);
if(!strcmp(character,character2)) {
ok=1;
break;
}
}
if(ok) {
*word=((*word)*f)+e;
} else {
fprintf(stdout,"%s: in_word:",procname);
fprintf(stdout," illegal digit '%s'\n",character2);
help=1;
}
}
#ifdef DEBUG58
fprintf(stdout,"%s: in_word:",procname);
fprintf(stdout," word: %lu",*word);
fprintf(stdout,", digits: %s",digits);
fprintf(stdout,", string: %s",buf);
fprintf(stdout,"\n");
#endif
}
static void line_clear(int *len, unsigned char **buf)
{
if(*len<1) {
*len=129;
*buf=realloc(*buf,*len);
}
**buf='\0';
}
static int line_add_string_sort(int *len, unsigned char **buf, unsigned char *string)
{
int cmp,count,add;
unsigned char *p;
p=*buf;
add=1;
while(*p!='\0') {
cmp=strncmp(string,p,strlen(string));
if(cmp>0) {
while(*p!=' ' && *p!='\0') // find next space
p++;
while(*p==' ' && *p!='\0') // find next non space
p++;
} else if(cmp==0) {
add=0;
break;
} else {
break;
}
}
if(add) {
count=strlen(*buf)+strlen(string)+1+1;
if(*buf==NULL || count>*len) {
int diff=p-*buf;
*len = *len + 128;
*buf=realloc(*buf,*len);
p=*buf+diff;
}
memmove(p+strlen(string)+1,p,strlen(p)+1);
memmove(p,string,strlen(string));
p+=strlen(string);
*p=' ';
}
return(add);
}
static void line_get_string(int len, unsigned char *buf, int n, unsigned char *string)
{
int e,ok,count;
unsigned char *p,*q;
ok=0;
p=string;
e=0;
while(*p!='\0') {
if(e==n) {
ok=1;
break;
}
while(*p!=' ' && *p!='\0') // find next space
p++;
while(*p==' ' && *p!='\0') // find next non space
p++;
e++;
}
if(ok) {
q=buf;
count=0;
while(*q!=' ' && *q!='\0') {
if(++count<len)
*q++=*p;
p++;
}
*q='\0';
} else {
buf[0]='\0';
}
}
static int size=5, zero=1, sspace=0, snewline=1,
scrlf=1, chars=72, pchars=0, words=0, pwords=0,
lines=10, plines=0, plinesdigits=5, slineno=1,
quiet=0, sort=0, unique=0, sample=0;
static unsigned long limit, word;
static unsigned char *digits="0123456789", character[32];
static unsigned char digitstemp[256];
static unsigned char linenobuf[1024];
static void readword(unsigned char *buf)
{
int d,e;
unsigned char temp1024[1024];
if(limit!=0) {
word=0;
if(zero) {
word=ressu_gen_limit(limit); // include zeroes
//fprintf(stdout,"(%02ld)",word);
} else if(limit>=1) {
while((word=ressu_gen_limit(limit))==0); // skip zeroes
}
out_word(sizeof(temp1024),temp1024,digits,word);
// fill leading zeroes
buf[0]='\0';
utf8getchar(sizeof(character),character,0,digits);
for(d=size-utf8len(temp1024);d>0;d--) {
strcat(buf,character);
}
// rest of the number
strcat(buf,temp1024);
} else if(digits!=NULL) {
int digitslen;
buf[0]='\0';
digitslen=utf8len(digits);
// fill whole word digit by digit
//fprintf(stdout,"[");
for(d=0;d<size;d++) {
if(digits[0]=='0' && !zero)
e=ressu_gen_limit(digitslen-1)+1;
else
e=ressu_gen_limit(digitslen);
utf8getchar(sizeof(temp1024),temp1024,e,digits);
//fprintf(stdout,"%s",temp1024);
strcat(buf,temp1024);
}
//fprintf(stdout,"]");
}
}
static int line_number_length()
{
int c;
out_word(sizeof(linenobuf),linenobuf,"0123456789",lines-1);
c=strlen(linenobuf);
if(c<5)
c=5;
return(c);
}
static void print_line_number()
{
unsigned char linenobuf[1024];
if(pwords==0 && slineno) {
sprintf(linenobuf,"%0*d",plinesdigits,plines);
fprintf(stdout,"%s",linenobuf);
fprintf(stdout," ");
}
}
static void print_spaces()
{
if(sspace>=2 &&
// rand space between double words
( (pwords>0 && pwords%sspace==0) ||
// rand space after linenumber
(slineno && pwords==0) ) )
fprintf(stdout," ");
if(sspace &&
// space between words
( (pwords>0) ||
// space after linenumber
(slineno && pwords==0) ) )
fprintf(stdout," ");
}
#ifdef OLD1
static void print_spaces()
{
if(sspace && pchars>0 && !quiet) {
if(sspace==3 && pwords%2==0) {
fprintf(stdout," ");
pchars++;
}
fprintf(stdout," ");
pchars++;
}
}
#endif
static void print_word(unsigned char *buf)
{
if(size!=0) {
fprintf(stdout,"%*s",size,buf);
} else {
fprintf(stdout,"%s",buf);
}
}
int main(int argc, char *argv[])
{
int c,d;
procname=argv[0];
limit=0;
#ifdef DEBUG4
ccp=cc;
cc_bytes=0;
#endif
clockbytes=0;
for(d=0;d<1024;d++)
periods[d]=0;
// look thru command line parameters
for(c=1;c<argc;c++) {
if(!strncmp("-",argv[c],1)) {
if(!strcmp("--lineno",argv[c])) {
slineno=!slineno;
} else if(!strcmp("--crlf",argv[c])) {
scrlf=!scrlf;
slineno=0;
} else if(!strcmp("--quiet",argv[c])) {
quiet=!quiet;
} else if(!strcmp("--stats",argv[c]) ||
!strcmp("--stat",argv[c])) {
stats=!stats;
} else if(!strcmp("--rand",argv[c])) {
digits = "0123456789";
sspace=2;
snewline=5;
slineno=1;
words=10;
chars=0;
limit=100000;
//size=5;
//lines=20000;
} else if(!strncmp("--space",argv[c],7)) {
if(*(argv[c]+7)!='\0' && atoi(argv[c]+7)>1) {
sspace=atoi(argv[c]+7);
} else if(c+1<argc && atoi(argv[c+1])>1) {
sspace=atoi(argv[c+1]);
c++;
} else {
sspace=!sspace;
}
} else if(!strncmp("--newline",argv[c],9)) {
if(*(argv[c]+9)!='\0' && atoi(argv[c]+9)>1) {
snewline=atoi(argv[c]+9);
} else if(c+1<argc && atoi(argv[c+1])>1) {
snewline=atoi(argv[c+1]);
c++;
} else {
snewline=!snewline;
}
} else if(!strcmp("--zero",argv[c])) {
zero=!zero;
} else if(!strcmp("--sort",argv[c])) {
sort=!sort;
if(sspace==0)
sspace=1;
} else if(!strcmp("--unique",argv[c])) {
unique=!unique;
if(sspace==0)
sspace=1;
} else if(!strcmp("--lotto",argv[c])) {
sort=!sort;
if(sspace==0)
sspace=1;
//sort=1;
//unique=1;
} else if(!strcmp("--sample",argv[c])) {
sample=!sample;
} else if(!strcmp("--copyright",argv[c]) ||
!strcmp("--version",argv[c])) {
fprintf(stderr,"%s",programname);
fprintf(stderr,", %s",copyright);
fprintf(stderr,"\n\n");
help=1;
} else if(!strncmp("--lim",argv[c],5)) {
if(*(argv[c]+5)!='\0') {
in_word(&limit, digits, argv[c]+5);
} else if(c+1<argc) {
in_word(&limit, digits, argv[c+1]);
c++;
}
if(sspace<1) // 23.6.2021
sspace=1;
} else if(!strncmp("-s",argv[c],2)) {
if(*(argv[c]+2)!='\0') {
size=atoi(argv[c]+2);
} else if(c+1<argc) {
size=atoi(argv[c+1]);
c++;
}
limit=0; // 23.6.2021
if(size==0)
size=1;
if(size>1024)
size=1024;
} else if(!strncmp("--bits",argv[c],6)) {
if(*(argv[c]+6)!='\0') {
ressu_bits_needed=atoi(argv[c]+6);
} else if(c+1<argc) {
ressu_bits_needed=atoi(argv[c+1]);
c++;
}
} else if(!strncmp("--bytes",argv[c],7)) {
if(*(argv[c]+7)!='\0') {
ressut_bytes=atoi(argv[c]+7);
} else if(c+1<argc) {
ressut_bytes=atoi(argv[c+1]);
c++;
}
} else if(!strncmp("-w",argv[c],2)) { // words per line
if(*(argv[c]+2)!='\0') {
words=atoi(argv[c]+2);
} else if(c+1<argc) {
words=atoi(argv[c+1]);
c++;
}
if(words<1)
words=1;
chars = 0;
} else if(!strncmp("-c",argv[c],2)) { // characters per line
if(*(argv[c]+2)!='\0') {
chars=atoi(argv[c]+2);
} else if(c+1<argc) {
chars=atoi(argv[c+1]);
c++;
}
words=0;
} else if(!strncmp("-l",argv[c],2)) { // lines
if(*(argv[c]+2)!='\0') {
lines=atoi(argv[c]+2);
} else if(c+1<argc) {
lines=atoi(argv[c+1]);
c++;
}
if(lines<1)
lines=1;
} else if(!strcmp("-x",argv[c])) {
digits = "0123456789abcdef";
size=4;
} else if(!strcmp("-d",argv[c])) {
digits = "0123456789";
size=5;
} else if(!strcmp("-o",argv[c])) {
digits = "01234567";
size=3;
} else if(!strcmp("-b",argv[c])) {
digits = "01";
size=8;
} else if(!strcmp("-1",argv[c])) {
digits=
"0123456789" \
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
"abcdefghijklmnopqrstuvwxyz";
size=8;
} else if(!strcmp("-11",argv[c])) {
digits=
"ABCDEFGHIJKLMNOPQRSTUVWXYZ";
size=8;
} else if(!strcmp("-12",argv[c])) {
digits=
"0123456789";
size=8;
} else if(!strcmp("-2",argv[c])) {
digits=
"0123456789" \
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
"abcdefghijklmnopqrstuvwxyz" \
"_-";
size=8;
} else if(!strcmp("-3",argv[c])) { // 9.5.2021 JariK
digits=
"!\"#$%&'()*+,-./0123456789:;<=>?@" \
"ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`" \
"abcdefghijklmnopqrstuvwxyz{|}~";
size=8;
} else if(!strcmp("--rus",argv[c])) { // russian alphabet
digits=
"АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ" \
"абвгдеёжзийклмнопрстуфхцчшщъыьэюя";
size=8;
} else if(!strcmp("--dnk",argv[c]) || // danish alphabet
!strcmp("--nor",argv[c])) { // norwegian alphabet
digits=
"ABCDEFGHIJKLMNOPQRSTUVWXYZÆØÅ" \
"abcdefghijklmnopqrstuvwxyzæøå";
size=8;
} else if(!strcmp("--fin",argv[c]) || // finnish alphabet
!strcmp("--swe",argv[c])) { // swedish alphabet
digits=
"ABCDEFGHIJKLMNOPQRSTUVWXYZÅÄÖ" \
"abcdefghijklmnopqrstuvwxyzåäö";
size=8;
} else if(!strcmp("--est",argv[c])) { // estonian alphabet
digits=
"ABCDEFGHIJKLMNOPQRSŠZŽTUVWÕÄÖÜXY" \
"abcdefghijklmnopqrsšzžtuvwõäöüxy";
size=8;
} else if(!strcmp("--ltu",argv[c])) { // lithuanian alphabet
digits=
"AĄBCČDEĘĖFGHIĮYJKLMNOPRSŠTUŲŪVZŽ" \
"aąbcčdeęėfghiįyjklmnoprsštuųūvzž";
size=8;
} else if(!strcmp("--lva",argv[c])) { // latvian alphabet
digits=
"AĀBCČDEĒFGĢHIĪJKĶLĻMNŅOPRSŠTUŪVZŽ" \
"aābcčdeēfgģhiījkķlļmnņoprsštuūvzž";
size=8;
} else if(!strcmp("--fra",argv[c]) // french alphabet
||!strcmp("--gbr",argv[c]) // great britain alphabet
||!strcmp("--usa",argv[c]) // united states alphabet
||!strcmp("--ita",argv[c]) // italian alphabet
) {
digits=
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
"abcdefghijklmnopqrstuvwxyz";
size=8;
} else if(!strcmp("--deu",argv[c])) { // deutche alphabet
digits=
"ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜẞ" \
"abcdefghijklmnopqrstuvwxyzäöüß";
size=8;
} else if(!strcmp("--grc",argv[c])) { // greek alphabet
digits=
"ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ" \
"αβγδεζηθικλμνξοπρστυφχψω";
size=8;
} else if(!strcmp("--cards",argv[c])) {
digits=
"🂡🂢🂣🂤🂥🂦🂧🂨🂩🂪🂫🂭🂮" \
"🂱🂲🂳🂴🂵🂶🂷🂸🂹🂺🂻🂽🂾" \
"🃁🃂🃃🃄🃅🃆🃇🃈🃉🃊🃋🃍🃎" \
"🃑🃒🃓🃔🃕🃖🃗🃘🃙🃚🃛🃝🃞";
size=1;
} else if(!strcmp("--isalnum",argv[c]) || // 9.5.2021 JariK
!strcmp("--isalpha",argv[c]) ||
!strcmp("--isdigit",argv[c]) ||
!strcmp("--isgraph",argv[c]) ||
!strcmp("--islower",argv[c]) ||
!strcmp("--isprint",argv[c]) ||
!strcmp("--ispunct",argv[c]) ||
!strcmp("--isupper",argv[c]) ||
!strcmp("--isxdigit",argv[c])) {
unsigned char *p=digitstemp;
for(d=0;d<256;d++) {
if((!strcmp("--isalnum",argv[c]) && isalnum(d)) ||
(!strcmp("--isalpha",argv[c]) && isalpha(d)) ||
(!strcmp("--isdigit",argv[c]) && isdigit(d)) ||
(!strcmp("--isgraph",argv[c]) && isgraph(d)) ||
(!strcmp("--islower",argv[c]) && islower(d)) ||
(!strcmp("--isprint",argv[c]) && isprint(d)) ||
(!strcmp("--ispunct",argv[c]) && ispunct(d)) ||
(!strcmp("--isupper",argv[c]) && isupper(d)) ||
(!strcmp("--isxdigit",argv[c]) && isxdigit(d))) {
*p++=d;
}
}
*p='\0';
digits=digitstemp;
size=8;
} else if(!strncmp("-i",argv[c],2)) {
digits=NULL;
if(*(argv[c]+2)!='\0') {
digits=argv[c]+2;
} else if(c+1 < argc) {
digits=argv[c+1];
c++;
}
if(digits==NULL || utf8len(digits)<2) {
fprintf(stderr,"%s: not enough digits \"%s\"\n",procname,argv[c]);
help = 1;
}
size=1;
} else if(!strcmp("--ressu",argv[c])) {
input=INPUT_RESSU;
} else if(!strcmp("--debug",argv[c])) {
input=INPUT_DEBUG;
} else if(!strcmp("--fast",argv[c])) {
input=INPUT_FAST;
} else if(!strcmp("--single",argv[c])) {
input=INPUT_SINGLE;
} else if(!strcmp("--urandom",argv[c])) {
input=INPUT_URANDOM;
#ifdef USE_RANDOM
} else if(!strcmp("--random",argv[c])) {
input=INPUT_RANDOM;
#endif
} else {
fprintf(stderr,"%s: invalid option %s\n",procname,argv[c]);
help = 1;
}
} else {
help = 1;
} // if(!strncmp
} // for(c=0
if(sample) {
//sample file size = CLIM*DLIM*BLKSIZE
#define CLIM 8192 // outer loop
#define DLIM 256 // inner loop
#define BLKSIZE 4096 // block size
#define STAT_LINE_READY 2
#define STAT_LINE_NOW 2
#define STAT_LINE_ANIM 2
#define TIMEFORMAT "%H:%M %Z"
#define TIMEFORMAT2 "%a %H:%M %Z"
#define DATEFORMAT "%a %d %b %Y"
unsigned int c, d;
unsigned char buffer[BLKSIZE];
FILE *fp1;
time_t secondsstart, secondsnow;
#ifdef STAT_LINE_ANIM
long int secs, prev_secs=-1;
int crs=0;
#endif
if((fp1=fopen(samplefilename,"a")) != NULL) {
secondsstart=time(NULL);
for(c=0;c<CLIM;c++) {
secondsnow=time(NULL);
// print status line:
// blk 10, written 10MB, 269KB/sec, left 8 h 38 m, ready at Sat 17 Jul 2021 01:57:43 EEST, now Fri 17:19:32 EEST
stat_line_begin();
stat_line_printf("\rblk %d, written ",c);
stat_line_readable((unsigned long)c*DLIM*BLKSIZE);
if(c>0) {
stat_line_printf(", ");
stat_line_readable((unsigned long)((double)c*DLIM*BLKSIZE/(secondsnow-secondsstart)) );
stat_line_printf("/sec");
char timebuf[128], timebuf2[128];
#ifdef STAT_LINE_NOW
// print now
stat_line_printf(", now");
strftime(timebuf,sizeof(timebuf),TIMEFORMAT2,
localtime((time_t *)&secondsnow));
stat_line_printf(" %s",timebuf);
#endif
// print left
long int secondsleft=(int)((((double)secondsnow-secondsstart)/c)*(CLIM-c) );
long int secondsleft2;
long int temp,timeprinted=0;
secondsleft2=secondsleft;
stat_line_printf(", left");
temp=secondsleft2/(24*3600);
if(temp>0) {
timeprinted=1;
stat_line_printf(" %dd",temp);
secondsleft2-=temp*(24*3600);
}
temp=secondsleft2/3600;
if(temp>0) {
timeprinted=1;
stat_line_printf(" %dh",temp);
secondsleft2-=temp*3600;
}
temp=secondsleft2/60;
if(temp>0) {
timeprinted=1;
stat_line_printf(" %dm",temp);
secondsleft2-=temp*60;
}
temp=secondsleft2;
if(!timeprinted) {
stat_line_printf(" %d seconds",temp);
}
#ifdef STAT_LINE_READY
long int secondsend=(int)secondsstart+((((double)secondsnow-secondsstart)/c)*CLIM);
// print end date if different7
stat_line_printf(", ready at");
strftime(timebuf,sizeof(timebuf),DATEFORMAT,
localtime((time_t *)&secondsend));
strftime(timebuf2,sizeof(timebuf2),DATEFORMAT,
localtime((time_t *)&secondsnow));
if(strcmp(timebuf,timebuf2)) {
stat_line_printf(" %s",timebuf);
}
// print end time
strftime(timebuf,sizeof(timebuf),TIMEFORMAT,
localtime((time_t *)&secondsend));
stat_line_printf(" %s",timebuf);
#endif
}
stat_line_end();
// do the work
#ifdef STAT_LINE_ANIM
unsigned char cursor[4] = { '|', '/', '-', '\\' };
fprintf(stderr," ");
#endif
for(d=0;d<DLIM;d++) {
#ifdef STAT_LINE_ANIM
secs=time(NULL)%sizeof(cursor);
if(prev_secs!=secs) {
if(prev_secs!=-1)
crs=(crs+1)%sizeof(cursor);
fprintf(stderr,"\b%c",cursor[crs]);
fflush(stderr);
prev_secs=secs;
}
#endif
if(input==INPUT_RESSU) // ressu prod
ressu_genbytes(sizeof(buffer),buffer);
else if(input==INPUT_DEBUG) // ressu debug
ressu_genbytes_debug(sizeof(buffer),buffer);
else if(input==INPUT_FAST) // ressu fast
ressu_genbytes_fast(sizeof(buffer),buffer);
else if(input==INPUT_SINGLE) // ressu single
ressu_genbytes_single(sizeof(buffer),buffer);
else if(input==INPUT_URANDOM) // urandom
readfile_xor(sizeof(buffer),buffer,urandomfilename);
#ifdef USE_RANDOM
else if(input==INPUT_RANDOM) // random
readfile_xor(sizeof(buffer),buffer,randomfilename);
#endif
#ifdef WRITE_SAMPLE
fwrite(buffer,1,sizeof(buffer),fp1);
#endif
} // for(d=0;
#ifdef STAT_LINE_ANIM
fprintf(stderr,"\b \b");
prev_secs=-1;
#endif
}
fclose(fp1);
} // if((fp1=fopen
// remove last status line
stat_line_begin();
stat_line_printf("Done!");
stat_line_end();
fprintf(stdout,"\n");
fflush(stdout);
exit(0);
} // if(sample)
// get linenumber length in digits
plinesdigits=line_number_length();
// get data length in digits
if(limit!=0) {
unsigned char wordbuf[128];
out_word(sizeof(wordbuf),wordbuf,digits,limit-1);
size=utf8len(wordbuf);
}
pchars=0;
pwords=0;
int linew=0;
// in beginning of line, count printed line number
if(!quiet && slineno) {
sprintf(linenobuf,"%0*d",plinesdigits,plines);
pchars += strlen(linenobuf);
pchars++;
}
// count words
while((chars>0 && pchars+size < chars) ||
(words>0 && pwords < words)) {
linew++;
if(sspace>=2 &&
( (pwords>0 && pwords%sspace==0) ||
(slineno && pwords==0) ) )
pchars++;
if(sspace &&
( (pwords>0) ||
(slineno && pwords==0) ) )
pchars++;
pchars+=size;
pwords++;
}
unsigned long wordvalues=1;
for(c=0;c<size;c++) {
if(wordvalues!=0 && wordvalues*utf8len(digits)<(unsigned long)65536*65536*65536) {
wordvalues*=utf8len(digits);
} else {
wordvalues=0;
}
}
if(limit > 0) {
if(sort==1 && limit-!zero<words) {
fprintf(stderr,"%s: limit is less than words (zero)",procname);
fprintf(stderr,", limit:%lu",limit);
fprintf(stderr,", words:%d",words);
fprintf(stderr,", zero:%d",zero);
fprintf(stderr,"\n");
help=1;
lines=0;
}
} else {
if(sort==1 && size>0 && wordvalues>0 && wordvalues<linew) {
fprintf(stderr,"%s:",procname);
fprintf(stderr," digits is less than calculated words");
fprintf(stderr,", digits:%d(%lu)",utf8len(digits),wordvalues);
fprintf(stderr,", words:%d\n",linew);
help=1;
lines=0;
}
}
// small words as single ressu_gen_limit()
if(limit==0 && wordvalues>0)
limit=wordvalues;
if(stats) {
fprintf(stdout,"randomsource: %s",randomgen[input]);
fprintf(stdout,", size: %d",size);
fprintf(stdout,", linew: %d",linew);
fprintf(stdout,", pchars: %d",pchars);
fprintf(stdout,", pwords: %d",pwords);
fprintf(stdout,", digitslen: %d",utf8len(digits));
if(wordvalues>0)
fprintf(stdout,", wordvalues: %lu",wordvalues);
if(limit>0)
fprintf(stdout,", limit: %lu",limit);
fprintf(stdout,"\n");
}
if(help) {
struct helpline {
char *command;
char *text;
} helplines[] = {
{ "newressu -d", "print random decimal digits" },
{ "newressu -o", "print octal digits" },
{ "newressu -x", "print hexadecimal digits" },
{ "newressu -b", "print binary digits" },
{ "newressu -d --space", "print decimal digits, with spaces between \"words\"" },
{ "newressu -b --space", "print binary digits, with spaces between \"words\"" },
{ "newressu -d -l30", "print decimal digits, 30 lines" },
{ "newressu -d -l30 --lineno", "print decimal digits, 30 lines, no linenumbers" },
{ "newressu -d -c128", "print decimal digits, 128 characters per line" },
{ "newressu -d --lim10", "print decimal numbers between 0-9" },
{ "newressu -d --lim10 -x","print hexadecimal numbers with decimal limit" },
{ "newressu -d -s10 --space","print decimal numbers with spaces and wordsize 10" },
{ "newressu -d --space --zero --lim7","print rollings of dice (1-6)" },
{ "newressu -b -s1 --space","print throws of coin (0,1)" },
{ "newressu -d --lim41 -w7 --zero --lotto","print lotto numbers for finnish lotto 7x(1-40)" },
{ "newressu -d -s5 --sort -w16","print 16 sorted decimal numbers from 0 to 99999" },
{ "newressu --isalnum", "print alphanumeric characters" },
{ "newressu --isalpha", "print alphabetic characters" },
{ "newressu --isgraph", "print printables excluding space" },
{ "newressu --islower", "print lowercase characters" },
{ "newressu --ispunct", "print punctuation characters" },
{ "newressu --isupper", "print uppercase characters" },
{ "newressu -1", "print material for passwords" },
{ "newressu -iаэыуояеёюи", "print russian vowels" },
{ "newressu --ressu", "use randomness from ressu (default)" },
{ "newressu --debug", "use randomness from debugging ressu" },
{ "newressu --fast", "use randomness from fast ressu" },
{ "newressu --single", "use randomness from single round of ressu" },
{ "newressu --urandom", "use randomness from /dev/urandom" },
#ifdef USE_RANDOM
{ "newressu --random", "use randomness from /dev/random" },
#endif
};
for(c=0;c<sizeof(helplines)/sizeof(helplines[0]);c++) {
fprintf(stderr,"%-50s",helplines[c].text);
fprintf(stderr,"%-25s",helplines[c].command);
fprintf(stderr,"\n");
}
for(c=0;c<chars;c++)
fprintf(stdout,"*");
fprintf(stdout,"\n");
if(lines>1)
lines=1; // print one line below help as a sample
}
if(lines==0)
exit(1);
int linecnt=0;
unsigned char *line=NULL;
unsigned char wordbuf[1025];
for(;;) {
if(!sort) { // also lotto
pwords=0;
while(pwords<linew) {
readword(wordbuf);
if(!quiet) {
// in beginning of line, print line number
print_line_number();
// want to print spaces between "words"?
print_spaces();
// print word
print_word(wordbuf);
}
pwords++;
} // while(pwords<linew) {
} else { // if(!sort)
pwords=0;
line_clear(&linecnt,&line);
// fetch and save words on this row
while(pwords<linew) {
readword(wordbuf);
if(line_add_string_sort(&linecnt,&line,wordbuf)) {
pwords++;
}
} // while(pwords<linew) {
pwords=0;
// print words on this row
while(pwords<linew) {
line_get_string(sizeof(wordbuf),wordbuf,pwords,line);
if(!quiet) {
// in beginning of line, print line number
print_line_number();
// want to print spaces between "words"?
print_spaces();
// print word
print_word(wordbuf);
}
pwords++;
} // while(pwords<linew) {
} // if(!sort)
if(!quiet) {
fprintf(stdout,"\n");
}
plines++;
if(!quiet && snewline>1 &&
plines<lines &&
plines%snewline==0)
fprintf(stdout,"\n");
// all needed lines printed?
if(plines >= lines)
break;
} // for(;;)
fflush(stdout);
}
#endif // MAIN