diff options
-rw-r--r-- | bounce.c | 12 | ||||
-rw-r--r-- | pounce.1 | 11 | ||||
-rw-r--r-- | ring.c | 36 |
3 files changed, 48 insertions, 11 deletions
diff --git a/bounce.c b/bounce.c index 34a56a8..b26a1cb 100644 --- a/bounce.c +++ b/bounce.c @@ -102,6 +102,7 @@ int main(int argc, char *argv[]) { char certPath[PATH_MAX] = ""; char privPath[PATH_MAX] = ""; const char *save = NULL; + size_t ring = 4096; bool insecure = false; const char *host = NULL; @@ -115,7 +116,7 @@ int main(int argc, char *argv[]) { const char *away = "pounced :3"; const char *quit = "connection reset by purr"; - const char *Opts = "!A:C:H:K:NP:Q:W:a:f:h:j:n:p:r:u:vw:"; + const char *Opts = "!A:C:H:K:NP:Q:W:a:f:h:j:n:p:r:s:u:vw:"; const struct option LongOpts[] = { { "insecure", no_argument, NULL, '!' }, { "away", required_argument, NULL, 'A' }, @@ -133,6 +134,7 @@ int main(int argc, char *argv[]) { { "nick", required_argument, NULL, 'n' }, { "port", required_argument, NULL, 'p' }, { "real", required_argument, NULL, 'r' }, + { "size", required_argument, NULL, 's' }, { "user", required_argument, NULL, 'u' }, { "verbose", no_argument, NULL, 'v' }, { "pass", required_argument, NULL, 'w' }, @@ -158,6 +160,11 @@ int main(int argc, char *argv[]) { break; case 'n': nick = optarg; break; case 'p': port = optarg; break; case 'r': real = optarg; + break; case 's': { + char *rest; + ring = strtoull(optarg, &rest, 0); + if (*rest) errx(EX_USAGE, "invalid size: %s", optarg); + } break; case 'u': user = optarg; break; case 'v': verbose = true; break; case 'w': pass = optarg; @@ -171,7 +178,6 @@ int main(int argc, char *argv[]) { if (!privPath[0]) { snprintf(privPath, sizeof(privPath), DEFAULT_PRIV_PATH, bindHost); } - if (!host) errx(EX_USAGE, "no host"); if (!nick) { nick = getenv("USER"); @@ -180,7 +186,7 @@ int main(int argc, char *argv[]) { if (!user) user = nick; if (!real) real = nick; - ringAlloc(4096); + ringAlloc(ring); if (save) saveLoad(save); int bind[8]; diff --git a/pounce.1 b/pounce.1 index f83882a..a3bfdd8 100644 --- a/pounce.1 +++ b/pounce.1 @@ -1,4 +1,4 @@ -.Dd October 29, 2019 +.Dd October 30, 2019 .Dt POUNCE 1 .Os . @@ -23,6 +23,7 @@ .Op Fl n Ar nick .Op Fl p Ar port .Op Fl r Ar real +.Op Fl s Ar size .Op Fl u Ar user .Op Fl w Ar pass .Op Ar config ... @@ -144,6 +145,14 @@ Set realname to .Ar real . The default realname is the same as the nickname. . +.It Fl s Ar size , Cm size = Ar size +Set the buffer +.Ar size . +This determines the maximum number of messages +stored in memory. +The size must be a power of two. +The default size is 4096. +. .It Fl u Ar user , Cm user = Ar user Set username to .Ar user . diff --git a/ring.c b/ring.c index f99d9d4..620f490 100644 --- a/ring.c +++ b/ring.c @@ -30,7 +30,9 @@ static struct { } ring; void ringAlloc(size_t len) { - if (len & (len - 1)) errx(EX_CONFIG, "ring length must be power of two"); + if (len & (len - 1)) { + errx(EX_CONFIG, "ring length must be power of two: %zu", len); + } ring.lines = calloc(len, sizeof(*ring.lines)); if (!ring.lines) err(EX_OSERR, "calloc"); ring.times = calloc(len, sizeof(*ring.times)); @@ -116,7 +118,10 @@ void ringInfo(void) { } } -static const size_t FileVersion = 0x0165636E756F70; +static const size_t FileVersion[] = { + 0x0165636E756F70, + 0x0265636E756F70, +}; static int writeSize(FILE *file, size_t value) { return (fwrite(&value, sizeof(value), 1, file) ? 0 : -1); @@ -129,7 +134,8 @@ static int writeString(FILE *file, const char *str) { } int ringSave(FILE *file) { - if (writeSize(file, FileVersion)) return -1; + if (writeSize(file, FileVersion[1])) return -1; + if (writeSize(file, ring.len)) return -1; if (writeSize(file, producer)) return -1; if (writeSize(file, consumers.len)) return -1; for (size_t i = 0; i < consumers.len; ++i) { @@ -166,8 +172,16 @@ void ringLoad(FILE *file) { fread(&version, sizeof(version), 1, file); if (ferror(file)) err(EX_IOERR, "fread"); if (feof(file)) return; + if (version != FileVersion[0] && version != FileVersion[1]) { + errx(EX_DATAERR, "unknown file version %zX", version); + } + + size_t saveLen = 4096; + if (version == FileVersion[1]) readSize(file, &saveLen); + if (saveLen > ring.len) { + errx(EX_DATAERR, "cannot load save with larger ring"); + } - if (version != FileVersion) errx(EX_DATAERR, "unknown file version"); readSize(file, &producer); char *buf = NULL; @@ -181,15 +195,23 @@ void ringLoad(FILE *file) { readSize(file, &consumers.ptr[consumer].pos); } - for (size_t i = 0; i < ring.len; ++i) { + for (size_t i = 0; i < saveLen; ++i) { readTime(file, &ring.times[i]); } - for (size_t i = 0; i < ring.len; ++i) { + for (size_t i = 0; i < saveLen; ++i) { readString(file, &buf, &cap); if (feof(file)) break; ring.lines[i] = strdup(buf); if (!ring.lines[i]) err(EX_OSERR, "strdup"); } - free(buf); + + if (ring.len > saveLen) { + producer %= saveLen; + for (size_t i = 0; i < consumers.len; ++i) { + struct Consumer *consumer = &consumers.ptr[i]; + consumer->pos %= saveLen; + if (consumer->pos > producer) consumer->pos = 0; + } + } } |