aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile59
-rw-r--r--README.md25
-rw-r--r--aes.c411
-rw-r--r--asciihexer.c46
-rw-r--r--config.h31
-rw-r--r--dummyshell.c622
-rw-r--r--gol.c469
-rw-r--r--suidcmd.c98
-rw-r--r--xidle.c45
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 />
diff --git a/aes.c b/aes.c
new file mode 100644
index 0000000..ba31b41
--- /dev/null
+++ b/aes.c
@@ -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;
+}
diff --git a/gol.c b/gol.c
new file mode 100644
index 0000000..77d54a6
--- /dev/null
+++ b/gol.c
@@ -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;
+}
diff --git a/xidle.c b/xidle.c
new file mode 100644
index 0000000..c2794fc
--- /dev/null
+++ b/xidle.c
@@ -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;
+ }
+}
+