summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEUcancER <root@euer.krebsco.de>2011-09-15 02:02:34 +0200
committerEUcancER <root@euer.krebsco.de>2011-09-15 02:02:34 +0200
commit095b22ab0c4b8ca7c6f33af2d1f75d3d82055455 (patch)
treea34afa0947b668fce2dc2b39fa1cfeac03386659
parent88517b3edfc7b633d210422afb8579e5d0d3d1e0 (diff)
parent90be8b346c43da2b36c0b4872fcf1190cfaeaa85 (diff)
Merge branch 'master' of github.com:krebscode/painload
-rw-r--r--.gitignore4
-rwxr-xr-xReaktor/IRC/asybot.py197
-rwxr-xr-xReaktor/IRC/bot.py34
-rwxr-xr-xReaktor/IRC/bot2.py130
-rw-r--r--Reaktor/IRC/content1
-rwxr-xr-xReaktor/IRC/index4
-rwxr-xr-xReaktor/IRC/install28
-rw-r--r--Reaktor/README.md23
-rwxr-xr-xReaktor/commands/reload2
-rwxr-xr-xReaktor/index7
-rwxr-xr-xReaktor/install6
-rw-r--r--cholerab/reaktor/priviliged_functions24
-rw-r--r--hyper/README.md15
-rw-r--r--hyper/process/Makefile19
-rw-r--r--hyper/process/main.go77
-rw-r--r--hyper/process/src/hyper/process/Makefile11
-rw-r--r--hyper/process/src/hyper/process/process.go132
-rw-r--r--hyper/process/test/bc.json11
-rw-r--r--hyper/sink/index.js13
-rwxr-xr-xpunani/bin/punani224
-rw-r--r--punani/doc/releases38
-rwxr-xr-xretiolum/bin/get-tinc-dir9
-rw-r--r--retiolum/hosts/zerg10
-rwxr-xr-xretiolum/scripts/tinc_setup/install.sh1
24 files changed, 772 insertions, 248 deletions
diff --git a/.gitignore b/.gitignore
index 0df2d5f6..5f187bc8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,8 @@
+# go
+_go_.8
+goinstall.log
+
# Linux kernel module
modules.order
Module.symvers
diff --git a/Reaktor/IRC/asybot.py b/Reaktor/IRC/asybot.py
new file mode 100755
index 00000000..99cb2fe6
--- /dev/null
+++ b/Reaktor/IRC/asybot.py
@@ -0,0 +1,197 @@
+#! /usr/bin/env python
+#
+# //Reaktor/IRC/asybot.py
+#
+
+def is_executable(x):
+ import os
+ return os.path.exists(x) and os.access(x, os.X_OK)
+
+from asynchat import async_chat as asychat
+from asyncore import loop
+from socket import AF_INET, SOCK_STREAM
+from signal import SIGALRM, signal, alarm
+from datetime import datetime as date, timedelta
+from sys import exit
+from re import split, search
+
+import logging,logging.handlers
+log = logging.getLogger('asybot')
+hdlr = logging.handlers.SysLogHandler(facility=logging.handlers.SysLogHandler.LOG_DAEMON)
+formatter = logging.Formatter( '%(filename)s: %(levelname)s: %(message)s')
+hdlr.setFormatter(formatter)
+log.addHandler(hdlr)
+
+class asybot(asychat):
+ def __init__(self, server, port, nickname, targets, **kwargs):
+ asychat.__init__(self)
+ self.server = server
+ self.port = port
+ self.nickname = nickname
+ self.targets = targets
+ self.username = kwargs['username'] if 'username' in kwargs else nickname
+ self.hostname = kwargs['hostname'] if 'hostname' in kwargs else nickname
+ self.ircname = kwargs['ircname'] if 'ircname' in kwargs else nickname
+ self.realname = kwargs['realname'] if 'realname' in kwargs else nickname
+ self.data = ''
+ self.set_terminator('\r\n')
+ self.create_socket(AF_INET, SOCK_STREAM)
+ self.connect((self.server, self.port))
+
+ # When we don't receive data for alarm_timeout seconds then issue a
+ # PING every hammer_interval seconds until kill_timeout seconds have
+ # passed without a message. Any incoming message will reset alarm.
+ self.alarm_timeout = 300
+ self.hammer_interval = 10
+ self.kill_timeout = 360
+ signal(SIGALRM, lambda signum, frame: self.alarm_handler())
+ self.reset_alarm()
+
+
+ def reset_alarm(self):
+ self.last_activity = date.now()
+ alarm(self.alarm_timeout)
+
+ def alarm_handler(self):
+ delta = date.now() - self.last_activity
+ if delta > timedelta(seconds=self.kill_timeout):
+ log.error('No data for %s. Giving up...' % delta)
+ exit(2)
+ else:
+ log.error('No data for %s. PINGing server...' % delta)
+ self.push('PING :%s' % self.nickname)
+ alarm(self.hammer_interval)
+
+ def collect_incoming_data(self, data):
+ self.data += data
+
+ def found_terminator(self):
+ log.debug('<< %s' % self.data)
+
+ message = self.data
+ self.data = ''
+
+ _, prefix, command, params, rest, _ = \
+ split('^(?::(\S+)\s)?(\S+)((?:\s[^:]\S*)*)(?:\s:(.*))?$', message)
+ params = params.split(' ')[1:]
+ #print([prefix, command, params, rest])
+
+ if command == 'PING':
+ self.push('PONG :%s' % rest)
+ log.info("Replying to servers PING with PONG :%s" %rest)
+
+ elif command == 'PRIVMSG':
+ self.on_privmsg(prefix, command, params, rest)
+
+ elif command == '433':
+ # ERR_NICKNAMEINUSE, retry with another name
+ _, nickname, int, _ = split('^.*[^0-9]([0-9]+)$', self.nickname) \
+ if search('[0-9]$', self.nickname) \
+ else ['', self.nickname, 0, '']
+ self.nickname = nickname + str(int + 1)
+ self.handle_connect()
+
+ self.reset_alarm()
+
+ def push(self, message):
+ log.debug('>> %s' % message)
+ asychat.push(self, message + self.get_terminator())
+
+ def handle_connect(self):
+ self.push('NICK %s' % self.nickname)
+ self.push('USER %s %s %s :%s' %
+ (self.username, self.hostname, self.server, self.realname))
+ self.push('JOIN %s' % ','.join(self.targets))
+
+ def on_privmsg(self, prefix, command, params, rest):
+ def PRIVMSG(text):
+ msg = 'PRIVMSG %s :%s' % (','.join(params), text)
+ self.push(msg)
+
+ def ME(text):
+ PRIVMSG('ACTION ' + text + '')
+
+ _from = prefix.split('!', 1)[0]
+
+ try:
+ _, _handle, _command, _argument, _ = split(
+ '^(\w+|\*):\s*(\w+)(?:\s+(.*))?$', rest)
+ except ValueError, error:
+ if search(self.nickname, rest):
+ PRIVMSG('I\'m so famous')
+ return # ignore
+
+ if _handle == self.nickname or _handle == '*':
+
+ from os.path import realpath, dirname, join
+ from subprocess import Popen as popen, PIPE
+
+ Reaktor_dir = dirname(realpath(dirname(__file__)))
+ public_commands = join(Reaktor_dir, 'public_commands')
+ command = join(public_commands, _command)
+
+ if is_executable(command):
+
+ env = {}
+ if _argument != None:
+ env['argument'] = _argument
+
+ try:
+ p = popen([command], stdin=PIPE, stdout=PIPE, stderr=PIPE, env=env)
+ except OSError, error:
+ ME('brain damaged')
+ log.error('OSError@%s: %s' % (command, error))
+ return
+
+ stdout, stderr = [ x[:len(x)-1] for x in
+ [ x.split('\n') for x in p.communicate()]]
+ code = p.returncode
+ pid = p.pid
+
+ log.info('command: %s -> %s' % (command, code))
+ [log.debug('%s stdout: %s' % (pid, x)) for x in stdout]
+ [log.debug('%s stderr: %s' % (pid, x)) for x in stderr]
+
+ if code == 0:
+ [PRIVMSG(x) for x in stdout]
+ [PRIVMSG(x) for x in stderr]
+ else:
+ ME('mimimi')
+
+ else:
+ if _handle != '*':
+ PRIVMSG(_from + ': you are made of stupid')
+
+
+# retrieve the value of a [singleton] variable from a tinc.conf(5)-like file
+def getconf1(x, path):
+ from re import findall
+ pattern = '(?:^|\n)\s*' + x + '\s*=\s*(.*\w)\s*(?:\n|$)'
+ y = findall(pattern, open(path, 'r').read())
+ if len(y) < 1:
+ raise AttributeError("len(getconf1('%s', '%s') < 1)" % (x, path))
+ if len(y) > 1:
+ y = ' '.join(y)
+ raise AttributeError("len(getconf1('%s', '%s') > 1)\n ====> %s"
+ % (x, path, y))
+ return y[0]
+
+if __name__ == "__main__":
+ from os import environ as env
+
+ lol = logging.DEBUG if env.get('debug',False) else logging.INFO
+ logging.basicConfig(level=lol)
+ name = getconf1('Name', '/etc/tinc/retiolum/tinc.conf')
+ hostname = '%s.retiolum' % name
+ nick = str(env.get('nick', name))
+ host = str(env.get('host', 'supernode'))
+ port = int(env.get('port', 6667))
+ target = str(env.get('target', '#retiolum'))
+ log.info('=> irc://%s@%s:%s/%s' % (nick, host, port, target))
+
+ from getpass import getuser
+ asybot(host, port, nick, [target], username=getuser(),
+ ircname='//Reaktor running at %s' % hostname,
+ hostname=hostname)
+
+ loop()
diff --git a/Reaktor/IRC/bot.py b/Reaktor/IRC/bot.py
deleted file mode 100755
index af974f4e..00000000
--- a/Reaktor/IRC/bot.py
+++ /dev/null
@@ -1,34 +0,0 @@
-#! /usr/bin/env python2
-
-from irclib import IRC, ServerConnectionError, is_channel
-from sys import exit
-from os import environ as env
-
-host = str(env.get('host', 'irc.freenode.org'))
-port = int(env.get('port', 6667))
-nick = str(env.get('nick', 'crabspasm'))
-channel = str(env.get('channel', '#tincspasm'))
-print '====> irc://%s@%s:%s/%s' % (nick, host, port, channel)
-
-irc = IRC()
-try:
- client = irc.server().connect(host, port, nick)
-except ServerConnectionError, error:
- print error
- exit
-
-def on_connect(connection, event):
- connection.join(channel)
- print 'Es passiert...'
-
-def on_join(connection, event):
- connection.privmsg(channel, 'lol')
-
-def on_disconnect(connection, event):
- exit
-
-client.add_global_handler('welcome', on_connect)
-client.add_global_handler('join', on_join)
-client.add_global_handler('disconnect', on_disconnect)
-
-irc.process_forever()
diff --git a/Reaktor/IRC/bot2.py b/Reaktor/IRC/bot2.py
deleted file mode 100755
index 326dd8f5..00000000
--- a/Reaktor/IRC/bot2.py
+++ /dev/null
@@ -1,130 +0,0 @@
-#! /usr/bin/env python
-#
-# //Reaktor/IRC/bot2.py
-#
-
-from __future__ import print_function
-from irclib import SimpleIRCClient, ServerConnectionError, is_channel
-from sys import exit
-from os import environ as env
-import re
-
-class IRCBot(SimpleIRCClient):
- def __init__(self, target):
- SimpleIRCClient.__init__(self)
- self.target = target
-
- def on_pubmsg(self, connection, event):
-
- def PRIVMSG(target, text):
- self.connection.privmsg(target, text)
-
- def ME(target, text):
- PRIVMSG(target, 'ACTION ' + text + '')
-
- def is_executable(x):
- import os
- return os.path.exists(x) and os.access(x, os.X_OK)
-
- _nickname = connection.get_nickname()
- _source = event.source()
- _from = _source.split('!', 1)[0]
- _target = event.target()
-
- try:
- _, _handle, _command, _argument, _ = re.split(
- '^(\w+|\*):\s*(\w+)(?:\s+(.*))?$', event.arguments()[0])
- except ValueError, error:
- if re.search(_nickname, event.arguments()[0]):
- PRIVMSG(self.target, 'I\'m so famous')
- return # ignore
-
- if _handle == _nickname or _handle == '*':
-
- from os.path import realpath, dirname, join
- from subprocess import Popen as popen, PIPE
-
- Reaktor_dir = dirname(realpath(dirname(__file__)))
- public_commands = join(Reaktor_dir, 'public_commands')
- command = join(public_commands, _command)
-
- if is_executable(command):
-
- env = {}
- if _argument != None:
- env['argument'] = _argument
-
- try:
- p = popen([command], stdin=PIPE, stdout=PIPE, stderr=PIPE, env=env)
- except OSError, error:
- ME(self.target, 'is made of stupid')
- print('OSError@%s: %s' % (command, error))
- return
-
- stdout, stderr = [ x[:len(x)-1] for x in
- [ x.split('\n') for x in p.communicate()]]
- code = p.returncode
- pid = p.pid
-
- print('command: %s -> %s' % (command, code))
- [print('%s stdout: %s' % (pid, x)) for x in stdout]
- [print('%s stderr: %s' % (pid, x)) for x in stderr]
-
- if code == 0:
- [PRIVMSG(self.target, x) for x in stdout]
- [PRIVMSG(_source, x) for x in stderr]
- else:
- ME(self.target, 'mimimi')
-
- else:
- if _handle != '*':
- PRIVMSG(self.target, _from + ': you are made of stupid')
-
- def on_welcome(self, connection, event):
- print('I\'m welcome! :D joining to %s now...' % (self.target))
- if is_channel(self.target):
- connection.join(self.target)
- else:
- self.connection.privmsg(self.target, 'lol')
- self.connection.quit('Pong timeout: 423 seconds')
-
- def on_join(self, connection, event):
- print('Es passiert in %s' % (self.target))
-
- def on_disconnect(self, connection, event):
- # TODO reconnect
- exit(0)
-
-# retrieve the value of a [singleton] variable from a tinc.conf(5)-like file
-def getconf1(x, path):
- from re import findall
- pattern = '(?:^|\n)\s*' + x + '\s*=\s*(.*\w)\s*(?:\n|$)'
- y = findall(pattern, open(path, 'r').read())
- if len(y) < 1:
- raise AttributeError("len(getconf1('%s', '%s') < 1)" % (x, path))
- if len(y) > 1:
- y = ' '.join(y)
- raise AttributeError("len(getconf1('%s', '%s') > 1)\n ====> %s"
- % (x, path, y))
- return y[0]
-
-def main():
- name = getconf1('Name', '/etc/tinc/retiolum/tinc.conf')
- nick = str(env.get('nick', name))
- host = str(env.get('host', 'supernode'))
- port = int(env.get('port', 6667))
- target = str(env.get('target', '#retiolum'))
- print('====> irc://%s@%s:%s/%s' % (nick, host, port, target))
-
- client = IRCBot(target)
- try:
- from getpass import getuser
- client.connect(host, port, nick, username=getuser(),
- ircname='//Reaktor running at %s.retiolum' % (name))
- except ServerConnectionError, error:
- print(error)
- exit(1)
- client.start()
-
-if __name__ == "__main__":
- main()
diff --git a/Reaktor/IRC/content b/Reaktor/IRC/content
deleted file mode 100644
index e0292376..00000000
--- a/Reaktor/IRC/content
+++ /dev/null
@@ -1 +0,0 @@
-python-irclib-0.4.6/ircbot.py
diff --git a/Reaktor/IRC/index b/Reaktor/IRC/index
index 68b6cf33..24982c76 100755
--- a/Reaktor/IRC/index
+++ b/Reaktor/IRC/index
@@ -4,6 +4,4 @@ set -xeuf
# cd //Reaktor
cd $(dirname $(readlink -f $0))/..
-IRC/install
-
-exec python IRC/bot2.py "$@"
+exec python IRC/asybot.py "$@"
diff --git a/Reaktor/IRC/install b/Reaktor/IRC/install
deleted file mode 100755
index d5f7a8c1..00000000
--- a/Reaktor/IRC/install
+++ /dev/null
@@ -1,28 +0,0 @@
-#! /bin/sh
-set -xeuf
-
-# cd //Reaktor/IRC
-cd $(dirname $(readlink -f $0))
-
-# install irclib.py
-{
- PV=0.4.6
- PN=python-irclib
- P=$PN-$PV
- tarball=$P.tar.gz
- URL=http://downloads.sourceforge.net/$PN/$tarball
- SHA1SUM=c6271e44293ed51c21af0f44ce106667d3006e6f
-
- file=irclib.py
-
- if ! echo "$SHA1SUM $file" | sha1sum -c; then
- temp=`mktemp`
- trap "rm -f $temp" EXIT INT
-
- echo $P/$file > $temp
- curl -LfsS $URL | tar --strip-components=1 -zxT $temp
- fi
- echo "$SHA1SUM $file" | sha1sum -c
-}
-
-
diff --git a/Reaktor/README.md b/Reaktor/README.md
index 05af8ef5..a581c6bd 100644
--- a/Reaktor/README.md
+++ b/Reaktor/README.md
@@ -2,28 +2,25 @@
## Quickstart
- ## 1. prepare Reaktor
- //Reaktor/install
+ ## 1. create a dedicated user
+ useradd reaktor
- ## 2. create a dedicated user
- useradd Reaktor
+ ## 2. marry Reaktor with /sbin/init
- ## 3. marry Reaktor with /sbin/init
-
- ## 3a. /etc/inittab-like foo
- echo 10:2345:respawn:/bin/su Reaktor -c /krebs/Reaktor/index >>/etc/inittab
- # or 10:2345:respawn:/usr/bin/sudo -u Reaktor /krebs/Reaktor/index
- # if Reaktor's shell is /bin/false or similar
- # [check with e.g getent passwd Reaktor]
+ ## 2a. /etc/inittab-like foo
+ echo 10:2345:respawn:/bin/su reaktor -c /krebs/Reaktor/index >>/etc/inittab
+ # or 10:2345:respawn:/usr/bin/sudo -u reaktor /krebs/Reaktor/index
+ # if reaktor's shell is /bin/false or similar
+ # [check with e.g getent passwd reaktor]
telinit q
- ## 3b. upstart-like foo
+ ## 2b. upstart-like foo
cat > /etc/init/Reaktor.conf <<EOF
description "Krebs Reaktor"
author "The Ministerium"
stop on runlevel [016]
respawn
- exec /usr/bin/sudo -u Reaktor /krebs/Reaktor/index
+ exec /usr/bin/sudo -u reaktor /krebs/Reaktor/index
EOF
start Reaktor
diff --git a/Reaktor/commands/reload b/Reaktor/commands/reload
index 2b78b178..bfa1f041 100755
--- a/Reaktor/commands/reload
+++ b/Reaktor/commands/reload
@@ -1,2 +1,2 @@
#! /bin/sh
-exec pkill -U Reaktor
+exec pkill -U reaktor
diff --git a/Reaktor/index b/Reaktor/index
index ac647ca3..05827373 100755
--- a/Reaktor/index
+++ b/Reaktor/index
@@ -4,4 +4,11 @@ set -euf
# cd //Reaktor
cd $(dirname $(readlink -f $0))
+# redirect stdout [and stderr] to syslog
+stdout=`mktemp -u`
+mkfifo $stdout
+trap "rm -vf $stdout" EXIT INT
+exec 1<>$stdout 2>&1
+logger -t Reaktor -f $stdout &
+
exec IRC/index
diff --git a/Reaktor/install b/Reaktor/install
deleted file mode 100755
index 761bc437..00000000
--- a/Reaktor/install
+++ /dev/null
@@ -1,6 +0,0 @@
-#! /bin/sh
-set -euf
-
-cd $(dirname $(readlink -f $0))
-
-exec IRC/install
diff --git a/cholerab/reaktor/priviliged_functions b/cholerab/reaktor/priviliged_functions
new file mode 100644
index 00000000..a673267e
--- /dev/null
+++ b/cholerab/reaktor/priviliged_functions
@@ -0,0 +1,24 @@
+Use Case 1: Request update on Host
+=================================
+
+< user> bot: update
+< bot> /whois user
+< bot> /msg user [CHALLENGE]
+< user> /msg bot [CHALLENGE-RESPONSE]
+< bot> updating...
+< bot> now on rev XXXXX
+
+Command Flow
+----------------
+The bot has a locally stored list of [trusted] hosts along with their public
+key, preferably from the tinc/retiolum directory.
+
+The bot encrypts a 1K Byte long message with the public key of the host
+retrieved by the /whois command.
+
+This challenge is sent to the user requesting the command via private message.
+The user then decrpyts the message with its own private key and sends the
+decrpyted message to the bot.
+
+The bot then executes the requested command if the challenge is answered
+correctly
diff --git a/hyper/README.md b/hyper/README.md
new file mode 100644
index 00000000..07fa1de5
--- /dev/null
+++ b/hyper/README.md
@@ -0,0 +1,15 @@
+# Overview
+
+## start conductor on port 8888 and sink on 1337
+
+ //hyper/process/main
+ //bin/node //hyper/sink
+
+## create bc process and retrieve it's process id (AKA {path})
+
+ url=http://localhost:8888
+ curl -fvsS --data-binary @//hyper/process/test/bc.json $url/proc
+
+## send data for calculation
+
+ echo 9000+2^42 | curl -fvsS --data-binary @- $url/{path}
diff --git a/hyper/process/Makefile b/hyper/process/Makefile
new file mode 100644
index 00000000..bbc1c2fb
--- /dev/null
+++ b/hyper/process/Makefile
@@ -0,0 +1,19 @@
+include $(GOROOT)/src/Make.inc
+
+GCIMPORTS = -I pkg/$(GOOS)_$(GOARCH)
+LDIMPORTS = -L pkg/$(GOOS)_$(GOARCH)
+
+TARG=main
+GOFILES=\
+ main.go\
+
+include $(GOROOT)/src/Make.cmd
+
+export GOPATH := $(PWD)
+.PHONY: prepare
+prepare:
+ #goinstall -v github.com/garyburd/twister/server
+ goinstall -v gorilla.googlecode.com/hg/gorilla/mux
+ goinstall -v $(PWD)/src/hyper/process
+
+_go_.$O: prepare
diff --git a/hyper/process/main.go b/hyper/process/main.go
new file mode 100644
index 00000000..5420f681
--- /dev/null
+++ b/hyper/process/main.go
@@ -0,0 +1,77 @@
+package main
+
+import "json"
+import "log"
+import "http"
+import "gorilla.googlecode.com/hg/gorilla/mux"
+import "os"
+import "fmt"
+import "bytes"
+
+import "hyper/process"
+
+var proc = map[string] *hyper.Process{}
+
+// TODO Retrieve Process, Write, Kill [autokill], get exit code
+
+func RespondJSON(res http.ResponseWriter, v interface{}) os.Error {
+ content, err := json.Marshal(v)
+ if err == nil {
+ log.Printf("< %s", content)
+ res.Header().Set("Content-Type", "application/json; charset=\"utf-8\"")
+ res.WriteHeader(http.StatusOK)
+ res.Write(content)
+ } else {
+ log.Printf("%s while json.Marshal(%s)", err, v)
+ }
+ return err
+}
+
+func CreateProcessHandler(res http.ResponseWriter, req *http.Request) {
+ if p, err := hyper.NewProcess(req); err == nil {
+ id := p.Id()
+ proc[id] = p
+ RespondJSON(res, &map[string]string{
+ "path": fmt.Sprintf("/proc/%s", id),
+ })
+ } else {
+ log.Printf("%s", err)
+ res.WriteHeader(http.StatusInternalServerError)
+ }
+}
+
+func RetrieveProcess(res http.ResponseWriter, req *http.Request) {
+ if p := proc[mux.Vars(req)["id"]]; p != nil {
+ RespondJSON(res, p)
+ } else {
+ res.WriteHeader(http.StatusNotFound)
+ }
+}
+
+func FeedProcess(res http.ResponseWriter, req *http.Request) {
+ if p := proc[mux.Vars(req)["id"]]; p != nil {
+ body := make([]byte, 4096)
+ if _, err := req.Body.Read(body); err == nil {
+ body = bytes.TrimRight(body, string([]byte{0}))
+ p.Write(body)
+ //if err := p.Write(body); err == nil {
+ RespondJSON(res, true)
+ //}
+ }
+ } else {
+ res.WriteHeader(http.StatusNotFound)
+ }
+}
+
+func main() {
+
+ // Gorilla
+ mux.HandleFunc("/proc", CreateProcessHandler).Methods("POST")
+ mux.HandleFunc("/proc/{id}", RetrieveProcess).Methods("GET")
+ mux.HandleFunc("/proc/{id}", FeedProcess).Methods("POST")
+
+ err := http.ListenAndServe("0.0.0.0:8888", mux.DefaultRouter)
+ if err != nil {
+ log.Fatal("ListenAndServe: ", err.String())
+ }
+}
diff --git a/hyper/process/src/hyper/process/Makefile b/hyper/process/src/hyper/process/Makefile
new file mode 100644
index 00000000..7ecda716
--- /dev/null
+++ b/hyper/process/src/hyper/process/Makefile
@@ -0,0 +1,11 @@
+include ${GOROOT}/src/Make.inc
+
+TARG=hyper/process
+
+GOFILES=\
+ process.go\
+
+#DEPS=\
+# gorilla.googlecode.com/hg/gorilla/context\
+
+include ${GOROOT}/src/Make.pkg
diff --git a/hyper/process/src/hyper/process/process.go b/hyper/process/src/hyper/process/process.go
new file mode 100644
index 00000000..18cf55fb
--- /dev/null
+++ b/hyper/process/src/hyper/process/process.go
@@ -0,0 +1,132 @@
+package hyper
+
+import "fmt"
+import "http"
+import "bytes"
+import "json"
+import "os"
+
+type Process struct {
+ Path string `json:"path"`
+ Argv []string `json:"argv"`
+ Envp map[string]string `json:"envp"`
+ //Stdin string `json:"stdin"`
+ Stdout string `json:"stdout"`
+ Stderr string `json:"stderr"`
+ process *os.Process
+ process_stdin *os.File
+ process_stdout *os.File
+ process_stderr *os.File
+ id string
+ client http.Client
+}
+
+func (p *Process) Id() string {
+ return p.id
+}
+
+func NewProcess(req *http.Request) (*Process, os.Error) {
+ body := make([]byte, 4096)
+ _, err := req.Body.Read(body)
+ if err != nil {
+ return nil, err
+ }
+
+ body = bytes.TrimRight(body, string([]byte{0}))
+
+ var p Process
+
+ if err := json.Unmarshal(body, &p); err != nil {
+ return nil, err
+ }
+
+ p.id = gensym()
+
+ if err := p.Start(); err != nil {
+ return nil, err
+ }
+
+ return &p, nil
+}
+
+func (hp *Process) Write(b []byte) {
+ n, err := hp.process_stdin.Write(b)
+ if err != nil {
+ fmt.Printf("Write: %s\n", err)
+ } else {
+ fmt.Printf("Wrote: %d bytes\n", n)
+ }
+}
+
+func (hp *Process) Start() os.Error {
+ var name = hp.Path //os.Args[1] //"/usr/b"
+ var argv = hp.Argv //os.Args[1:] //[]string{ "bc" }
+ //var chroot = false
+ //var dir = "/var/empty"
+ var files [3][2]*os.File
+ var err os.Error
+
+ for i, _ := range files {
+ files[i][0], files[i][1], err = os.Pipe()
+ if err != nil {
+ return err
+ }
+ }
+
+ var env []string
+ for k, v := range hp.Envp {
+ env = append(env, fmt.Sprintf("%s=%s", k, v))
+ }
+
+ var attr = &os.ProcAttr{
+ //Dir: dir,
+ Env: env, //os.Environ(),
+ Files: []*os.File{ files[0][0], files[1][1], files[2][1]},
+ }
+
+ //var foo, _ = json.Marshal(attr)
+ //fmt.Printf("%s\n", foo)
+
+ hp.process, err = os.StartProcess(name, argv, attr)
+ if err != nil {
+ return err
+ }
+
+ hp.process_stdin = files[0][1]
+ hp.process_stdout = files[1][0]
+ hp.process_stderr = files[2][0]
+
+ for _, file := range attr.Files {
+ file.Close()
+ }
+
+ go hp.reader(hp.process_stdout, hp.Stdout)
+ go hp.reader(hp.process_stderr, hp.Stderr)
+ return nil
+}
+
+func (p *Process) reader(file *os.File, url string) {
+ var b []byte = make([]byte, 1024)
+ var err os.Error = nil
+ for err == nil {
+ var n int
+ n, err = file.Read(b)
+ fmt.Printf("data: %d, %s\n", n, b)
+
+ res, err := p.client.Post(url, "application/octet-stream", bytes.NewBuffer(b))
+ res = res
+ if err != nil {
+ fmt.Printf("EE: %s: %s\n", url, err)
+ }
+ }
+}
+
+func gensym() string {
+ f, _ := os.Open("/dev/urandom")
+ b := make([]byte, 16)
+ f.Read(b)
+ f.Close()
+ uuid := fmt.Sprintf("%x-%x-%x-%x-%x", b[0:4], b[4:6], b[6:8], b[8:10], b[10:])
+ return uuid
+}
+
diff --git a/hyper/process/test/bc.json b/hyper/process/test/bc.json
new file mode 100644
index 00000000..5b3b0721
--- /dev/null
+++ b/hyper/process/test/bc.json
@@ -0,0 +1,11 @@
+{
+ "path": "/usr/bin/bc",
+ "argv": [
+ "bc"
+ ],
+ "envp": {
+ "was": "geht"
+ },
+ "stdout": "http://127.0.0.1:1337/",
+ "stderr": "http://127.0.0.1:1337/"
+}
diff --git a/hyper/sink/index.js b/hyper/sink/index.js
new file mode 100644
index 00000000..b556b88d
--- /dev/null
+++ b/hyper/sink/index.js
@@ -0,0 +1,13 @@
+require('http').createServer(function (req, res) {
+
+ req.on('data', function (data) {
+ require('util').puts(data);
+ });
+
+ req.on('end', function () {
+ res.writeHead(200, {'Content-Type': 'text/plain', 'Content-Length': 0});
+ res.end();
+ });
+}).listen(1337, '127.0.0.1', function () {
+ console.log('Running HyperSink at http://127.0.0.1:1337/');
+});
diff --git a/punani/bin/punani b/punani/bin/punani
index 7af6f0f8..d118b13c 100755
--- a/punani/bin/punani
+++ b/punani/bin/punani
@@ -6,33 +6,150 @@
# -E -i spec insert a package to the target filesystem
# -E -r spec remove a package
#
-
+set -euf
godmode() {
if test "${nosudo-false}" != true -a `id -u` != 0; then
- echo "Warning: we require god mode..." >&2
+ echo "!! we require god mode..." >&2
exec sudo "$0" "$@"
exit 23 # go to hell
fi
}
-if pacman --version 2>/dev/null | fgrep -q Pacman; then
- system="${system+$system, }arch-like"
-fi
+# return the 'system' variable
+# currently be:
+# arch-like
+# debian-like
+guess_system()
+{
+ if [ -f "/etc/arch-release" ] ;then
+ system="${system+$system, }arch-like"
+ fi
+ if [ -f "/etc/lsb-release" -o -f "/etc/debian_version" ] ;then
+ system="${system+$system, }debian-like"
+ fi
+
+}
+arch_aur_helper()
+{
+ # pacman is the last fallback helper
+ manager="yaourt clyde packer bauerbill tupac pacaur paktahn pbfetch aurget aurora cower powaur pacman"
+ for i in $manager;do
+ mgr=`which $i`
+ if [ "$mgr" ] ;then
+ echo $mgr
+ return 0
+ fi
+ done
+ echo "!! no helper found, this should never happen(tm)."
+ return 1
+}
+handle_system () {
+ case "$system" in
+ (*arch-like*)
+ # dryrun
+ # TODO dryrun not dry enough for aur helper
+ if [ "${dryrun-}" ];then
+ pacman () { echo "pacman $@" ; }
+ pkgfile () { echo "pkgfile $@"; }
+ yaourt () { echo "yaourt $@" ; }
+ fi
+
+ # get dependencies :
+ # we need pkgfile
+ if ! [ `which pkgfile` ] ; then
+ pacman -S --noconfirm pkgtools
+ pkgfile -u
+ fi
+ punani_Scientist_update() {
+ pacman -Sy
+ pkgtool -u
+ }
+ punani_Scientist_search() {
+ pkgfile $1
+ if [ "${hard-}" ] ; then
+ mgr=`arch_aur_helper`
+ $mgr -Ss $1
+ fi
+
+ }
-case "$system" in
- (*arch-like*)
- punani_Engineer_insert() {
- pacman -Sy "$1"
- }
- punani_Engineer_remove() {
- pacman -Rcs "$1"
- }
- ;;
- (*)
- email='krebs@syntax-fehler.de'
- irc_host='irc.freenode.org'
- irc_channel='#tincspasm'
- cat>&2<<EOF
+ punani_Engineer_insert() {
+ # punani under archlinux first tries to load the packages with the given file name
+ # it needs pkgfile for that
+ #
+ # when trying harder it tries to load the package with the given name directly via yaourt
+ echo "** trying to find package with given file"
+ if pacman -S `pkgfile $1` 2>/dev/null; then
+ echo "++ finished"
+ exit 0
+ else
+ echo "!! nothing found in base repos"
+ if [ "${hard-}" ] ; then
+ echo "** trying harder"
+ echo "** trying yaourt directly with given package"
+ mgr=`arch_aur_helper`
+ if $mgr -S $1 ;then
+ echo "++ finished"
+ return 0
+ else
+ echo "!! giving up...i am sorry"
+ return 1
+ fi</