Skip to content
frobork.c 3.42 KiB
Newer Older
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>

enum frobork_kode {
        FK_RETURN,
        FK_EXECVE,
        FK_DUP2,
        FK_CLOSE,
        FK_FCHDIR,
        FK_SETUID,
        FK_SETGID,
        FK_SIGNAL,
        FK_SETSID,
        FK_SETPGID,
        FK_TCSETPGRP
};


/*
 * frobork.c
 */

#define XX (*kode++)
#define T(type) ((type)XX)
#define X T(int)
#define TRY2(x,y) if((x)==(y)) { goto on_error; } ; break;
#define TRY(x) TRY2(x,-1)
#define OBJLEN(x) (x),sizeof(x)
#define GETX {x=X;}

#if 0 /* support for any of the types we use being larger than an int */
#define MAXUINTP1 (1ULL+(unsigned long long)((unsigned int)-1))
#define SIZUI (sizeof(unsigned int))
#define SIZULL (sizeof(unsigned int))

unsigned long long read_and_increment_pointer (unsigned int**p, unsigned int size) {
  unsigned long long r;
  unsigned int *q = *p;
  unsigned int i = 0;
  unsigned long long factor = 1;

  if (size <= SIZUI) {
    r = *q;
    q++;
  } else   if (size > SIZULL) {
      write(2,OBJLEN("frobork: bad int size\n"));
      exit(43);
  } else {
    r = 0;
    while (i<size) {
      r += *q*f;
      f *= MAXUINTP1;
      q++;
      i+=SIZUI;
    }
  }
  *p = q;
  return r;
}
#define T(type) ((type)read_and_increment_pointer((unsigned int**)&kode,sizeof(type)))
#endif

int frobork (int* kode)
{
        pid_t pid, p1,p2;
        int x;
	sighandler_t sh;
        char *a,**b,**c;

        pid = fork();
        if (pid) {
                return pid;
        }

        while (1) {
                switch (X) {
                case FK_RETURN:
                        return(0);
                case FK_EXECVE:
                        a=T(char *);b=T(char **);c=T(char **);
                        TRY(execve(a,b,c));
                        break;
                case FK_DUP2:
                        GETX; TRY(dup2(x,X));
                        break;
                case FK_CLOSE:
                        TRY(close(X));
                        break;
                case FK_FCHDIR:
                        TRY(fchdir(X));
                        break;
                case FK_SETUID:
                        TRY(setuid(T(uid_it)));
                        break;
                case FK_SETGID:
                        TRY(setgid(T(gid_it)));
                        break;
                case FK_SIGNAL:
                        GETX;
			switch(X) {
			case 0: sh = SIG_...;
			case 1: sh = SIG_...;
			case 2: sh = SIG_...;
			}
			TRY2(signal(x,y,SIG_ERR);
                        break;
                case FK_SETSID:
                        TRY(setsid());
                        break;
                case FK_SETPGID:
                        p1=T(pid_t);p2=T(pid_t);
                        TRY(setpgid(p1,p2));
                        break;
                case FK_TCSETPGRP:
                        GETX;TRY(tcsetpgrp(x,T(pid_t)));
                        break;
                default:
                        write(2,OBJLEN("frobork: bad code\n"));
                        exit(42);
                }
        }
        return 0;
on_error:
        perror("frobork");
        exit(44);
}

#ifdef TEST_FROBORK
int main (int argc, char** argv) {
        int kode[] = {
                FK_DUP2, 0, 4,
                FK_CLOSE, 4,
                FK_SETSID,
                FK_RETURN
        };
        argc++;argv++;
        printf("pid=%d frobork returned %d\n",getpid(),frobork(kode));
        return 0;
}
#endif