diff options
-rw-r--r-- | Makefile | 59 | ||||
-rw-r--r-- | README.md | 25 | ||||
-rw-r--r-- | aes.c | 411 | ||||
-rw-r--r-- | asciihexer.c | 46 | ||||
-rw-r--r-- | config.h | 31 | ||||
-rw-r--r-- | dummyshell.c | 622 | ||||
-rw-r--r-- | gol.c | 469 | ||||
-rw-r--r-- | suidcmd.c | 98 | ||||
-rw-r--r-- | xidle.c | 45 |
9 files changed, 1806 insertions, 0 deletions
diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..4815a84 --- /dev/null +++ b/Makefile @@ -0,0 +1,59 @@ +CC := gcc +CFLAGS := -O2 -g -Wall -ffunction-sections -fdata-sections -ffast-math -fomit-frame-pointer -fexpensive-optimizations +LDFLAGS := +RM := rm -rf +LIBS := -lcurses + +TARGETS := aes asciihexer dummyshell suidcmd + +ifneq ($(strip $(MAKE_NCURSES)),) +TARGETS += gol +endif +ifneq ($(strip $(MAKE_X11)),) +TARGETS += xidle +endif + + +all: $(TARGETS) + +%.o: %.c + @echo 'Building file: $<' + @echo 'Invoking: GCC C Compiler' + $(CC) $(CFLAGS) -D_GNU_SOURCE=1 -D_HAVE_CONFIG=1 -std=c99 -c -fmessage-length=0 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -o "$@" "$<" + @echo 'Finished building: $<' + @echo ' ' + + +aes: aes.o +asciihexer: asciihexer.o +dummyshell: dummyshell.o +suidcmd: suidcmd.o + @echo 'Building target: $@' + @echo 'Invoking: GCC C Linker' + $(CC) $(LDFLAGS) -o "$@" "$<" + @echo 'Finished building target: $@' + @echo ' ' + +gol: gol.o + @echo 'Building target: $@' + @echo 'Invoking: GCC C Linker' + $(CC) $(LDFLAGS) -o "$@" "$<" -lncurses + @echo 'Finished building target: $@' + @echo ' ' + +xidle: xidle.o + @echo 'Building target: $@' + @echo 'Invoking: GCC C Linker' + $(CC) $(LDFLAGS) -o "$@" "$<" -lX11 -lXext -lXss + @echo 'Finished building target: $@' + @echo ' ' + +clean: + -$(RM) aes.o asciihexer.o dummyshell.o gol.o suidcmd.o xidle.o + -$(RM) aes.d asciihexer.d dummyshell.d gol.d suidcmd.d xidle.d + -$(RM) aes asciihexer dummyshell gol suidcmd xidle + -@echo ' ' + +rebuild: clean all + +.PHONY: all clean diff --git a/README.md b/README.md new file mode 100644 index 0000000..bbef6f1 --- /dev/null +++ b/README.md @@ -0,0 +1,25 @@ +some tools +======== + +aes.c +======== +A minimal working aes implementation.<br /> + +asciihexer.c +======== +Magic ascii-2-hex app.<br /> + +dummyshell.c +======== +A minimalistic restricted system-usage/messaging/command-exec shell.<br /> + +gol.c +======== +Conway's GameOfLife - written by Steffen Vogel / bugfixed,improved by myself. <br /> + +suidcmd.c +======== +Run arbitrary commands (useful for running non-suid programs on non-suid fs).<br /> + +<br /> +Thats all folks.<br /> @@ -0,0 +1,411 @@ +// AES Implementation by X-N2O +// Started: 15:41:35 - 18 Nov 2009 +// Finished: 20:03:59 - 21 Nov 2009 +// Logarithm, S-Box, and RCON tables are not hardcoded +// Instead they are generated when the program starts +// All of the code below is based from the AES specification +// You can find it at http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf +// You may use this code as you wish, but do not remove this comment +// This is only a proof of concept, and should not be considered as the most efficient implementation + +#include <stdlib.h> +#include <string.h> +#include <stdio.h> + +#define AES_RPOL 0x011b // reduction polynomial (x^8 + x^4 + x^3 + x + 1) +#define AES_GEN 0x03 // gf(2^8) generator (x + 1) +#define AES_SBOX_CC 0x63 // S-Box C constant + +#define KEY_128 (128/8) +#define KEY_192 (192/8) +#define KEY_256 (256/8) + +#define aes_mul(a, b) ((a)&&(b)?g_aes_ilogt[(g_aes_logt[(a)]+g_aes_logt[(b)])%0xff]:0) +#define aes_inv(a) ((a)?g_aes_ilogt[0xff-g_aes_logt[(a)]]:0) + +unsigned char g_aes_logt[256], g_aes_ilogt[256]; +unsigned char g_aes_sbox[256], g_aes_isbox[256]; + +typedef struct { + unsigned char state[4][4]; + int kcol; + size_t rounds; + unsigned long keysched[0]; +} aes_ctx_t; + +void aes_init(); +aes_ctx_t *aes_alloc_ctx(unsigned char *key, size_t keyLen); +inline unsigned long aes_subword(unsigned long w); +inline unsigned long aes_rotword(unsigned long w); +void aes_keyexpansion(aes_ctx_t *ctx); + +inline unsigned char aes_mul_manual(unsigned char a, unsigned char b); // use aes_mul instead + +void aes_subbytes(aes_ctx_t *ctx); +void aes_shiftrows(aes_ctx_t *ctx); +void aes_mixcolumns(aes_ctx_t *ctx); +void aes_addroundkey(aes_ctx_t *ctx, int round); +void aes_encrypt(aes_ctx_t *ctx, unsigned char input[16], unsigned char output[16]); + +void aes_invsubbytes(aes_ctx_t *ctx); +void aes_invshiftrows(aes_ctx_t *ctx); +void aes_invmixcolumns(aes_ctx_t *ctx); +void aes_decrypt(aes_ctx_t *ctx, unsigned char input[16], unsigned char output[16]); + +void aes_free_ctx(aes_ctx_t *ctx); + +void init_aes() +{ + int i; + unsigned char gen; + + // build logarithm table and it's inverse + gen = 1; + for(i = 0; i < 0xff; i++) { + g_aes_logt[gen] = i; + g_aes_ilogt[i] = gen; + gen = aes_mul_manual(gen, AES_GEN); + } + + // build S-Box and it's inverse + for(i = 0; i <= 0xff; i++) { + char bi; + unsigned char inv = aes_inv(i); + + g_aes_sbox[i] = 0; + for(bi = 0; bi < 8; bi++) { + // based on transformation 5.1 + // could also be done with a loop based on the matrix + g_aes_sbox[i] |= ((inv & (1<<bi)?1:0) + ^ (inv & (1 << ((bi+4) & 7))?1:0) + ^ (inv & (1 << ((bi+5) & 7))?1:0) + ^ (inv & (1 << ((bi+6) & 7))?1:0) + ^ (inv & (1 << ((bi+7) & 7))?1:0) + ^ (AES_SBOX_CC & (1 << bi)?1:0) + ) << bi; + } + g_aes_isbox[g_aes_sbox[i]] = i; + } + // warning: quickhack + g_aes_sbox[1] = 0x7c; + g_aes_isbox[0x7c] = 1; + g_aes_isbox[0x63] = 0; +} + +aes_ctx_t *aes_alloc_ctx(unsigned char *key, size_t keyLen) +{ + aes_ctx_t *ctx; + size_t rounds; + size_t ks_size; + + switch(keyLen) { + case 16: // 128-bit key + rounds = 10; + break; + + case 24: // 192-bit key + rounds = 12; + break; + + case 32: // 256-bit key + rounds = 14; + break; + + default: + return NULL; + } + + ks_size = 4*(rounds+1)*sizeof(unsigned long); + ctx = malloc(sizeof(aes_ctx_t)+ks_size); + if(ctx) { + ctx->rounds = rounds; + ctx->kcol = keyLen/4; + memcpy(ctx->keysched, key, keyLen); + ctx->keysched[43] = 0; + aes_keyexpansion(ctx); + } + + return ctx; +} + +inline unsigned long aes_subword(unsigned long w) +{ + return g_aes_sbox[w & 0x000000ff] | + (g_aes_sbox[(w & 0x0000ff00) >> 8] << 8) | + (g_aes_sbox[(w & 0x00ff0000) >> 16] << 16) | + (g_aes_sbox[(w & 0xff000000) >> 24] << 24); +} + +inline unsigned long aes_rotword(unsigned long w) +{ + // May seem a bit different from the spec + // It was changed because unsigned long is represented with little-endian convention on x86 + // Should not depend on architecture, but this is only a POC + return ((w & 0x000000ff) << 24) | + ((w & 0x0000ff00) >> 8) | + ((w & 0x00ff0000) >> 8) | + ((w & 0xff000000) >> 8); +} + +void aes_keyexpansion(aes_ctx_t *ctx) +{ + unsigned long temp; + unsigned long rcon; + register int i; + + rcon = 0x00000001; + for(i = ctx->kcol; i < (4*(ctx->rounds+1)); i++) { + temp = ctx->keysched[i-1]; + if(!(i%ctx->kcol)) { + temp = aes_subword(aes_rotword(temp)) ^ rcon; + rcon = aes_mul(rcon, 2); + } else if(ctx->kcol > 6 && i%ctx->kcol == 4) + temp = aes_subword(temp); + ctx->keysched[i] = ctx->keysched[i-ctx->kcol] ^ temp; + } +} + +inline unsigned char aes_mul_manual(unsigned char a, unsigned char b) +{ + register unsigned short ac; + register unsigned char ret; + + ac = a; + ret = 0; + while(b) { + if(b & 0x01) + ret ^= ac; + ac <<= 1; + b >>= 1; + if(ac & 0x0100) + ac ^= AES_RPOL; + } + + return ret; +} + +void aes_subbytes(aes_ctx_t *ctx) +{ + int i; + + for(i = 0; i < 16; i++) { + int x, y; + + x = i & 0x03; + y = i >> 2; + ctx->state[x][y] = g_aes_sbox[ctx->state[x][y]]; + } +} + +void aes_shiftrows(aes_ctx_t *ctx) +{ + unsigned char nstate[4][4]; + int i; + + for(i = 0; i < 16; i++) { + int x, y; + + x = i & 0x03; + y = i >> 2; + nstate[x][y] = ctx->state[x][(y+x) & 0x03]; + } + + memcpy(ctx->state, nstate, sizeof(ctx->state)); +} + +void aes_mixcolumns(aes_ctx_t *ctx) +{ + unsigned char nstate[4][4]; + int i; + + for(i = 0; i < 4; i++) { + nstate[0][i] = aes_mul(0x02, ctx->state[0][i]) ^ + aes_mul(0x03, ctx->state[1][i]) ^ + ctx->state[2][i] ^ + ctx->state[3][i]; + nstate[1][i] = ctx->state[0][i] ^ + aes_mul(0x02, ctx->state[1][i]) ^ + aes_mul(0x03, ctx->state[2][i]) ^ + ctx->state[3][i]; + nstate[2][i] = ctx->state[0][i] ^ + ctx->state[1][i] ^ + aes_mul(0x02, ctx->state[2][i]) ^ + aes_mul(0x03, ctx->state[3][i]); + nstate[3][i] = aes_mul(0x03, ctx->state[0][i]) ^ + ctx->state[1][i] ^ + ctx->state[2][i] ^ + aes_mul(0x02, ctx->state[3][i]); + } + + memcpy(ctx->state, nstate, sizeof(ctx->state)); +} + +void aes_addroundkey(aes_ctx_t *ctx, int round) +{ + int i; + + for(i = 0; i < 16; i++) { + int x, y; + + x = i & 0x03; + y = i >> 2; + ctx->state[x][y] = ctx->state[x][y] ^ + ((ctx->keysched[round*4+y] & (0xff << (x*8))) >> (x*8)); + } +} + +void aes_encrypt(aes_ctx_t *ctx, unsigned char input[16], unsigned char output[16]) +{ + int i; + + // copy input to state + for(i = 0; i < 16; i++) + ctx->state[i & 0x03][i >> 2] = input[i]; + + aes_addroundkey(ctx, 0); + + for(i = 1; i < ctx->rounds; i++) { + aes_subbytes(ctx); + aes_shiftrows(ctx); + aes_mixcolumns(ctx); + aes_addroundkey(ctx, i); + } + + aes_subbytes(ctx); + aes_shiftrows(ctx); + aes_addroundkey(ctx, ctx->rounds); + + // copy state to output + for(i = 0; i < 16; i++) + output[i] = ctx->state[i & 0x03][i >> 2]; +} + +void aes_invshiftrows(aes_ctx_t *ctx) +{ + unsigned char nstate[4][4]; + int i; + + for(i = 0; i < 16; i++) { + int x, y; + + x = i & 0x03; + y = i >> 2; + nstate[x][(y+x) & 0x03] = ctx->state[x][y]; + } + + memcpy(ctx->state, nstate, sizeof(ctx->state)); +} + +void aes_invsubbytes(aes_ctx_t *ctx) +{ + int i; + + for(i = 0; i < 16; i++) { + int x, y; + + x = i & 0x03; + y = i >> 2; + ctx->state[x][y] = g_aes_isbox[ctx->state[x][y]]; + } +} + +void aes_invmixcolumns(aes_ctx_t *ctx) +{ + unsigned char nstate[4][4]; + int i; + + for(i = 0; i < 4; i++) { + nstate[0][i] = aes_mul(0x0e, ctx->state[0][i]) ^ + aes_mul(0x0b, ctx->state[1][i]) ^ + aes_mul(0x0d, ctx->state[2][i]) ^ + aes_mul(0x09, ctx->state[3][i]); + nstate[1][i] = aes_mul(0x09, ctx->state[0][i]) ^ + aes_mul(0x0e, ctx->state[1][i]) ^ + aes_mul(0x0b, ctx->state[2][i]) ^ + aes_mul(0x0d, ctx->state[3][i]); + nstate[2][i] = aes_mul(0x0d, ctx->state[0][i]) ^ + aes_mul(0x09, ctx->state[1][i]) ^ + aes_mul(0x0e, ctx->state[2][i]) ^ + aes_mul(0x0b, ctx->state[3][i]); + nstate[3][i] = aes_mul(0x0b, ctx->state[0][i]) ^ + aes_mul(0x0d, ctx->state[1][i]) ^ + aes_mul(0x09, ctx->state[2][i]) ^ + aes_mul(0x0e, ctx->state[3][i]); + } + + memcpy(ctx->state, nstate, sizeof(ctx->state)); +} + +void aes_decrypt(aes_ctx_t *ctx, unsigned char input[16], unsigned char output[16]) +{ + int i; + + // copy input to state + for(i = 0; i < 16; i++) + ctx->state[i & 0x03][i >> 2] = input[i]; + + aes_addroundkey(ctx, ctx->rounds); + for(i = ctx->rounds-1; i >= 1; i--) { + aes_invshiftrows(ctx); + aes_invsubbytes(ctx); + aes_addroundkey(ctx, i); + aes_invmixcolumns(ctx); + } + + aes_invshiftrows(ctx); + aes_invsubbytes(ctx); + aes_addroundkey(ctx, 0); + + // copy state to output + for(i = 0; i < 16; i++) + output[i] = ctx->state[i & 0x03][i >> 2]; +} + +void aes_free_ctx(aes_ctx_t *ctx) +{ + free(ctx); +} + +#define PRINT_BYTES(bPtr, siz, offset) { int _bPtr_idx; for (_bPtr_idx = offset; _bPtr_idx < offset+siz; _bPtr_idx++) { printf("%02X ", bPtr[_bPtr_idx]); } printf("\n"); } +int main(int argc, char *argv[]) +{ + if (argc != 3) { + fprintf(stderr, "usage: %s [KEY] [MSG]\n", argv[0]); + return 1; + } + + size_t klen = strlen(argv[1]); + unsigned char key[KEY_128]; + memcpy(key, argv[1], klen); + + size_t plen = strlen(argv[2]); + unsigned char ptext[plen+1]; + memcpy(ptext, argv[2], plen); + ptext[plen] = '\0'; + + unsigned char ctext[plen+1]; + memset(ctext, '\0', plen+1); + unsigned char decptext[plen+1]; + memset(decptext, '\0', plen+1); + + aes_ctx_t *ctx; + + init_aes(); + ctx = aes_alloc_ctx(key, sizeof(key)); + if(!ctx) { + perror("aes_alloc_ctx"); + return EXIT_FAILURE; + } + printf("Encrypted[HEX]..: "); + aes_encrypt(ctx, ptext, ctext); + PRINT_BYTES(ctext, sizeof(ctext), 0); + aes_decrypt(ctx, ctext, decptext); + printf("Decrypted[HEX]..: "); + PRINT_BYTES(decptext, sizeof(decptext), 0); + printf("Decrypted[ASCII]: "); + puts((char*)decptext); + + aes_free_ctx(ctx); + return EXIT_SUCCESS; +} + diff --git a/asciihexer.c b/asciihexer.c new file mode 100644 index 0000000..afa1cd0 --- /dev/null +++ b/asciihexer.c @@ -0,0 +1,46 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#define ASCII_HEXLEN 3 + + +static void defaultHexOut(char *text) { + int i; + size_t len; + + for (i = 0; i < (len = strlen(text)); i++) { + printf("0x%X%c", text[i], (i == len-1 ? '\n' : ' ')); + } +} + +static void dwordHexOut(char *text) { + int i; + size_t len; + + for (i = 0; i < (len = strlen(text)); i++) { + printf("%s%X%s", (i % 4 == 0 ? (i == 0 ? "0x" : " 0x") : ""), text[i], (i == len-1 ? "\n" : "")); + } +} + +static void strHexOut(char *text) { + int i; + size_t len; + + for (i = 0; i < (len = strlen(text)); i++) { + printf("%s%X%s", (i == 0 ? "0x" : ""), text[i], (i == len-1 ? "\n" : "")); + } +} + +int main(int argc, char **argv) +{ + if (argc != 2) { + fprintf(stderr, "usage: %s [TEXT]\n", argv[0]); + return 1; + } + + defaultHexOut(argv[1]); + dwordHexOut(argv[1]); + strHexOut(argv[1]); + return 0; +} diff --git a/config.h b/config.h new file mode 100644 index 0000000..beafcf6 --- /dev/null +++ b/config.h @@ -0,0 +1,31 @@ +/************** + * GameOfLife * + **************/ + +/* the number of random spawns per cycle */ +#define RANDOM_SPAWNS 20 + +/* enable hotkeys q, p, c, +/- */ +#define ENABLE_HOTKEYS 1 + +/* enable the upper status bar */ +#define ENABLE_STATUS 1 + +/* enable the cursor */ +#define ENABLE_CURSOR 1 + +/* set the cursor symbol */ +#define CURSOR_CHAR '#' + + +/************** + * DummyShell * + **************/ + +#define _HAS_CMD 1 +#define _HAS_MSG 1 +#define _HAS_HOSTENT 1 +#define _HAS_SIGNAL 1 +#define _HAS_UTMP 1 +#define _HAS_SYSINFO 1 + diff --git a/dummyshell.c b/dummyshell.c new file mode 100644 index 0000000..aa3c17a --- /dev/null +++ b/dummyshell.c @@ -0,0 +1,622 @@ +/* + * build with: gcc -Wall -O2 -D_GNU_SOURCE=1 -D_HAS_CMD=1 -D_HAS_MSG=1 -D_HAS_HOSTENT=1 -D_HAS_SIGNAL=1 -D_HAS_UTMP=1 -D_HAS_SYSINFO -ffunction-sections -fdata-sections -ffast-math -fomit-frame-pointer dummyshell.c -o dummyshell + * strip -s dummyshell + */ + + +#ifdef _HAVE_CONFIG +#include "config.h" +#endif +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <termios.h> +#include <fcntl.h> +#include <time.h> +#include <ctype.h> /* isprint(...) */ +#include <sys/ioctl.h> /* ioctl(...) */ +#include <stdint.h> /* UINT8_MAX */ +#include <string.h> /* memset(...) */ +#include <sys/types.h> +#include <pwd.h> /* getpwuid(...) */ +#ifdef _HAS_CMD +#include <sys/wait.h> +#else +#warning "COMMANDS(_HAS_CMD) disabled!" +#endif +#ifdef _HAS_MSG +#include <errno.h> +#include <string.h> +#else +#warning "MESSAGE(_HAS_MSG) disabled!" +#endif +#ifdef _HAS_HOSTENT +#include <netdb.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#else +#warning "HOSTENT(_HAS_HOSTENT) disabled!" +#endif +#ifdef _HAS_SIGNAL +#include <signal.h> /* signal(...) */ +#else +#warning "SIGNAL(_HAS_SIGNAL) disabled!" +#endif +#ifdef _HAS_UTMP +#include <utmp.h> /* utmp structure */ +#else +#warning "UTMP(_HAS_UTMP) disabled!" +#endif +#ifdef _HAS_SYSINFO +#include "sys/types.h" /* sysinfo structture */ +#include "sys/sysinfo.h" /* sysinfo(...) */ +#else +#warning "SYSINFO(_HAS_SYSINFO) disabled!" +#endif + +/* for print_memusage() and print cpuusage() see: http://stackoverflow.com/questions/63166/how-to-determine-cpu-and-memory-consumption-from-inside-a-process */ + + +static const char keymsg[] = " ['q'-EXIT | 'm'-MESSAGE | 'c'-CMDS] "; +static const char txtheader[] = + "**************\n" + "* dummyshell *\n" + "**************\n" + "!(C) by Toni Uhlig\n" + "@see: https://raw.githubusercontent.com/lnslbrty/foo-scripts/master/dummyshell.c\n"; + +static volatile unsigned char doLoop = 1; + + +static void printQuitLoop(void) { + printf("quit in 3 .. "); + fflush(stdout); + sleep(1); + printf("2 .. "); + fflush(stdout); + sleep(1); + printf("1 .. "); + fflush(stdout); + sleep(1); + printf("\n"); + doLoop = 0; +} + +#define I_CLEARBUF 0x1 +static char readInput(char* buf, size_t* siz, size_t szMax, char key, int flags) { + if (flags & I_CLEARBUF) { + memset(&buf[0], '\0', szMax); + *siz = 0; + } else switch (key) { + case '\n': + break; + case 127: + if (*siz > 0) + buf[--(*siz)] = '\0'; + break; + case EOF: break; + default: + if (isprint(key) && *siz < szMax) + buf[(*siz)++] = key; + break; + } + return key; +} + +#ifdef _HAS_CMD +struct __attribute__((__packed__)) cmd { + char* name; + char* path; + char* defargs; +}; + +static struct cmd cmds[] = { + { "ether-wake", "/var/media/ftp/bin/suid-ether-wake", "-b -i lan" }, + { "echo", "/bin/echo", NULL }, + { NULL, NULL, NULL } +}; + +static void print_cmds(void) +{ + size_t idx = 0; + printf("\33[2K\r[COMMANDS]\n"); + while ( cmds[idx++].path != NULL ) { + printf(" [%lu] %s\n", (unsigned long int)idx-1, ( cmds[idx-1].name != NULL ? cmds[idx-1].name : "unknown" )); + } +} + +int safe_exec(const char* cmdWithArgs) +{ + pid_t child; + if ( (child = fork()) == 0 ) { + size_t szCur = 0, szMax = 10; + char** args = calloc(szMax, sizeof(char**)); + const char* cmd = NULL; + + const char* prv = cmdWithArgs; + const char* cur = NULL; + while ( (cur = strchr(prv, ' ')) ) { + if (cmd == NULL) + cmd = strndup(prv, cur-prv); + + args[szCur++] = strndup(prv, cur-prv); + if (szCur >= szMax) { + szMax *= 2; + args = realloc(args, sizeof(char**)*szMax); + } + + cur++; + prv = cur; + } + if (cmd == NULL) { + cmd = cmdWithArgs; + } else { + args[szCur++] = strndup(prv, cur-prv); + } + args[szCur] = NULL; + execv(cmd, args); + exit(-5); + } else if (child != -1) { + int retval = 0; + waitpid(child, &retval, 0); + return retval; + } + return -6; +} + +static int exec_cmd(size_t i, char* args, size_t szArgs) +{ + size_t idx = (size_t)-1; + while ( cmds[++idx].path != NULL ) { + if (idx == i) { + size_t siz = strlen(cmds[idx].path)+szArgs+1; + char execbuf[siz+1]; + memset(&execbuf[0], '\0', siz+1); + snprintf(&execbuf[0], siz+1, "%s %s", cmds[idx].path, args); + return safe_exec(&execbuf[0]); + } + } + return -7; +} +#endif + +#ifdef _HAS_MSG +#define MSGFILE "/tmp/dummyshell.msg" +#define STRLEN(str) (sizeof(str)/sizeof(str[0])) +static int msgfd = -1; +static int init_msg(void) +{ + msgfd = open(MSGFILE, O_RDWR | O_CREAT | O_APPEND | O_DSYNC | O_RSYNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + if (msgfd < 0) { + fprintf(stderr, "fopen(\"%s\") with write access: %s\n", MSGFILE, strerror(errno)); + msgfd = open(MSGFILE, O_RDONLY | O_CREAT | O_APPEND | O_DSYNC | O_RSYNC); + if (msgfd < 0) { + fprintf(stderr, "fopen(\"%s\") readonly: %s\n", MSGFILE, strerror(errno)); + return -1; + } + } + return 0; +} + +struct __attribute__((__packed__)) msgHdr { + uint8_t szFrom; + uint8_t szMsg; + time_t timestamp; +}; + +struct __attribute__((__packed__)) msg { + char* from; + char* msg; +}; + +static int read_msg(struct msgHdr* hdr, struct msg* msg) +{ + if (msgfd < 0) return -1; + int ok = 1; + size_t rb = 0; + if ( (rb = read(msgfd, hdr, sizeof(struct msgHdr)*1)) == sizeof(struct msgHdr)*1 ) { + msg->from = calloc(hdr->szFrom+1, sizeof(char)); + msg->msg = calloc(hdr->szMsg+1, sizeof(char)); + if ( (rb = read(msgfd, &(msg->from[0]), sizeof(char)*hdr->szFrom)) != sizeof(char)*hdr->szFrom ) + ok = 0; + if ( (rb = read(msgfd, &(msg->msg[0]), sizeof(char)*hdr->szMsg)) != sizeof(char)*hdr->szMsg ) + ok = 0; + char newline = 0; + if ( (rb = read(msgfd, &newline, sizeof(char)*1)) != sizeof(char)*1 ) + ok = 0; + if (!ok || newline != '\n') { + free(msg->from); + free(msg->msg); + msg->from = NULL; + msg->msg = NULL; + return -1; + } + return 0; + } + return -1; +} + +static int print_msg(void) { + struct msgHdr hdr; + struct msg msg; + memset(&hdr, '\0', sizeof(struct msgHdr)); + memset(&msg, '\0', sizeof(struct msg)); + if (read_msg(&hdr, &msg) == 0) { + struct tm localtime; + struct passwd* pwd = NULL; + unsigned long int uid = strtoul(msg.from, NULL, 10); + if ( (pwd = getpwuid((uid_t)uid)) ) { + free(msg.from); + msg.from = strdup(pwd->pw_name); + } + if (localtime_r(&hdr.timestamp, &localtime) != NULL) { + printf("\33[2K\r[%02d-%02d-%04d %02d:%02d:%02d] Message from %s: %s\n", localtime.tm_mday, localtime.tm_mon+1, 1900+localtime.tm_year, localtime.tm_hour, localtime.tm_min, localtime.tm_sec, msg.from, msg.msg); + } else { + printf("\33[2K\r\aMessage from %s: %s\n", msg.from, msg.msg); + } + free(msg.from); + free(msg.msg); + return 0; + } + return -1; +} + +static int write_msg(char* msg) { + char from[6]; + memset(&from[0], '\0', STRLEN(from)); + if (snprintf(&from[0], STRLEN(from), "%u", getuid()) > 0) { + struct msgHdr hdr; + hdr.szFrom = strnlen(from, STRLEN(from)); + hdr.szMsg = strnlen(msg, UINT8_MAX); + hdr.timestamp = time(NULL); + char* buf = calloc(sizeof(hdr) + hdr.szFrom + hdr.szMsg + 2, sizeof(char)); + if (buf) { + memcpy(buf, &hdr, sizeof(hdr)); + memcpy(buf+sizeof(hdr), from, hdr.szFrom); + memcpy(buf+sizeof(hdr)+hdr.szFrom, msg, hdr.szMsg); + *(buf + sizeof(hdr) + hdr.szFrom + hdr.szMsg) = '\n'; + int failed = 1; + if ( write(msgfd, buf, sizeof(char)*(sizeof(hdr)+hdr.szFrom+hdr.szMsg+1)) == sizeof(char)*(sizeof(hdr)+hdr.szFrom+hdr.szMsg+1) ) + failed = 0; + free(buf); + return failed; + } + } + return -1; +} +#endif + +#ifdef _HAS_HOSTENT +#define ARP_STRING_LEN 1024 +#define ARP_IP_LEN 32 +#define XSTR(s) STR(s) +#define STR(s) #s +static void print_nethost(void) +{ + FILE *arpCache = fopen("/proc/net/arp", "r"); + if (arpCache != NULL) { + char arpline[ARP_STRING_LEN+1]; + memset(&arpline[0], '\0', ARP_STRING_LEN+1); + if (fgets(arpline, ARP_STRING_LEN, arpCache)) { + char arpip[ARP_IP_LEN+1]; + memset(&arpip[0], '\0', ARP_IP_LEN); + const char nonline[] = "\33[2K\rhost online...: "; + size_t i = 0; + while (1 == fscanf(arpCache, "%" XSTR(ARP_IP_LEN) "s %*s %*s %*s %*s %*s", &arpip[0])) { + struct in_addr ip; + struct hostent *hp = NULL; + if (inet_aton(&arpip[0], &ip)) { + hp = gethostbyaddr((const void *)&ip, sizeof ip, AF_INET); + } + char *herrmsg = NULL; + if (hp == NULL) { + switch (h_errno) { + case HOST_NOT_FOUND: herrmsg = "HOST UNKNOWN"; break; + case NO_ADDRESS: herrmsg = "IP UNKNOWN"; break; + case NO_RECOVERY: herrmsg = "SERVER ERROR"; break; + case TRY_AGAIN: herrmsg = "TEMPORARY ERROR"; break; + } + } + printf("%s[%lu] %.*s aka %s\n", nonline, (long unsigned int)++i, ARP_IP_LEN, arpip, (hp != NULL ? hp->h_name : herrmsg)); + memset(&arpip[0], '\0', ARP_IP_LEN); + } + } + fclose(arpCache); + } +} +#endif + +#ifdef _HAS_UTMP +#ifndef _GNU_SOURCE +size_t +strnlen(const char *str, size_t maxlen) +{ + const char *cp; + for (cp = str; maxlen != 0 && *cp != '\0'; cp++, maxlen--); + return (size_t)(cp - str); +} +#endif + +static void print_utmp(void) +{ + int utmpfd = open("/var/run/utmp", O_RDONLY); + if (utmpfd >= 0) { + struct utmp ut; + memset(&ut, '\0', sizeof(struct utmp)); + const char uonline[] = "\33[2K\ruser online...: "; + size_t i = 0; + while ( read(utmpfd, &ut, sizeof(struct utmp)) == sizeof(struct utmp) && strnlen(ut.ut_user, UT_NAMESIZE) > 0 ) { + if (strnlen(ut.ut_host, UT_HOSTSIZE) > 0) { + printf("%s[%lu] %.*s from %.*s\n", uonline, (long unsigned int)++i, UT_NAMESIZE, ut.ut_user, UT_HOSTSIZE, ut.ut_host); + } else { + printf("%s[%lu] %.*s\n", uonline, (long unsigned int)++i, UT_NAMESIZE, ut.ut_user); + } + } + } +} +#endif + +#ifdef _HAS_SYSINFO +static unsigned long long lastTotalUser, lastTotalUserLow, lastTotalSys, lastTotalIdle; + +static void init_cpuusage(){ + FILE* file = fopen("/proc/stat", "r"); + if (file) { + fscanf(file, "cpu %llu %llu %llu %llu", &lastTotalUser, &lastTotalUserLow, + &lastTotalSys, &lastTotalIdle); + fclose(file); + } +} + +static void print_cpuusage(){ + double percent; + FILE* file; + unsigned long long totalUser, totalUserLow, totalSys, totalIdle, total; + + file = fopen("/proc/stat", "r"); + fscanf(file, "cpu %llu %llu %llu %llu", &totalUser, &totalUserLow, + &totalSys, &totalIdle); + fclose(file); + + if (totalUser < lastTotalUser || totalUserLow < lastTotalUserLow || + totalSys < lastTotalSys || totalIdle < lastTotalIdle){ + //Overflow detection. Just skip this value. + percent = -1.0; + } else{ + total = (totalUser - lastTotalUser) + (totalUserLow - lastTotalUserLow) + + (totalSys - lastTotalSys); + percent = total; + total += (totalIdle - lastTotalIdle); + percent /= total; + percent *= 100; + } + + lastTotalUser = totalUser; + lastTotalUserLow = totalUserLow; + lastTotalSys = totalSys; + lastTotalIdle = totalIdle; + + printf("CPU...........: %.02f%%\n", percent); +} + +static void print_memusage(void) +{ + struct sysinfo meminfo; + memset(&meminfo, '\0', sizeof(struct sysinfo)); + if (sysinfo(&meminfo) == 0) { + unsigned long long totalvmem = meminfo.totalram; + totalvmem += meminfo.totalswap; + totalvmem *= meminfo.mem_unit; + unsigned long long usedvmem = meminfo.totalram - meminfo.freeram; + usedvmem += meminfo.totalswap - meminfo.freeswap; + usedvmem *= meminfo.mem_unit; + printf("VMEM(used/max): %llu/%lld (Mb)\n", (usedvmem/(1024*1024)), (totalvmem/(1024*1024))); + } +} +#endif + +#ifdef _HAS_SIGNAL +void SigIntHandler(int signum) +{ + if (signum == SIGINT) { + doLoop = 0; + } +} +#endif + +enum mainState { MS_DEFAULT, MS_MESSAGE, MS_COMMAND }; + +int main(int argc, char** argv) +{ + enum mainState state = MS_DEFAULT; + struct timeval tv; + tv.tv_sec = 1; + tv.tv_usec = 0; + +#ifdef _HAS_SIGNAL + signal(SIGINT, SigIntHandler); +#endif + size_t inputsiz = 0, absiz = UINT8_MAX; + struct winsize wsiz; + ioctl(0, TIOCGWINSZ, &wsiz); + if (wsiz.ws_col < absiz) + absiz = wsiz.ws_col - 3; + char inputbuf[absiz+1]; + memset(&inputbuf[0], '\0', absiz+1); +#ifdef _HAS_MSG + if (init_msg() != 0) + return 1; + if (argc > 1) { + const char optRmsg[] = "readmsg"; + const char optWmsg[] = "writemsg"; + const char optNofollow[] = "-n"; + if (strncmp(argv[1], optRmsg, STRLEN(optRmsg)) == 0) { + if (argc == 2) while (doLoop) { + if (print_msg() != 0) + sleep(1); + } else if (argc == 3) { + if (strncmp(argv[2], optNofollow, STRLEN(optNofollow)) == 0) { + while (print_msg() == 0) {} + } else { + fprintf(stderr, "%s readmsg [-n]\n", argv[0]); + return 1; + } + } + return 0; + } else if (strncmp(argv[1], optWmsg, STRLEN(optWmsg)) == 0) { + if (argc == 3) { + return write_msg(argv[2]); + } else { + fprintf(stderr, "%s writemsg msg\n", argv[0]); + } + return 0; + } else { + fprintf(stderr, "usage: %s [readmsg [-n] | writemsg msg]\n", argv[0]); + return 1; + } + } +#endif +#ifdef _HAS_SYSINFO + init_cpuusage(); +#endif + int flags = fcntl(STDIN_FILENO, F_GETFL, 0); + fcntl(STDIN_FILENO, F_SETFL, flags | O_NONBLOCK); + + static struct termios oldt, newt; + tcgetattr(STDIN_FILENO, &oldt); + newt = oldt; + newt.c_lflag &= ~(ICANON | ECHO); + tcsetattr(STDIN_FILENO, TCSANOW, &newt); + + printf("%s\n", txtheader); + fd_set fds; + time_t start = time(NULL); + time_t cur; + unsigned char mins = 0, hrs = 0; + while (doLoop > 0) { + cur = time(NULL); + double diff = difftime(cur, start); +#if defined(_HAS_UTMP) || defined(_HAS_SYSINFO) + if ((unsigned int)diff % 60 == 0) { + if (diff != 0 && ++mins == 60) { + mins = 0; + hrs++; + } + struct tm localtime; + if (localtime_r(&cur, &localtime) != NULL) { + printf("\33[2K\r--- %02d:%02d:%02d ---\n", localtime.tm_hour, localtime.tm_min, localtime.tm_sec); + } +#ifdef _HAS_UTMP + print_utmp(); +#endif +#ifdef _HAS_HOSTENT + print_nethost(); +#endif +#ifdef _HAS_SYSINFO + print_memusage(); + print_cpuusage(); +#endif + } +#endif +#ifdef _HAS_MSG + while (print_msg() == 0) {} +#endif + switch (state) { + case MS_DEFAULT: + printf("\r--- %02d:%02d:%02d ---%s", hrs, mins, ((unsigned int)diff % 60), keymsg); + break; + case MS_MESSAGE: + case MS_COMMAND: +#if defined(_HAS_MSG) || defined(_HAS_CMD) + printf("\33[2K\r> %s", inputbuf); +#endif + break; + } + fflush(stdout); + + FD_ZERO(&fds); + FD_SET(STDIN_FILENO, &fds); + int ret = select(FD_SETSIZE, &fds, NULL, NULL, &tv); + if (doLoop == 1 && ret == 0) { + tv.tv_sec = 1; + tv.tv_usec = 0; + } else if (FD_ISSET(STDIN_FILENO, &fds)) { + char key = getchar(); + switch (state) { + case MS_DEFAULT: + switch ( key ) { + case 'q': +#ifdef _HAS_SIGNAL + signal(SIGINT, SIG_IGN); +#endif + printQuitLoop(); + break; + case 'm': +#ifdef _HAS_MSG + state = MS_MESSAGE; +#else + printf("<feature disabled>\n"); +#endif + break; + case 'c': +#ifdef _HAS_CMD + print_cmds(); + state = MS_COMMAND; +#else + printf("<feature disabled>\n"); +#endif + break; + default: printf("unknown key: %c\n", key); break; + } + break; + case MS_COMMAND: + case MS_MESSAGE: + switch (readInput(&inputbuf[0], &inputsiz, absiz, key, 0)) { + case '\n': + if (state == MS_MESSAGE) { +#ifdef _HAS_MSG + printf("\33[2K\rSending message(%lu): %s\n", (long unsigned int)inputsiz, inputbuf); + if (write_msg(inputbuf) != 0) + printf("Sending failed.\n"); +#endif + } else if (state == MS_COMMAND) { +#ifdef _HAS_CMD + int inputFail = 0; + if (inputsiz < 3) { + inputFail++; + } else { + char* endptr = NULL; + unsigned long int tmpi = strtoul(inputbuf, &endptr, 10); + if (*endptr == ' ') { + endptr++; + printf("\33[2K\rExec CMD #%lu with args: %s\n", tmpi, endptr); + int retval; + switch ( (retval = exec_cmd(tmpi, endptr, strlen(endptr))) ) { + case -7: printf("unknown cmd #%lu\n", tmpi); break; + case -6: printf("fork error cmd #%lu\n", tmpi); break; + case -5: printf("execute cmd #%lu\n", tmpi); break; + + case 0: break; + default: printf("Something went wrong, child returned: %d\n", retval); break; + } + } else inputFail++; + } + if (inputFail > 0) + printf("\33[2K\rFORMAT: [cmd#] [params]\n"); +#endif + } + state = MS_DEFAULT; + readInput(&inputbuf[0], &inputsiz, absiz, 0, I_CLEARBUF); + break; + } + fflush(stdout); + break; + } + } + } + while (getchar() != EOF) {} + + tcsetattr( STDIN_FILENO, TCSANOW, &oldt); + return 0; +} @@ -0,0 +1,469 @@ +/** + * @author Steffen Vogel <info@steffenvogel.de>, Toni Uhlig <matzeton@googlemail.com> + * @copyright Copyright (c) 2010-2014, Steffen Vogel, Toni Uhlig + * @license http://opensource.org/licenses/gpl-license.php GNU Public License + */ + +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <curses.h> +#include <time.h> + +/* configuration */ +#include "config.h" + +#if defined(RANDOM_SPAWNS) +static uint8_t rnd_spawns = 0xFF; +#endif + +struct config { + uint8_t paused:1; + uint8_t quit:1; + uint8_t menu:1; + uint8_t reprint:1; +}; + +struct pattern { + uint8_t width; + uint8_t height; + uint8_t * data; +}; + +struct cursor { + uint8_t x; + uint8_t y; +}; + +uint8_t start[3][3] = { + {0, 1, 1}, + {1, 1, 0}, + {0, 1, 0} +}; + +uint8_t glider[3][3] = { + {0, 1, 0}, + {0, 0, 1}, + {1, 1, 1} +}; + +uint8_t segler[4][5] = { + {0, 1, 1, 1, 1}, + {1, 0, 0, 0, 1}, + {0, 0, 0, 0, 1}, + {1, 0, 0, 1, 0} +}; + +uint8_t buffer[7][3] = { + {1, 1, 1}, + {1, 0, 1}, + {1, 0, 1}, + {0, 0, 0}, + {1, 0, 1}, + {1, 0, 1}, + {1, 1, 1} +}; + +uint8_t kreuz[3][3] = { + {0, 1, 0}, + {1, 1, 1}, + {0, 1, 0} +}; + +uint8_t ship[3][3] = { + {1, 1, 0}, + {1, 0, 1}, + {0, 1, 1} +}; + +/* initialize world with zero (dead cells) */ +void clean_world(uint8_t ** world, uint8_t width, uint8_t height) { + int a; + for (a = 0; a < width; a++) { + memset(world[a], 0, height * sizeof(uint8_t)); + } +} + +/* allocate memory for world */ +uint8_t ** create_world(uint8_t width, uint8_t height) { + uint8_t ** world = calloc(width, sizeof(uint8_t *)); + int a; + for (a = 0; a < width; a++) { + world[a] = calloc(height, sizeof(uint8_t)); + } + + clean_world(world, width, height); + return world; +} + +void free_world(uint8_t ** world, uint8_t width, uint8_t height) { + int a; + for (a = 0; a < width; a++) { + free(world[a]); + } + free(world); +} + +/* insert pattern at (x|y) into world */ +void inhabit_world(struct pattern pattern, uint8_t x, uint8_t y, uint8_t ** world, uint8_t width, uint8_t height) { + uint8_t a, b; + + for (a = 0; a < pattern.height; a++) { + int c = a; + if ((y + c) >= height) c -= height; + + for (b = 0; b < pattern.width; b++) { + int d = b; + if ((x + d) >= width) d -= width; + world[x+d][y+c] = pattern.data[(a*pattern.width)+b]; + } + } +} + +/* calc alive cells */ +uint8_t calc_cell_count(uint8_t ** world, uint8_t width, uint8_t height) { + int cell_count = 0; + uint8_t a, b; + + for (a = 0; a < width; a++) { + for (b = 0; b < height; b++) { + cell_count += (world[a][b]) ? 1 : 0; + } + } + + return cell_count; +} + +uint8_t calc_cell_neighbours(uint8_t x, uint8_t y, uint8_t ** world, uint8_t width, uint8_t height) { + uint8_t neighbours = 0; + int a, b; + + for (a = x-1; a <= x+1; a++) { + int c = a; + if (a < 0) c += width; + if (a >= width) c -= width; + + for (b = y-1; b <= y+1; b++) { + int d = b; + if (a == x && b == y) continue; + if (b < 0) d += height; + if (b >= height) d -= height; + + neighbours += (world[c][d] > 0) ? 1 : 0; + } + } + + return neighbours; /* 0 <= neighbours <= 8 */ +} + +uint8_t calc_next_cell_gen(uint8_t x, uint8_t y, uint8_t ** world, uint8_t width, uint8_t height) { + fflush(stdout); + uint8_t neighbours = calc_cell_neighbours(x, y, world, width, height); + uint8_t alive = world[x][y]; + + if (alive) { + if (neighbours > 3 || neighbours < 2) { + return 0; /* died by over-/underpopulation */ + } + else { + return 1; /* kept alive */ + } + } + else if (neighbours == 3) { + return 1; /* born */ + } + else { + return 0; /* still dead */ + } +} + +void calc_next_gen(uint8_t ** world, uint8_t ** next_gen, uint8_t width, uint8_t height) { + uint8_t x, y; + + for (x = 0; x < width; x++) { + for (y = 0; y < height; y++) { + next_gen[x][y] = calc_next_cell_gen(x, y, world, width, height); + } + } + + /* copy world */ + for (x = 0; x < width; x++) { + for (y = 0; y < height; y++) { + world[x][y] = next_gen[x][y]; + } + } +} + +/* print world with colors and count of neighbours */ +void print_world(uint8_t ** world, uint8_t width, uint8_t height) { + uint8_t x, y; + move(0, 0); /* reset cursor */ + + /* cells */ + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + uint8_t neighbours = calc_cell_neighbours(x, y, world, width, height); + + if (neighbours > 1) attron(COLOR_PAIR(neighbours)); + addch((world[x][y]) ? '0' + neighbours : ' '); + if (neighbours > 1) attroff(COLOR_PAIR(neighbours)); + } + } +} + +#ifdef ENABLE_CURSOR +void print_cursor(uint8_t ** world, struct cursor cur) { + uint8_t color = (world[cur.x][cur.y]) ? 7 : 6; + + move(cur.y, cur.x); + addch(CURSOR_CHAR | A_BLINK | A_BOLD | A_STANDOUT | COLOR_PAIR(color)); +} +#endif + +#ifdef ENABLE_HOTKEYS +#define MENU_WIDTH 25 +void print_menu(uint8_t width, uint8_t height) { + uint8_t startx, starty, mwdth_rel, posy = 0; + + mwdth_rel = (uint8_t) (MENU_WIDTH)/2+10; + startx = (uint8_t) (width/2) - mwdth_rel; + starty = (uint8_t) (height/2) - (uint8_t) (mwdth_rel/2); + attron(COLOR_PAIR(1)); + for (int i = 0; i < MENU_WIDTH; i++) { + mvprintw(starty, startx+i, "-"); + mvprintw(starty+(mwdth_rel*2/3), startx+i, "-"); + if (i % 2 == 0) { + mvprintw(starty+posy+1, startx-1, "|"); + mvprintw(starty+posy+1, startx+MENU_WIDTH, "|"); + posy++; + } + } + mvprintw(starty, startx-1, "+"); + mvprintw(starty, startx+MENU_WIDTH, "+"); + mvprintw(starty+posy+1, startx-1, "+"); + mvprintw(starty+posy+1, startx+MENU_WIDTH, "+"); + for (int i = startx; i < startx+MENU_WIDTH; i++) { + for (int j = starty+1; j <= starty+posy; j++) { + mvprintw(j, i, " "); + } + } + mvprintw(starty+1, startx+1, "q ~ Exit"); + mvprintw(starty+3, startx+1, "c ~ Clear Screen"); +#if defined(RANDOM_SPAWNS) + mvprintw(starty+5, startx+1, "d ~ Rnd Spawns [%d]", (rnd_spawns == 0 ? 0 : 1)); +#endif + mvprintw(starty+7, startx+1, "p ~ Pause"); + mvprintw(starty+9, startx+1, "+/- ~ Change Framerate"); + mvprintw(starty+11, startx+1, "0-5 ~ Create Pattern"); + attroff(COLOR_PAIR(1)); +} +#endif + +/* set up ncurses screen */ +WINDOW * init_screen() { + WINDOW * win = initscr(); + noecho(); + timeout(0); + keypad(win, 1); + mousemask(BUTTON1_PRESSED, NULL); + mouseinterval(200); + curs_set(0); + + start_color(); + init_color(COLOR_CYAN, 500, 1000, 0); /* redefine as orange */ + + init_pair(1, COLOR_BLACK, COLOR_WHITE); + init_pair(2, COLOR_WHITE, COLOR_BLACK); + init_pair(3, COLOR_GREEN, COLOR_BLACK); + init_pair(4, COLOR_YELLOW, COLOR_BLACK); + init_pair(5, COLOR_CYAN, COLOR_BLACK); + init_pair(6, COLOR_BLUE, COLOR_BLACK); + init_pair(7, COLOR_MAGENTA, COLOR_BLACK); + init_pair(8, COLOR_RED, COLOR_BLACK); + + return win; +} + +uint8_t **init_world(WINDOW *win, uint8_t **worlds[2], uint8_t *width, uint8_t *height) { + getmaxyx(win, *height, *width); + for (int i = 0; i < 2; i++) + worlds[i] = create_world(*width, *height); + return (worlds[0]); +} + +void free_all(uint8_t **worlds[2], uint8_t width, uint8_t height) { + free_world(worlds[0], width, height); + free_world(worlds[1], width, height); +} + +// returns realloc'd && resized world +uint8_t **resized(WINDOW *win, uint8_t **worlds[2], uint8_t *width, uint8_t *height) { + free_world(worlds[0], *width, *height); + free_world(worlds[1], *width, *height); + return (init_world(win, worlds, width, height)); +} + +int main(int argc, char * argv[]) { + WINDOW * win = init_screen(); +#ifdef ENABLE_CURSOR + MEVENT event; +#endif + + /* predefined patterns */ + struct pattern patterns[] = { + {3, 3, (uint8_t *) start}, + {3, 3, (uint8_t *) glider}, + {5, 4, (uint8_t *) segler}, + {3, 7, (uint8_t *) buffer}, + {8, 4, (uint8_t *) kreuz}, + {6, 6, (uint8_t *) ship} + }; + struct cursor cur = {0, 0}; + struct config cfg; + + int generation = 0, input, framerate = 17; + uint8_t width, height; + uint8_t ** worlds[2], ** world; +#if defined(RANDOM_SPAWNS) + int idle_gens = 0; + srand(time(NULL)); +#endif + + memset(&cfg, '\0', sizeof(struct config)); + /* initialize world */ + world = init_world(win, worlds, &width, &height); + /* make the world real */ + inhabit_world(patterns[3], width/2, height/2, worlds[0], width, height); + + /* simulation loop */ + while(!cfg.quit) { + if (!cfg.paused) { + /* calc next generation */ + usleep(1 / (float) framerate * 1000000); /* sleep */ + calc_next_gen(world, worlds[++generation % 2], width, height); + world = worlds[generation % 2]; /* new world */ + } + + /* handle events */ + switch (input = getch()) { +#ifdef ENABLE_HOTKEYS + case '+': /* increase framerate */ + framerate++; + break; + + case '-': /* decrease framerate */ + if (framerate > 1) framerate--; + break; + + case 'q': /* quit */ + cfg.quit = 1; + break; +#if defined(RANDOM_SPAWNS) + case 'd': /* disable random spawn */ + rnd_spawns = ~rnd_spawns; + break; +#endif + case 'p': /* pause */ + cfg.paused ^= 1; + break; + + case 'c': /* clean world */ + clean_world(world, width, height); + generation = 0; + break; +#endif +#if defined(ENABLE_HOTKEYS) || defined(ENABLE_CURSOR) + case '0': /* insert pattern */ + case '1': + case '2': + case '3': + case '4': + case '5': + inhabit_world(patterns[input - '0'], cur.x, cur.y, world, width, height); + break; +#endif +#ifdef ENABLE_CURSOR + case ' ': /* toggle cell at cursor position */ + world[cur.x][cur.y] = (world[cur.x][cur.y]) ? 0 : 1; + break; + + case KEY_MOUSE: /* move cursor to mouse posititon */ + if (getmouse(&event) == OK && event.bstate & BUTTON1_PRESSED) { + cur.x = event.x; + cur.y = event.y; + if (cur.x >= width) cur.x = width - 1; + if (cur.y >= height) cur.y = height - 1; + world[cur.x][cur.y] = (world[cur.x][cur.y]) ? 0 : 1; + } + break; + + case KEY_UP: + if (cur.y > 0) { + cur.y--; + } + break; + + case KEY_DOWN: + if (cur.y < height-1) { + cur.y++; + } + break; + + case KEY_LEFT: + if (cur.x > 0) { + cur.x--; + } + break; + + case KEY_RIGHT: + if (cur.x < width-1) { + cur.x++; + } + break; + case KEY_RESIZE: + world = resized(win, worlds, &width, &height); + break; +#endif + } + +#if defined(RANDOM_SPAWNS) + if (rnd_spawns) { + /* spawn a new pattern at a random position, if nothing happens */ + idle_gens++; + if (idle_gens >= RANDOM_SPAWNS && !cfg.paused) + { + idle_gens = 0; + inhabit_world(patterns[rand() % (sizeof(patterns)/sizeof(patterns[0]))], rand() % (width - 1), rand() % (height - 1), world, width, height); + } + } +#endif + + /* update screen */ + print_world(world, width, height); +#ifdef ENABLE_CURSOR + print_cursor(world, cur); +#endif +#ifdef ENABLE_STATUS + attron(COLOR_PAIR(1)); + for (int i = 0; i < width; i++) mvprintw(0, width - i, " "); + mvprintw(0, 0, "[generation:%4d] [cells:%3d] [fps:%2d] [width:%d] [height:%d] [cursor:%2d|%2d]", generation, calc_cell_count(world, width, height), framerate, width, height, cur.x, cur.y); + if (cfg .paused) mvprintw(0, width-6, "PAUSED"); + attroff(COLOR_PAIR(1)); +#endif + +#ifdef ENABLE_HOTKEYS + if (cfg.paused) { + print_menu(width, height); + usleep(1); + } +#endif + refresh(); + } + + free_all(worlds, width, height); + delwin(win); + endwin(); /* exit ncurses mode */ + return (EXIT_SUCCESS); +} diff --git a/suidcmd.c b/suidcmd.c new file mode 100644 index 0000000..b601c15 --- /dev/null +++ b/suidcmd.c @@ -0,0 +1,98 @@ +/* + * build with: gcc -std=c99 -D_GNU_SOURCE=1 -Wall -O2 -ffunction-sections -fdata-sections -fomit-frame-pointer ./suidcmd.c -o ./suidcmd + * strip -s ./suidcmd + */ + +#ifdef _HAVE_CONFIG +#include "config.h" +#endif +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <sys/wait.h> + + +#ifndef CMD +#define CMD "/usr/sbin/ether-wake" +#endif + + +int safe_exec(const char* cmdWithArgs) +{ + pid_t child; + if ( (child = fork()) == 0 ) { + size_t szCur = 0, szMax = 10; + char** args = calloc(szMax, sizeof(char**)); + const char* cmd = NULL; + + const char* prv = cmdWithArgs; + const char* cur = NULL; + while ( (cur = strchr(prv, ' ')) ) { + if (cmd == NULL) + cmd = strndup(prv, cur-prv); + + args[szCur++] = strndup(prv, cur-prv); + if (szCur >= szMax) { + szMax *= 2; + args = realloc(args, sizeof(char**)*szMax); + } + + cur++; + prv = cur; + } + if (cmd == NULL) { + cmd = cmdWithArgs; + } else { + args[szCur++] = strndup(prv, cur-prv); + } + args[szCur] = NULL; + execv(cmd, args); + } else { + int retval = 0; + waitpid(child, &retval, 0); + return retval; + } + return -1; +} + +int main(int argc, char** argv) +{ + uid_t ruid, euid, suid; + + if (getresuid(&ruid, &euid, &suid) != 0) { + perror("getresuid()"); + } else { + printf("%s: RUID:%u , EUID:%u , SUID:%u\n", argv[0], ruid, euid, suid); + } + + if (setuid(0) != 0) { + perror("setuid(0)"); + } else printf("%s: setuid(0)\n", argv[0]); + + char* cmd = NULL; + if (asprintf(&cmd, "%s", CMD) <= 0) { + fprintf(stderr, "%s: asprintf(\"%s\") error\n", argv[0], CMD); + return 1; + } + + char* prev_cmd = NULL; + for (int i = 1; i < argc; ++i) { + prev_cmd = cmd; + if (asprintf(&cmd, "%s %s", prev_cmd, argv[i]) < 0) { + fprintf(stderr, "%s: asprintf(\"%s\") error\n", argv[0], argv[i]); + return 1; + } + free(prev_cmd); + } + + int retval = -1; + switch ( (retval = safe_exec(cmd)) ) { + case -1: fprintf(stderr, "%s: could not create child process..\n", argv[0]); return 1; + case 127: fprintf(stderr, "%s: could not execute shell (child process)..\n", argv[0]); return 1; + default: + printf("%s: child process returned with: %d\n", argv[0], retval); + } + free(cmd); + return 0; +} @@ -0,0 +1,45 @@ +#include <stdio.h> +#include <stdbool.h> +#include <X11/Xlib.h> +#include <X11/extensions/scrnsaver.h> + + +/* Report amount of X server idle time. */ +/* gcc xidle.c -o xidle -lX11 -lXext -lXss */ + +int main(int argc, char *argv[]) +{ + Display *display; + int event_base, error_base; + XScreenSaverInfo info; + float seconds; + unsigned int d_seconds = 0; + + if (argc == 2) { + d_seconds = atoi(argv[1]); + } + + display = XOpenDisplay(""); + if (!display) + return -1; + + if (XScreenSaverQueryExtension(display, &event_base, &error_base) == true) { + if (XScreenSaverQueryInfo(display, DefaultRootWindow(display), &info) != true) { + fprintf(stderr, "Error: XScreenSaver QueryInfo failed\n"); + return -1; + } + seconds = (float)info.idle/1000.0f; + if ( d_seconds > 0 ) { + if (d_seconds <= (unsigned int) seconds) { + return 1; + } + } else { + printf("%f\n",seconds); + } + return 0; + } else { + fprintf(stderr,"Error: XScreenSaver Extension not present\n"); + return -1; + } +} + |