1
0
mirror of https://github.com/fumiama/CMoe-Counter.git synced 2024-11-23 22:00:56 +01:00

add editor

This commit is contained in:
源文雨 2023-03-07 21:29:29 +08:00
parent 6db67452a1
commit 946cbbac67
3 changed files with 269 additions and 13 deletions

View File

@ -10,7 +10,10 @@ add_compile_options(-std=c99)
message(STATUS "optional:-std=c99")
add_executable(cmoe cmoe.c)
add_executable(cmoeditor editor.c)
target_link_libraries(cmoe spb)
target_link_libraries(cmoeditor spb)
INSTALL(TARGETS cmoe RUNTIME DESTINATION bin)
INSTALL(TARGETS cmoeditor RUNTIME DESTINATION bin)

29
cmoe.c
View File

@ -18,27 +18,24 @@ static FILE* fp;
#define ADD_HEADER_PARAM(buf, offset, h, p) sprintf(buf + offset, (h), (p))
#define HEADER(content_type) HTTP200 SERVER_STRING CACHE_CTRL CONTENT_TYPE(content_type)
#define headers(content_len, content_type) (_headers(content_len, HEADER(content_type), sizeof(HEADER(content_type))-1))
static void _headers(uint32_t content_len, const char* h, size_t hlen) {
static int _headers(uint32_t content_len, const char* h, size_t hlen) {
char buf[64];
size_t offset = ADD_HEADER_PARAM(buf, 0, CONTENT_LEN "\r\n", content_len);
if(offset <= 0) {
write(1, "\0\0\0\0", 4);
exit(EXIT_FAILURE);
}
if(offset <= 0) return -1;
content_len += offset+hlen;
struct iovec iov[3] = {{&content_len, sizeof(uint32_t)}, {(void*)h, hlen}, {(void*)buf, offset}};
writev(1, (const struct iovec *)&iov, 3);
return writev(1, (const struct iovec *)&iov, 3) <= 0;
}
static void http_error(errcode_enum_t code, char* msg) {
static inline void http_error(errcode_enum_t code, char* msg) {
uint32_t len = strlen(msg) + typel[code];
char* str = malloc(len);
char str[len];
sprintf(str, types[code], msg);
struct iovec iov[2] = {{(void*)&len, sizeof(uint32_t)}, {(void*)str, len}};
writev(1, (const struct iovec *)&iov, 2);
free(str);
}
// get_arg used malloc but has never freed
static char* get_arg(const char* query) {
int len = 0;
while(query[len] && query[len] != '&') len++;
@ -75,14 +72,14 @@ static int del_user(FILE* fp, SIMPLE_PB* spb) {
return 2;
}
static int add_user(char* name, uint32_t count, FILE* fp) {
static inline int add_user(char* name, uint32_t count, FILE* fp) {
counter.count = count;
strncpy(counter.name, name, COUNTER_NAME_LEN-1);
fseek(fp, 0, SEEK_END);
return !set_pb(fp, items_len, sizeof(counter_t), &counter);
}
static uint32_t get_content_len(int isbig, uint16_t* len_type, char* cntstr) {
static inline uint32_t get_content_len(int isbig, uint16_t* len_type, char* cntstr) {
uint32_t len = sizeof(svg_small) // small & big has the same len
+ sizeof(svg_tail) - 1;
for(int i = 0; cntstr[i]; i++) {
@ -142,7 +139,10 @@ static void return_count(FILE* fp, char* name, char* theme) {
h = H_SMALL;
head = (char*)svg_small;
}
headers(get_content_len(isbig, len_type, cntstr), image/svg+xml);
if(headers(get_content_len(isbig, len_type, cntstr), image/svg+xml)) {
write(1, "\0\0\0\0", 4);
return;
}
printf(head, w*(10+cntstrbuf-cntstr));
for(int i = 0; cntstr[i]; i++) {
printf(img_slot_front, w * i, w, h);
@ -248,7 +248,10 @@ int main(int argc, char **argv) {
add_user(name, 0, fp);
fclose(fp); fp = NULL;
char* msg = "<P>Success.\r\n";
headers(strlen(msg), text/html);
if(headers(strlen(msg), text/html)) {
write(1, "\0\0\0\0", 4);
return 8;
}
return write(1, msg, strlen(msg)) <= 0;
}

250
editor.c Normal file
View File

@ -0,0 +1,250 @@
#include <simple_protobuf.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "cmoe.h"
static uint32_t* items_len;
static counter_t counter;
static FILE* fp;
static char buf[sizeof(SIMPLE_PB)+sizeof(counter_t)];
static int del_user(FILE* fp, SIMPLE_PB* spb) {
counter_t *d = (counter_t *)spb->target;
uint32_t next = ftell(fp);
uint32_t this = next - spb->real_len;
fseek(fp, 0, SEEK_END);
uint32_t end = ftell(fp);
if(next == end) return ftruncate(fileno(fp), end - spb->real_len);
uint32_t cap = end - next;
char *data = malloc(cap);
if(data) {
fseek(fp, next, SEEK_SET);
if(fread(data, cap, 1, fp) == 1) {
if(!ftruncate(fileno(fp), end - spb->real_len)){
fseek(fp, this, SEEK_SET);
if(fwrite(data, cap, 1, fp) == 1) {
free(data);
fflush(fp);
return 0;
}
}
}
free(data);
}
return 2;
}
#define has_next(fp, ch) ((ch=getc(fp)),(feof(fp)?0:(ungetc(ch,fp),1)))
int main(int argc, char** argv) {
if (argc != 2) {
puts("Usage: editor dat.sp");
return 0;
}
fp = fopen(argv[1], "rb+");
if (!fp) {
perror("fopen");
return 1;
}
items_len = align_struct(sizeof(counter_t), 2, &counter.name, &counter.count);
if(!items_len) {
perror("align_struct");
return 2;
}
int go;
lop: do {
go = 1;
puts("\ncommands:");
puts("\ta string uint: add user with count.");
puts("\td string: delete user.");
puts("\tD string: delete users match the keyword (empty is not allowed).");
puts("\tg string: get user count.");
puts("\tm uint: print users < count.");
puts("\tM uint: delete users < count.");
puts("\tp string: print users match the keyword (empty for all).");
puts("\tq: quit.");
putchar('>');putchar(' ');
char c = getchar();
switch (c) {
case 'a':
while ((c = getchar()) == ' '); // skip space
memset(counter.name, 0, sizeof(counter.name));
counter.name[0] = c;
while ((c = getchar()) != ' ' && go < sizeof(counter.name)-1) counter.name[go++] = c;
while ((c = getchar()) == ' '); // skip space
ungetc(c, stdin);
scanf("%u", &counter.count);
while (getchar() != '\n'); // skip to endl
printf("set user '%s' to %u\n", counter.name, counter.count);
if (fseek(fp, 0, SEEK_END)) {
perror("fseek");
return 3;
}
if (set_pb(fp, items_len, sizeof(counter_t), &counter) != 2) {
puts("set pb error.");
return 4;
}
break;
case 'd':
while ((c = getchar()) == ' '); // skip space
memset(counter.name, 0, sizeof(counter.name));
counter.name[0] = c;
while ((c = getchar()) != '\n' && go < sizeof(counter.name)-1) counter.name[go++] = c;
if (fseek(fp, 0, SEEK_SET)) {
perror("fseek");
return 5;
}
while(has_next(fp, c)) {
SIMPLE_PB *spb = read_pb_into(fp, (SIMPLE_PB*)buf);
counter_t *d = (counter_t *)spb->target;
if (strcmp(counter.name, d->name)) continue;
if(del_user(fp, spb)) {
perror("del_user");
return 6;
}
printf("del user '%s'.\n", d->name);
goto lop;
}
printf("no such user '%s'.\n", counter.name);
break;
case 'D':
if (getchar() == '\n') {
puts("empty D is not allowed.");
break;
}
while ((c = getchar()) == ' '); // skip space
memset(counter.name, 0, sizeof(counter.name));
counter.name[0] = c;
while ((c = getchar()) != '\n' && go < sizeof(counter.name)-1) counter.name[go++] = c;
go = 1;
scanlopD:
if (fseek(fp, 0, SEEK_SET)) {
perror("fseek");
return 7;
}
while(has_next(fp, c)) {
SIMPLE_PB *spb = read_pb_into(fp, (SIMPLE_PB*)buf);
counter_t *d = (counter_t *)spb->target;
if (strstr(d->name, counter.name)) {
if(del_user(fp, spb)) {
perror("del_user");
return 8;
}
printf("del user '%s'.\n", d->name);
go++;
goto scanlopD;
}
}
if (go == 1) puts("no result.");
break;
case 'g':
while ((c = getchar()) == ' '); // skip space
memset(counter.name, 0, sizeof(counter.name));
counter.name[0] = c;
while ((c = getchar()) != '\n' && go < sizeof(counter.name)-1) counter.name[go++] = c;
if (fseek(fp, 0, SEEK_SET)) {
perror("fseek");
return 5;
}
while(has_next(fp, c)) {
SIMPLE_PB *spb = read_pb_into(fp, (SIMPLE_PB*)buf);
counter_t *d = (counter_t *)spb->target;
if (strcmp(counter.name, d->name)) continue;
printf("user '%s' = %u.\n", d->name, d->count);
goto lop;
}
printf("no such user '%s'.\n", counter.name);
break;
case 'm':
while ((c = getchar()) == ' '); // skip space
ungetc(c, stdin);
scanf("%u", &counter.count);
while (getchar() != '\n'); // skip to endl
go = 1;
if (fseek(fp, 0, SEEK_SET)) {
perror("fseek");
return 7;
}
while(has_next(fp, c)) {
SIMPLE_PB *spb = read_pb_into(fp, (SIMPLE_PB*)buf);
counter_t *d = (counter_t *)spb->target;
if (d->count < counter.count) {
printf("'%s' = %u\n", d->name, d->count);
go++;
}
}
if (go == 1) puts("no result.");
break;
case 'M':
if (getchar() == '\n') {
puts("empty M is not allowed.");
break;
}
while ((c = getchar()) == ' '); // skip space
ungetc(c, stdin);
scanf("%u", &counter.count);
while (getchar() != '\n'); // skip to endl
go = 1;
scanlopM:
if (fseek(fp, 0, SEEK_SET)) {
perror("fseek");
return 7;
}
while(has_next(fp, c)) {
SIMPLE_PB *spb = read_pb_into(fp, (SIMPLE_PB*)buf);
counter_t *d = (counter_t *)spb->target;
if (d->count < counter.count) {
if(del_user(fp, spb)) {
perror("del_user");
return 8;
}
printf("del user '%s'.\n", d->name);
go++;
goto scanlopM;
}
}
if (go == 1) puts("no result.");
break;
case 'p':
if ((c = getchar()) != '\n') {
while ((c = getchar()) == ' '); // skip space
memset(counter.name, 0, sizeof(counter.name));
counter.name[0] = c;
while ((c = getchar()) != '\n' && go < sizeof(counter.name)-1) counter.name[go++] = c;
} else counter.name[0] = 0;
go = 1;
if (fseek(fp, 0, SEEK_SET)) {
perror("fseek");
return 7;
}
while(has_next(fp, c)) {
SIMPLE_PB *spb = read_pb_into(fp, (SIMPLE_PB*)buf);
counter_t *d = (counter_t *)spb->target;
if (!counter.name[0] || strstr(d->name, counter.name)) {
printf("'%s' = %u\n", d->name, d->count);
go++;
}
}
if (go == 1) puts("no result.");
break;
case 'q':
go = 0;
break;
default:
printf("invalid operator '%c'.\n", c);
while (getchar() != '\n'); // skip to endl
break;
}
} while (go);
}
static void __attribute__((destructor)) defer_close_fp() {
if(fp) {
if (fclose(fp)) perror("fclose");
else puts("file closed.");
}
}