Pulled all of src
Before Width: | Height: | Size: 306 KiB After Width: | Height: | Size: 306 KiB |
Before Width: | Height: | Size: 120 KiB After Width: | Height: | Size: 120 KiB |
Before Width: | Height: | Size: 1.2 MiB After Width: | Height: | Size: 1.2 MiB |
Before Width: | Height: | Size: 400 KiB After Width: | Height: | Size: 400 KiB |
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 38 KiB |
Before Width: | Height: | Size: 729 KiB After Width: | Height: | Size: 729 KiB |
Before Width: | Height: | Size: 1.1 MiB After Width: | Height: | Size: 1.1 MiB |
Before Width: | Height: | Size: 452 KiB After Width: | Height: | Size: 452 KiB |
Before Width: | Height: | Size: 95 KiB After Width: | Height: | Size: 95 KiB |
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 44 KiB |
Before Width: | Height: | Size: 97 KiB After Width: | Height: | Size: 97 KiB |
Before Width: | Height: | Size: 61 KiB After Width: | Height: | Size: 61 KiB |
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 31 KiB |
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 52 KiB |
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 980 KiB After Width: | Height: | Size: 980 KiB |
Before Width: | Height: | Size: 87 KiB After Width: | Height: | Size: 87 KiB |
Before Width: | Height: | Size: 8.3 KiB After Width: | Height: | Size: 8.3 KiB |
Before Width: | Height: | Size: 158 KiB After Width: | Height: | Size: 158 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
108
g.cgi.go
|
@ -1,108 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"crypto/md5"
|
|
||||||
"fmt"
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
"os/exec"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// printf "USER:PASS" | base64 | while read a; do printf "%s" "$a" | md5sum; done
|
|
||||||
const AuthFilename = "/home/neale/.config/g.cgi/authorization"
|
|
||||||
const GitProjectRoot = "/home/neale/projects"
|
|
||||||
|
|
||||||
func execv(name string, arg ...string) {
|
|
||||||
c := exec.Command(name, arg...)
|
|
||||||
c.Stdin = os.Stdin
|
|
||||||
c.Stdout = os.Stdout
|
|
||||||
c.Stderr = os.Stderr
|
|
||||||
if err := c.Run(); err != nil {
|
|
||||||
log.Print(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Authenticated() bool {
|
|
||||||
auth := os.Getenv("HTTP_AUTHORIZATION")
|
|
||||||
if auth == "" {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Build up a string to match
|
|
||||||
parts := strings.Split(auth, " ")
|
|
||||||
switch {
|
|
||||||
case len(parts) != 2:
|
|
||||||
return false
|
|
||||||
case parts[0] != "Basic":
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
hash := md5.Sum([]byte(parts[1]))
|
|
||||||
hashhex := fmt.Sprintf("%x", hash)
|
|
||||||
|
|
||||||
authfile, err := os.Open(AuthFilename)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
defer authfile.Close()
|
|
||||||
|
|
||||||
scanner := bufio.NewScanner(authfile)
|
|
||||||
for scanner.Scan() {
|
|
||||||
line := scanner.Text()
|
|
||||||
if line == "" || strings.HasPrefix(line, "#") {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if line == hashhex {
|
|
||||||
os.Setenv("AUTH_TYPE", parts[0])
|
|
||||||
os.Setenv("REMOTE_USER", "XXX-neale")
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func notice() {
|
|
||||||
fmt.Println("Content-type: text/html")
|
|
||||||
fmt.Println()
|
|
||||||
fmt.Println("<!DOCTYPE html>")
|
|
||||||
fmt.Println("<html><head>")
|
|
||||||
fmt.Println("<title>Neale's Projects have Moved</title>")
|
|
||||||
fmt.Println("<meta name=\"viewport\" content=\"width=device-width\">")
|
|
||||||
fmt.Println("</head><body>")
|
|
||||||
fmt.Println("<h1>Neale's Projects have Moved</h1>")
|
|
||||||
fmt.Println("I've moved most of my stuff to")
|
|
||||||
fmt.Println("<a href=\"https://github.com/nealey\">Github</a>.")
|
|
||||||
fmt.Println("<p>")
|
|
||||||
fmt.Println("X11 things may now be in the")
|
|
||||||
fmt.Println("<a href=\"https://github.com/9wm\">9wm team</a>.")
|
|
||||||
fmt.Println("<p>")
|
|
||||||
fmt.Println("Network security things may now be in the")
|
|
||||||
fmt.Println("<a href=\"https://github.com/dirtbags\">dirtbags team</a>.")
|
|
||||||
fmt.Println("</body></html>")
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
log.SetFlags(0)
|
|
||||||
//log.SetOutput(os.Stdout)
|
|
||||||
//log.SetPrefix("Status: 500 CGI Go Boom\nContent-type: text/plain\n\nERROR: ")
|
|
||||||
|
|
||||||
uri := os.Getenv("REQUEST_URI")
|
|
||||||
switch {
|
|
||||||
case strings.HasSuffix(uri, "git-upload-pack") || strings.HasSuffix(uri, "git-receive-pack"):
|
|
||||||
if Authenticated() {
|
|
||||||
os.Setenv("GIT_PROJECT_ROOT", GitProjectRoot)
|
|
||||||
execv("git", "http-backend")
|
|
||||||
} else {
|
|
||||||
fmt.Println("Status: 401 Not Authorized")
|
|
||||||
fmt.Println("Content-type: text/plain")
|
|
||||||
fmt.Println("WWW-Authenticate: Basic realm=\"git\"")
|
|
||||||
fmt.Println()
|
|
||||||
fmt.Println("Nope", os.Getenv("HTTP_AUTHORIZATION"))
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
notice()
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1 +0,0 @@
|
||||||
COPY += src/9wm/9wm.png
|
|
BIN
src/9wm/9wm.png
Before Width: | Height: | Size: 75 KiB |
|
@ -1,54 +0,0 @@
|
||||||
Title: 9wm
|
|
||||||
Author: Neale Pickett <neale@woozle.org>
|
|
||||||
|
|
||||||
9wm is an X11 window manager inspired by the Plan 9 window manager 8½.
|
|
||||||
It provides a very simple and clean user interface.
|
|
||||||
It makes heavy use of the mouse, and no use of the keyboard.
|
|
||||||
It is click-to-type.
|
|
||||||
It uses the X11 font system (which, unfortunately, means no Unicode support).
|
|
||||||
|
|
||||||
9wm does not provide virtual desktops, customization, key bindings,
|
|
||||||
or compositing.
|
|
||||||
It does not allocate any colors,
|
|
||||||
and only requires Xlib,
|
|
||||||
both of which will be great news if you are in 1993.
|
|
||||||
|
|
||||||
9wm is distributed under [an MIT License](https://github.com/nealey/9wm/blob/master/LICENSE.md),
|
|
||||||
at <https://github.com/nealey/9wm>.
|
|
||||||
|
|
||||||
|
|
||||||
How do I use it?
|
|
||||||
================
|
|
||||||
|
|
||||||
![Screenshot](9wm.png)
|
|
||||||
|
|
||||||
The focused window has a black border.
|
|
||||||
Mouse and keyboard events go to this window.
|
|
||||||
Left click a non-focused window (white border) to focus it.
|
|
||||||
|
|
||||||
Right-click anywhere other than the focused window,
|
|
||||||
including in any non-focused window,
|
|
||||||
to bring up a menu.
|
|
||||||
All further actions are done with the right mouse button.
|
|
||||||
The menu has options for:
|
|
||||||
|
|
||||||
* New: launch a new xterm
|
|
||||||
* Reshape: select a window, draw new rectangle for its size
|
|
||||||
* Move: drag a window around
|
|
||||||
* Delete: kill (close) a window
|
|
||||||
* Hide: hide (iconify) a window
|
|
||||||
|
|
||||||
Beneath the first 5 items are a list of all hidden windows.
|
|
||||||
|
|
||||||
Middle-click anywhere other than the focused window
|
|
||||||
to run "mm mouse2".
|
|
||||||
It's up to you to write an "mm" program and put it in your path somewhere,
|
|
||||||
if you want to use this for something.
|
|
||||||
I have mine run "google-chrome-stable --show-app-list".
|
|
||||||
|
|
||||||
|
|
||||||
More Information
|
|
||||||
================
|
|
||||||
|
|
||||||
More information can be found in the
|
|
||||||
[README](https://github.com/nealey/9wm/blob/master/README.md).
|
|
|
@ -1,10 +0,0 @@
|
||||||
TARGETS += $(DESTDIR)/src/dwm/config.h $(DESTDIR)/src/dwm/status.sh
|
|
||||||
TARGETS += $(DESTDIR)/src/dwm/dwm-button.sh
|
|
||||||
|
|
||||||
$(DESTDIR)/src/dwm/config.h: $(HOME)/src/ports/dwm/config.h
|
|
||||||
@mkdir -p $(@D)
|
|
||||||
cp $< $@
|
|
||||||
|
|
||||||
$(DESTDIR)/src/dwm/%.sh: $(HOME)/bin/%
|
|
||||||
@mkdir -p $(@D)
|
|
||||||
cp $< $@
|
|
|
@ -1,26 +0,0 @@
|
||||||
Title: dwm hacks
|
|
||||||
|
|
||||||
I seem to have trouble keeping my attention on the task at hand if there
|
|
||||||
are little things flashing in the corner of the screen, or even changing
|
|
||||||
color (like, "you have new email"). The less I have on the screen, the
|
|
||||||
more productive I seem to be. It is for this reason that I've been
|
|
||||||
using "tiling" window managers since about 2003.
|
|
||||||
|
|
||||||
I've been using [dwm](http://dwm.suckless.org/) since a friend
|
|
||||||
introduced me to it around 2008. What I like most about dwm, aside from
|
|
||||||
helping me stay focused on the task at hand, is that it gets out of my
|
|
||||||
way. There are no buttons to click, and no windows to drag around or
|
|
||||||
resize. In fact, I hardly ever use the mouse anymore, outside of my web
|
|
||||||
browser.
|
|
||||||
|
|
||||||
* [My config.h](config.h) contains a few features I've added, like
|
|
||||||
restarting dwm, multimedia buttons, and
|
|
||||||
[xss](http://woozle.org/~neale/src/xss.html) integration (3 lines of
|
|
||||||
code).
|
|
||||||
* [My status program](http://woozle.org/~neale/g.cgi/status)
|
|
||||||
is responsible for having DWM show the
|
|
||||||
current time, load average, battery charge, and wifi status. It
|
|
||||||
gracefully handles machines that lack one or more of these features.
|
|
||||||
* [My button script](dwm-button.sh) is invoked when a multimedia button
|
|
||||||
is pressed, and handles screen brightness, volume, external monitors,
|
|
||||||
and more.
|
|
|
@ -1,140 +0,0 @@
|
||||||
#! /usr/bin/guile \
|
|
||||||
--debug -e eguile-main -s
|
|
||||||
!#
|
|
||||||
|
|
||||||
;; eguile -- embedded guile preprocessor
|
|
||||||
;; Copyright (C) 2002 Neale Pickett <neale@woozle.org>
|
|
||||||
;;
|
|
||||||
;; This program is free software; you can redistribute it and/or
|
|
||||||
;; modify it under the terms of the GNU General Public License as
|
|
||||||
;; published by the Free Software Foundation; either version 2 of the
|
|
||||||
;; License, or (at your option) any later version.
|
|
||||||
;;
|
|
||||||
;; This program is distributed in the hope that it will be useful,
|
|
||||||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
;; General Public License for more details.
|
|
||||||
;;
|
|
||||||
;; You should have received a copy of the GNU General Public License
|
|
||||||
;; along with this program; if not, write to the Free Software
|
|
||||||
;; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
|
||||||
;; 02111-1307 USA
|
|
||||||
|
|
||||||
|
|
||||||
(use-modules (ice-9 slib))
|
|
||||||
|
|
||||||
(require 'fluid-let)
|
|
||||||
(require 'string-search)
|
|
||||||
(require 'object->string)
|
|
||||||
|
|
||||||
;;
|
|
||||||
;; Backwards compatibility. Set this to:
|
|
||||||
;;
|
|
||||||
;; 'escm for escm compatibility
|
|
||||||
;; number for old eguile compatibility
|
|
||||||
;;
|
|
||||||
;; Anything else gets you no backwards compatibility -- you get to do
|
|
||||||
;; things the current way.
|
|
||||||
;;
|
|
||||||
(define eguile-compatibility 'current)
|
|
||||||
|
|
||||||
;; Retrieve a named parameter with optional default
|
|
||||||
(define (getparam args name . default)
|
|
||||||
(define (loop args)
|
|
||||||
(cond
|
|
||||||
((null? args)
|
|
||||||
(if (pair? default)
|
|
||||||
(car default)
|
|
||||||
#f))
|
|
||||||
((equal? (car args) name)
|
|
||||||
(cadr args))
|
|
||||||
(else
|
|
||||||
(loop (cddr args)))))
|
|
||||||
(loop args))
|
|
||||||
|
|
||||||
|
|
||||||
(define lmatch '())
|
|
||||||
(define rmatch '())
|
|
||||||
|
|
||||||
;;
|
|
||||||
;; New^3 improved parser! Woo woo woo!
|
|
||||||
;;
|
|
||||||
(define (stml->commands inp)
|
|
||||||
(define (loop inp needle other buf)
|
|
||||||
;; Read in a line, looking for needle. If it's there, switch needle
|
|
||||||
;; and other, and outbuf buf + line
|
|
||||||
(let ((line (read-line inp 'concat)))
|
|
||||||
(cond
|
|
||||||
((eof-object? line) (cons buf '("")))
|
|
||||||
(else
|
|
||||||
(let ((pos (substring? needle line)))
|
|
||||||
(cond
|
|
||||||
(pos
|
|
||||||
(unread-string (substring line
|
|
||||||
(+ (string-length needle)
|
|
||||||
pos))
|
|
||||||
inp)
|
|
||||||
(cons (string-append buf (substring line 0 pos))
|
|
||||||
(loop inp other needle "")))
|
|
||||||
(else
|
|
||||||
(loop inp needle other (string-append buf line))))))))) ; Ha ha, scheme
|
|
||||||
|
|
||||||
(define (list->commands list)
|
|
||||||
;; Convert the output of (loop) to something that can be evaled.
|
|
||||||
(cond
|
|
||||||
((null? list) "")
|
|
||||||
((null? (cdr list))
|
|
||||||
(string-append "Unbalanced preprocessor directives: "
|
|
||||||
(object->string list)))
|
|
||||||
(else
|
|
||||||
(let ((str (object->string (car list)))
|
|
||||||
(expr (cadr list))
|
|
||||||
(rest (list->commands (cddr list))))
|
|
||||||
(string-append " (display "
|
|
||||||
(object->string (car list))
|
|
||||||
") "
|
|
||||||
(cond
|
|
||||||
((equal? (substring? ":d " expr) 0)
|
|
||||||
(string-append "(display "
|
|
||||||
(substring expr 3)
|
|
||||||
")"))
|
|
||||||
(else
|
|
||||||
expr))
|
|
||||||
rest)))))
|
|
||||||
|
|
||||||
(list->commands
|
|
||||||
(loop inp "<?scm" " ?>" "")))
|
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
||||||
|
|
||||||
(define *program-name* #f) ; Dynamically bound
|
|
||||||
(define *input-file* #f) ; Dynamically bound
|
|
||||||
(define *output-file* #f) ; Dynamically bound
|
|
||||||
|
|
||||||
(define (eguile-port inp)
|
|
||||||
(let ((commands (stml->commands inp)))
|
|
||||||
(eval-string commands)))
|
|
||||||
|
|
||||||
(define (eguile-file input)
|
|
||||||
(fluid-let ((*input-file* input))
|
|
||||||
(eguile-port (open-input-file input))))
|
|
||||||
|
|
||||||
(define (eguile input output)
|
|
||||||
(fluid-let ((*output-file* output))
|
|
||||||
(let ((out-port (open-output-file output))
|
|
||||||
(*stdout* (current-output-port)))
|
|
||||||
(set-current-output-port out-port)
|
|
||||||
(eguile-file input)
|
|
||||||
(set-current-output-port *stdout*))))
|
|
||||||
|
|
||||||
(define (eguile-main argv)
|
|
||||||
;; Make sure we have the correct number of arguments
|
|
||||||
(if (not (= (length argv) 3))
|
|
||||||
(begin
|
|
||||||
(display (string-append "Usage: " (car argv) " infile outfile"))
|
|
||||||
(newline)
|
|
||||||
(exit)))
|
|
||||||
|
|
||||||
(fluid-let ((*program-name* (car argv)))
|
|
||||||
;; Do it to it
|
|
||||||
(eguile (cadr argv) (caddr argv))))
|
|
|
@ -1,62 +0,0 @@
|
||||||
Title: Eguile : a scheme preprocessor
|
|
||||||
Author: Neale Pickett <neale@woozle.org>
|
|
||||||
|
|
||||||
If you've ever wished your text preprocessor could do symbolic
|
|
||||||
derivation, eguile is the tool for you!
|
|
||||||
|
|
||||||
eguile is a preprocessor which lets you include Scheme code in your
|
|
||||||
source files--any source files, not just HTML. With the bundled
|
|
||||||
ntp-style.scm, you can give web pages a consistent interface with easy
|
|
||||||
navigation bars, just like this page. Further functionality is limited
|
|
||||||
only by your imagination and programming ability.
|
|
||||||
|
|
||||||
eguile looks like PHP, but with Scheme instead of Perl. If you're the
|
|
||||||
sort of person that would enjoy something like this, you probably don't
|
|
||||||
need any further description.
|
|
||||||
|
|
||||||
|
|
||||||
Downloading it
|
|
||||||
--------------------------
|
|
||||||
|
|
||||||
[eguile.scm](http://woozle.org/~neale/src/eguile/eguile.scm).
|
|
||||||
|
|
||||||
|
|
||||||
Reference
|
|
||||||
--------------------------
|
|
||||||
|
|
||||||
Easy squeezy:
|
|
||||||
|
|
||||||
<dl>
|
|
||||||
<dt><?scm scheme-code ?></dt>
|
|
||||||
<dd>Evaluates scheme-code, discarding value of the last expression</dd>
|
|
||||||
|
|
||||||
<dt><?scm:d scheme-code ?></dt>
|
|
||||||
<dd>Evaluates scheme-code, displaying the value of the last expression</dd>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
For example:
|
|
||||||
|
|
||||||
<?scm (define (square x) (* x x)) ?>
|
|
||||||
2 squared is <?scm:d (square 2) ?>
|
|
||||||
|
|
||||||
renders as:
|
|
||||||
|
|
||||||
2 squared is 4
|
|
||||||
|
|
||||||
|
|
||||||
Inspiration
|
|
||||||
--------------------------
|
|
||||||
|
|
||||||
I modeled eguile after ht2html by Barry Warsaw (a far cooler cat than
|
|
||||||
I). ht2html is a slick package, but it didn't feel enough like
|
|
||||||
programming to me and seemed more complicated than it needed to be. escm
|
|
||||||
seemed like a better solution, but felt a little too kludgy, and I
|
|
||||||
needed to learn Scheme better anyway. So I stole the layout from ht2html
|
|
||||||
and the syntax from escm.
|
|
||||||
|
|
||||||
|
|
||||||
License
|
|
||||||
--------------------------
|
|
||||||
|
|
||||||
eguile is distributed under the GNU Public License version 2.0 or
|
|
||||||
later. Please refer to the file COPYING for more information.
|
|
10
src/eris.md
|
@ -1,10 +0,0 @@
|
||||||
Title: Eris HTTPd
|
|
||||||
|
|
||||||
Eris HTTPd is a small web server to be run from inetd or tcpserver
|
|
||||||
(tcpsvd in busybox). It is based on
|
|
||||||
[fnord HTTPd](http://www.fefe.de/fnord/) but shares very little
|
|
||||||
code in common now.
|
|
||||||
|
|
||||||
* [Eris Versions](/neale/g.cgi/net/eris/)
|
|
||||||
* [README](/neale/g.cgi/net/eris/about/)
|
|
||||||
|
|
54
src/escm.md
|
@ -1,54 +0,0 @@
|
||||||
Title: escm: a scheme preprocessor
|
|
||||||
|
|
||||||
This is my port of [eguile](http://woozle.org/~neale/src/eguile) to
|
|
||||||
gauche scheme. It uses regular expressions and as a result is faster
|
|
||||||
and easier to read. It's so tiny, in fact, that I don't feel compelled
|
|
||||||
to write much about it.
|
|
||||||
|
|
||||||
eguile looks like PHP, but with Scheme instead of Perl. If you're the
|
|
||||||
sort of person that would enjoy something like this, you probably don't
|
|
||||||
need any further description.
|
|
||||||
|
|
||||||
I use eguile along with a couple handy procedures and some makefiles to
|
|
||||||
generate my entire web space, and a few non-profit web sites I maintain.
|
|
||||||
I'd be happy to share the site-building stuff with anybody who asks, but
|
|
||||||
I'm not going to package it up until someone's interested.
|
|
||||||
|
|
||||||
|
|
||||||
Downloading it
|
|
||||||
--------------
|
|
||||||
|
|
||||||
You can download a [tarball of the latest version in git](http://woozle.org/~neale/g.cgi/escm/snapshot/escm-master.tar.gz), or check it out yourself:
|
|
||||||
|
|
||||||
git clone http://woozle.org/~neale/repos/escm
|
|
||||||
|
|
||||||
|
|
||||||
Reference
|
|
||||||
---------
|
|
||||||
|
|
||||||
Easy squeezy:
|
|
||||||
|
|
||||||
<dl>
|
|
||||||
<dt><?scm scheme-code ?></dt>
|
|
||||||
<dd>Evaluates scheme-code, discarding value of the last expression</dd>
|
|
||||||
|
|
||||||
<dt><?scm:d scheme-code ?></dt>
|
|
||||||
<dd>Evaluates scheme-code, displaying the value of the last expression</dd>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
For example:
|
|
||||||
|
|
||||||
<?scm (define (square x) (* x x)) ?>
|
|
||||||
2 squared is <?scm:d (square 2) ?>
|
|
||||||
|
|
||||||
renders as:
|
|
||||||
|
|
||||||
2 squared is 4
|
|
||||||
|
|
||||||
|
|
||||||
Related stuff
|
|
||||||
------------------------
|
|
||||||
|
|
||||||
* [escm 1.1](http://practical-scheme.net/vault/escm.html) by Shiro
|
|
||||||
Kawai, author of gauche, was my inspiration.
|
|
||||||
* [eguile](http://woozle.org/~neale/src/eguile) is Guile-only
|
|
167
src/firebot.md
|
@ -1,167 +0,0 @@
|
||||||
Title: Firebot: IRC Automaton
|
|
||||||
|
|
||||||
FireBot is a winner!
|
|
||||||
|
|
||||||
Firebot is an IRC bot combining the functionality of a Linkbot, an
|
|
||||||
Infobot, and a Clickolinko, which is this cool thing Emad El-Haraty and
|
|
||||||
I came up with to make short URLs out of stuff posted into the channel,
|
|
||||||
for people with text browsers that wrap URLs.
|
|
||||||
|
|
||||||
Note that, in addition to interacting with FireBot within a channel, you
|
|
||||||
can also communicate directly with FireBot via `/msg` commands. Just in
|
|
||||||
case you need a little one-on-one action and don't want spew your
|
|
||||||
playtime around some channel with other folks watching. That can be *so*
|
|
||||||
distracting. Some commands still require you to preface them with
|
|
||||||
FireBot's name. Example:
|
|
||||||
|
|
||||||
/msg firebot firebot: literal ...
|
|
||||||
|
|
||||||
|
|
||||||
Downloading
|
|
||||||
-----------
|
|
||||||
|
|
||||||
You can download a [tarball snapshot of the latest release](http://woozle.org/~neale/g.cgi/firebot/snapshot/firebot-master.tar.gz), or use cogito:
|
|
||||||
|
|
||||||
git clone http://woozle.org/~neale/projects/firebot
|
|
||||||
|
|
||||||
|
|
||||||
LinkBot Features
|
|
||||||
----------------
|
|
||||||
|
|
||||||
Firebot can link channels across networks. It is present in all
|
|
||||||
channels and the same functions can be accessed on either side.
|
|
||||||
Everything said on one channel is relayed to the others.
|
|
||||||
|
|
||||||
It is possible to link multiple channels on multiple servers, including
|
|
||||||
multiple channels on a single server.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
ClickLinko (UrlBot)
|
|
||||||
-------------------
|
|
||||||
|
|
||||||
Whenever FireBot sees a URL in the channel, he makes a note of it and
|
|
||||||
creates a shorter URL out of it.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
InfoBot
|
|
||||||
-------
|
|
||||||
|
|
||||||
As an InfoBot, FireBot listens in the channel for anything of the form
|
|
||||||
"x is y", and then stores that little tidbit. Later, when someone asks
|
|
||||||
a question about x ("what is x?", "who is x?", "wtf is x?"), FireBot
|
|
||||||
answers with the factoid he gathered.
|
|
||||||
|
|
||||||
<dl>
|
|
||||||
<dt>firebot, **x**</dt>
|
|
||||||
<dd>look up a factoid for **x**</dd>
|
|
||||||
|
|
||||||
<dt>firebot, **x** is **y**</dt>
|
|
||||||
<dd>store **y** as a factiod about **x**</dd>
|
|
||||||
|
|
||||||
<dt>firebot, **x** is also **y**</dt>
|
|
||||||
<dd>store **y** as another factoid about **x**</dd>
|
|
||||||
|
|
||||||
<dt>firebot, append **x** <= **y**</dt>
|
|
||||||
<dd>store **y** as another factoid about **x**. You'd use this for things where **x** has the word "is" in it, or other things that you can't store with the preceding commands.</dd>
|
|
||||||
|
|
||||||
<dt>no, firebot, **x** is **y**</dt>
|
|
||||||
<dd>store **y** as the only factoid about **x**, even if **x** already has factoids</dd>
|
|
||||||
|
|
||||||
<dt>firebot, literal **x**</dt>
|
|
||||||
<dd>display all factoids about **x**</dd>
|
|
||||||
|
|
||||||
<dt>firebot, lock **x**</dt>
|
|
||||||
<dd>do not learn any more factoids about **x**</dd>
|
|
||||||
|
|
||||||
<dt>firebot, unlock **x**</dt>
|
|
||||||
<dd>resume learning factoids about **x**</dd>
|
|
||||||
|
|
||||||
<dt>firebot, forget **x**</dt>
|
|
||||||
<dd>forget all factoids about **x**</dd>
|
|
||||||
|
|
||||||
<dt>firebot, forget **x** from **y**</dt>
|
|
||||||
<dd>forget a single entry (**x**) that is listed in **y**; **x** can be a single word, it does not need to be the whole entry</dd>
|
|
||||||
|
|
||||||
<dt>firebot, shut up</td>
|
|
||||||
<dd>make the bot only respond to factoids when addressed specifically</dd>
|
|
||||||
|
|
||||||
<dt>firebot, be chatty</td>
|
|
||||||
<dd>make the bot respond to factoids even when not addressed</dd>
|
|
||||||
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
In addition, the following tricks can be used within factiods:
|
|
||||||
|
|
||||||
* Any factoid beginning with `\\` (a backslash) is displayed directly.
|
|
||||||
That is, instead of saying "<firebot> x is y", FireBot just says
|
|
||||||
"<firebot> y".
|
|
||||||
* Any factoid beginning with <code>:</code> (a colon) is
|
|
||||||
displayed an action. That is, instead of saying "<firebot> x is y",
|
|
||||||
FireBot says "* firebot y"
|
|
||||||
* You may put `%(sender)s` in the factoid to print the name of the
|
|
||||||
person who asked about the factoid (when sent to a user in a private
|
|
||||||
message, it's the recipient of the message)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Utilities
|
|
||||||
---------
|
|
||||||
|
|
||||||
<dl>
|
|
||||||
|
|
||||||
<dt>firebot, later tell **whom** **what**</dt>
|
|
||||||
<dd>The next time **whom** says something in the channel, deliver the message **what** publically.</dd>
|
|
||||||
|
|
||||||
<dt>firebot, in **time** say **what**</dt>
|
|
||||||
<dd>after **time** (eg. "15 seconds", "2 hours", "5 days"), announce **what** in the channel</dd>
|
|
||||||
|
|
||||||
<dt>seen **whom**</dt>
|
|
||||||
<dd>Report the last thing said in the channel by **whom**, and how long ago it was said.</dd>
|
|
||||||
|
|
||||||
<dt>dict **word**</dt>
|
|
||||||
<dd>look **word** up in the dictionary</dd>
|
|
||||||
|
|
||||||
<dt>quote **symbol**</dt>
|
|
||||||
<dd>get a stock quote for **symbol**</dd>
|
|
||||||
|
|
||||||
<dt>pollen **zip**</dt>
|
|
||||||
<dd>report pollen forecast for US zip code **zip**</dd>
|
|
||||||
|
|
||||||
<dt>cdecl explain **jibberish**</dt>
|
|
||||||
<dd>explain the C declaration **jibberish** (eg. "cdecl explain struct bar *(*foo)[](int)")</dd>
|
|
||||||
|
|
||||||
<dt>cdecl declare **english**</dt>
|
|
||||||
<dd>give the C declaration for **english** (eg. "cdecl declare foo as pointer to array of function (int) returning pointer to struct bar")</dd>
|
|
||||||
|
|
||||||
<dt>how many **x** in **y** **z**</dt>
|
|
||||||
<dd>determine the number of **x** items that are contained in **y** amount of **z** items (eg. how many miles in 1 light year)</dd>
|
|
||||||
|
|
||||||
<dt>how much is **amt** **source** in **dest**</dt>
|
|
||||||
<dd>do a currency conversion from **source** to **dest**. Both must be three-letter currency codes. (eg. "how much is 100 USD in EUR")</dd>
|
|
||||||
|
|
||||||
<dt>calc **expr**</dt>
|
|
||||||
<dd>calculate **expr** (eg. "calc 2 * 5")</dd>
|
|
||||||
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
|
|
||||||
Toys
|
|
||||||
----
|
|
||||||
|
|
||||||
<dl>
|
|
||||||
|
|
||||||
<dt>8ball, **question**</dt>
|
|
||||||
<dd>consult the magic 8-ball regarding **question**</dd>
|
|
||||||
|
|
||||||
<dt>**nickname**++</dt>
|
|
||||||
<dd>add a whuffie point for **nickname**</dd>
|
|
||||||
|
|
||||||
<dt>**nickname**--</dt>
|
|
||||||
<dd>remove a whuffie point for **nickname**</dd>
|
|
||||||
|
|
||||||
<dt>whuffie for **nickname**</dt>
|
|
||||||
<dd>check the whuffie for **nickname**</dd>
|
|
||||||
|
|
||||||
</dl>
|
|
32
src/index.md
|
@ -1,32 +0,0 @@
|
||||||
Title: Software
|
|
||||||
|
|
||||||
I write software for a living. I like doing it so much that sometimes I
|
|
||||||
even write software just for fun.
|
|
||||||
|
|
||||||
|
|
||||||
Current Work
|
|
||||||
------------
|
|
||||||
|
|
||||||
* [Runit-Init](/neale/g.cgi/aur/runit-init/about/), an /sbin/init replacement based on busybox
|
|
||||||
* [Eris HTTPd](/neale/g.cgi/net/eris/about/), a small HTTP (web) server
|
|
||||||
* [9wm](9wm/), an emulation of the Plan 9 window manager
|
|
||||||
* [xss](/neale/g.cgi/x11/xss/about/), a suite of X screensaver programs
|
|
||||||
|
|
||||||
|
|
||||||
Not-So-Current Work
|
|
||||||
-------------------
|
|
||||||
|
|
||||||
* [Python IPQueue](ipqueue/), python bindings to Linux libipqueue. It was mentioned in a book and Google Scholar says it's been cited two other times, which makes me *Internet Famous* 😎.
|
|
||||||
* [eguile](eguile/), like PHP but with Scheme instead. A fork of this is used in gnucash.
|
|
||||||
* [Woozle Scoreboard](http://woozle.org/scoreboard/), a browser-based roller derby scorebard
|
|
||||||
* [Hardware Scoreboard](/neale/g.cgi/derby/hw-scoreboard/about/), a microcontroller-based LED roller derby scoreboard
|
|
||||||
* [Penalty Timer](https://play.google.com/store/apps/details?id=org.woozle.penaltytimer), a roller derby penalty timer for Android
|
|
||||||
* [Hercules DJ Controller Driver](/neale/g.cgi/hdjd/about/)
|
|
||||||
|
|
||||||
|
|
||||||
Even More
|
|
||||||
---------
|
|
||||||
|
|
||||||
* [All projects on woozle](/neale/g.cgi/)
|
|
||||||
* [Github Account](https://github.com/nealey)
|
|
||||||
* [Gitorious Account](https://gitorious.org/~neale)
|
|
|
@ -1,84 +0,0 @@
|
||||||
Title: Python ipqueue
|
|
||||||
|
|
||||||
No Longer Maintained
|
|
||||||
--------------------
|
|
||||||
|
|
||||||
This software is no longer maintained.
|
|
||||||
|
|
||||||
ipqueue has been deprecated in favor of nfqueue. You can download a [Python
|
|
||||||
nfqueue module](http://software.inl.fr/trac/wiki/nfqueue-bindings) which should
|
|
||||||
support all the functionality of ipqueue. In Debian or Ubuntu, you can just
|
|
||||||
|
|
||||||
# apt-get install libnetfilter-queue-python
|
|
||||||
|
|
||||||
This page remains here for those who know what they're doing and are
|
|
||||||
still using the old libipq. This software will not compile with the
|
|
||||||
backwards-compatibility library provided by nfqueue.
|
|
||||||
|
|
||||||
About
|
|
||||||
-----
|
|
||||||
|
|
||||||
This is the Netfilter userspace IPQueue module for Python. It allows you
|
|
||||||
to do all your Linux IPQueue stuff from the comfort of Python. This only
|
|
||||||
works with Linux.
|
|
||||||
|
|
||||||
Put in simpler terms, this is a way to hook a Python script into your
|
|
||||||
kernel's networking stack. This could be the fundamental building block
|
|
||||||
of a firewall. You can use it to snoop on traffic, modify or discard
|
|
||||||
certain packets, make routing decisions, masquerade stuff, whatever--and
|
|
||||||
you get it all with garbage collection :)
|
|
||||||
|
|
||||||
Apparently this program appears in a book called "Security Power Tools".
|
|
||||||
That means I'm *Internet Famous*!
|
|
||||||
|
|
||||||
Download
|
|
||||||
--------
|
|
||||||
|
|
||||||
This software is no longer maintained (see above).
|
|
||||||
|
|
||||||
* [Latest version](/neale/g.cgi/attic/py-ipqueue/snapshot/py-ipqueue-master.tar.gz)
|
|
||||||
* [Git repository](/neale/g.cgi/attic/py-ipqueue/)
|
|
||||||
* [Netfilter QUEUE bindings](nfqueue-0.1.tar.bz2) by Mike Auty <mike.auty@gmail.com>
|
|
||||||
* [nfqueue bindings](http://software.inl.fr/trac/wiki/nfqueue-bindings)
|
|
||||||
|
|
||||||
License
|
|
||||||
-------
|
|
||||||
|
|
||||||
GPL, of course.
|
|
||||||
|
|
||||||
Support
|
|
||||||
-------
|
|
||||||
|
|
||||||
This software is no longer maintained (see above). Support requests
|
|
||||||
will be politely redirected to the newer [nfqueue
|
|
||||||
bindings](http://software.inl.fr/trac/wiki/nfqueue-bindings).
|
|
||||||
|
|
||||||
|
|
||||||
Screen Shots
|
|
||||||
------------
|
|
||||||
|
|
||||||
Here's an example program which transparently proxies all traffic it
|
|
||||||
gets to port 25 of 10.1.1.2. This is just an example, a real-world
|
|
||||||
transparent proxy would be much more sophisticated.
|
|
||||||
|
|
||||||
#! /usr/bin/env python
|
|
||||||
|
|
||||||
import ipqueue
|
|
||||||
import iputils
|
|
||||||
|
|
||||||
rewrite = 1
|
|
||||||
|
|
||||||
q = ipqueue.IPQ(ipqueue.IPQ_COPY_PACKET)
|
|
||||||
while 1:
|
|
||||||
p = q.read()
|
|
||||||
tcp = iputils.TCP(p[ipqueue.PAYLOAD])
|
|
||||||
print "Got %s -> %s on hook %d" % (iputils.ntoa(tcp.saddr),
|
|
||||||
iputils.ntoa(tcp.daddr),
|
|
||||||
p[ipqueue.HOOK])
|
|
||||||
|
|
||||||
if rewrite and p[ipqueue.HOOK] == 0:
|
|
||||||
tcp.daddr = iputils.aton("10.1.1.2")
|
|
||||||
tcp.th_dport = 25
|
|
||||||
q.set_verdict(p[0], ipqueue.NF_ACCEPT, tcp.to_str())
|
|
||||||
else:
|
|
||||||
q.set_verdict(p[0], ipqueue.NF_ACCEPT)
|
|
264
src/misc/9p.scm
|
@ -1,264 +0,0 @@
|
||||||
#! /usr/bin/gosh
|
|
||||||
|
|
||||||
;; Description: 9p implementation in Scheme
|
|
||||||
;; Author: Neale Pickett <neale@woozle.org>
|
|
||||||
|
|
||||||
;; This uses gauche's networking stuff, but no other gauche stuff. It
|
|
||||||
;; should be possible to substitute your implementation's networking
|
|
||||||
;; procedures without too much effort.
|
|
||||||
(use gauche.net)
|
|
||||||
(require-extension (srfi 1 4 8 9))
|
|
||||||
|
|
||||||
(define message-specs
|
|
||||||
;; name num format
|
|
||||||
'((TVersion 100 (2 4 s)) ;x64
|
|
||||||
(RVersion 101 (2 4 s))
|
|
||||||
(TAuth 102 (2 4 s s))
|
|
||||||
(RAuth 103 (2 13))
|
|
||||||
(TAttach 104 (2 4 4 s s)) ;x68
|
|
||||||
(RAttach 105 (2 13))
|
|
||||||
(TError 106 ()) ;illegal
|
|
||||||
(RError 107 (2 s))
|
|
||||||
(TFlush 108 (2 2)) ;x6c
|
|
||||||
(RFlush 109 (2))
|
|
||||||
(TWalk 110 (2 4 4 (2 . s)))
|
|
||||||
(RWalk 111 (2 (2 . 13)))
|
|
||||||
(TOpen 112 (2 4 1)) ;x70
|
|
||||||
(ROpen 113 (2 13 4))
|
|
||||||
(TCreate 114 (2 4 s 4 1))
|
|
||||||
(RCreate 115 (2 13 4))
|
|
||||||
(TRead 116 (2 4 8 4)) ;x74
|
|
||||||
(RRead 117 (2 (4 . d)))
|
|
||||||
(TWrite 118 (2 4 8 (4 . s)))
|
|
||||||
(RRwrite 119 (2 4))
|
|
||||||
(TClunk 120 (2 4)) ;x78
|
|
||||||
(RClunk 121 (2))
|
|
||||||
(TRemove 122 (2 4))
|
|
||||||
(RRemove 123 (2))
|
|
||||||
(TStat 124 (2 4)) ;x7c
|
|
||||||
(RStat 125 (2 n))
|
|
||||||
(TWStat 126 (2 4 n))
|
|
||||||
(RWStat 127 (2)))) ;x7f
|
|
||||||
|
|
||||||
(define (spec-by-num num)
|
|
||||||
(let loop ((specs message-specs))
|
|
||||||
(cond
|
|
||||||
((null? specs)
|
|
||||||
#f)
|
|
||||||
((equal? (cadar specs) num)
|
|
||||||
(car specs))
|
|
||||||
(else
|
|
||||||
(loop (cdr specs))))))
|
|
||||||
|
|
||||||
|
|
||||||
;;
|
|
||||||
;; Helper procedures
|
|
||||||
;;
|
|
||||||
|
|
||||||
(define (u8-list->uint l)
|
|
||||||
(let loop ((l (reverse l))
|
|
||||||
(acc 0))
|
|
||||||
(if (null? l)
|
|
||||||
acc
|
|
||||||
(loop (cdr l)
|
|
||||||
(+ (* 256 acc)
|
|
||||||
(car l))))))
|
|
||||||
|
|
||||||
(define (uint->u8-list width i)
|
|
||||||
(if (zero? width)
|
|
||||||
'()
|
|
||||||
(let ((b (modulo i 256))
|
|
||||||
(r (floor (/ i 256))))
|
|
||||||
(cons b (uint->u8-list (- width 1) r)))))
|
|
||||||
|
|
||||||
;; XXX: s had better be printable 7-bit ASCII
|
|
||||||
(define (string->u8-list s)
|
|
||||||
(map char->integer (string->list s)))
|
|
||||||
|
|
||||||
(define (u8-list->string l)
|
|
||||||
(list->string (map integer->char l)))
|
|
||||||
|
|
||||||
|
|
||||||
;;
|
|
||||||
;; Packing and unpacking, both deal with u8-lists
|
|
||||||
;;
|
|
||||||
|
|
||||||
(define (pack fmt args)
|
|
||||||
(let loop ((fmt fmt)
|
|
||||||
(args args)
|
|
||||||
(acc '()))
|
|
||||||
;;(write (list fmt args acc)) (newline)
|
|
||||||
(cond
|
|
||||||
((null? fmt)
|
|
||||||
acc)
|
|
||||||
((number? (car fmt))
|
|
||||||
(loop (cdr fmt)
|
|
||||||
(cdr args)
|
|
||||||
(append acc (uint->u8-list (car fmt) (car args)))))
|
|
||||||
((equal? (car fmt) 's)
|
|
||||||
;;XXX Should handle UTF-8
|
|
||||||
(loop (cdr fmt)
|
|
||||||
(cdr args)
|
|
||||||
(append acc
|
|
||||||
(uint->u8-list 2 (string-length (car args)))
|
|
||||||
(string->u8-list (car args)))))
|
|
||||||
((pair? (car fmt))
|
|
||||||
;; fmt item is (c . type), which gets packed to a c-octet n,
|
|
||||||
;; followed by n types.
|
|
||||||
(let ((count (length (car args))))
|
|
||||||
(loop (cdr fmt)
|
|
||||||
(cdr args)
|
|
||||||
(append acc
|
|
||||||
(uint->u8-list (caar fmt) count)
|
|
||||||
(pack (make-list count (cdar fmt))
|
|
||||||
(car args))))))
|
|
||||||
((equal? (car fmt) 'n)
|
|
||||||
;; XXX: total guess here
|
|
||||||
(loop (cdr fmt)
|
|
||||||
(cdr args)
|
|
||||||
(append acc (car args))))
|
|
||||||
(else
|
|
||||||
(error (format "Unknown format element: ~a" (car fmt)))))))
|
|
||||||
|
|
||||||
(define (unpack fmt l)
|
|
||||||
(reverse
|
|
||||||
(let loop ((fmt fmt)
|
|
||||||
(l l)
|
|
||||||
(acc '()))
|
|
||||||
;;(write (list fmt l acc)) (newline)
|
|
||||||
(cond
|
|
||||||
((null? fmt)
|
|
||||||
acc)
|
|
||||||
((number? (car fmt))
|
|
||||||
(loop (cdr fmt)
|
|
||||||
(drop l (car fmt))
|
|
||||||
(cons (u8-list->uint (take l (car fmt)))
|
|
||||||
acc)))
|
|
||||||
((equal? (car fmt) 's)
|
|
||||||
(let ((len (u8-list->uint (take l 2)))
|
|
||||||
(m (drop l 2)))
|
|
||||||
(loop (cdr fmt)
|
|
||||||
(drop m len)
|
|
||||||
(cons (u8-list->string (take m len))
|
|
||||||
acc))))
|
|
||||||
((pair? (car fmt))
|
|
||||||
(let* ((count (u8-list->uint (take l (caar fmt))))
|
|
||||||
(m (drop l (caar fmt))))
|
|
||||||
(receive (p octets)
|
|
||||||
(case (cdar fmt)
|
|
||||||
((s)
|
|
||||||
(let ((p (reverse (unpack (make-list count (cdar fmt))
|
|
||||||
l))))
|
|
||||||
(values p
|
|
||||||
(reduce + 0 (map string-length p)))))
|
|
||||||
((d)
|
|
||||||
(values (take m count)
|
|
||||||
count))
|
|
||||||
(else
|
|
||||||
(values (reverse (unpack (make-list count (cdar fmt))
|
|
||||||
l))
|
|
||||||
(* count (cdar fmt)))))
|
|
||||||
(loop (cdr fmt)
|
|
||||||
(drop m octets)
|
|
||||||
(cons p acc)))))
|
|
||||||
|
|
||||||
(else
|
|
||||||
(error (format "Unknown format element: ~a" (car fmt))))))))
|
|
||||||
|
|
||||||
|
|
||||||
;;
|
|
||||||
;; Packet assembly and disassembly
|
|
||||||
;;
|
|
||||||
|
|
||||||
(define (make-packet type . args)
|
|
||||||
(let* ((spec (cdr (assoc type message-specs)))
|
|
||||||
(msgnum (car spec))
|
|
||||||
(fmt (cadr spec))
|
|
||||||
(p (pack fmt args)))
|
|
||||||
(append (uint->u8-list 4 (+ 5 (length p)))
|
|
||||||
(list msgnum)
|
|
||||||
p)))
|
|
||||||
|
|
||||||
(define (write-packet ixp type . args)
|
|
||||||
((ixp-write ixp) (apply make-packet (cons type args))))
|
|
||||||
|
|
||||||
(define (read-uint width ixp)
|
|
||||||
(u8-list->uint ((ixp-read ixp) width)))
|
|
||||||
|
|
||||||
(define (read-packet ixp)
|
|
||||||
(let* ((len (read-uint 4 ixp))
|
|
||||||
(msgnum (read-uint 1 ixp))
|
|
||||||
(spec (spec-by-num msgnum))
|
|
||||||
(fmt (caddr spec))
|
|
||||||
(datum ((ixp-read ixp) (- len 5))))
|
|
||||||
(cons (car spec)
|
|
||||||
(unpack fmt datum))))
|
|
||||||
|
|
||||||
|
|
||||||
;;
|
|
||||||
;; 9p record
|
|
||||||
;;
|
|
||||||
;; This is how I deal with the fact that no two scheme implementations
|
|
||||||
;; have the same socket API. There are no SRFIs for sockets so that's
|
|
||||||
;; not likely to change in the near future.
|
|
||||||
;;
|
|
||||||
;; You create one of these with (make-ixp read-u8-list write-u8-list).
|
|
||||||
;; read-u8-list should one argument, count, and return a list of length
|
|
||||||
;; count of octets (u8s) read from the socket. write-u8-list takes one
|
|
||||||
;; argument, l (a u8-list), and writes that to the socket.
|
|
||||||
;;
|
|
||||||
(define-record-type ixp
|
|
||||||
(make-ixp read-u8-list write-u8-list)
|
|
||||||
ixp?
|
|
||||||
(read-u8-list ixp-read)
|
|
||||||
(write-u8-list ixp-write))
|
|
||||||
|
|
||||||
|
|
||||||
(define (ixp-transaction ixp type . args)
|
|
||||||
(apply write-packet (append (list ixp type 1) args))
|
|
||||||
(let ((ret (read-packet ixp)))
|
|
||||||
(if (equal? (car ret) 'RError)
|
|
||||||
(error (format "IXP Recieve: ~a" ret))
|
|
||||||
ret)))
|
|
||||||
|
|
||||||
;; Rewriting this procedure should be all you need to do in order to
|
|
||||||
;; port this code.
|
|
||||||
(define (gauche-with-ixp socket proc)
|
|
||||||
(call-with-client-socket socket
|
|
||||||
(lambda (in out)
|
|
||||||
(let ((ixp (make-ixp
|
|
||||||
(lambda (count)
|
|
||||||
(let ((vec (make-u8vector count)))
|
|
||||||
(if (not (equal? (read-block! vec in) count))
|
|
||||||
(error "read-octets: short read")
|
|
||||||
(u8vector->list vec))))
|
|
||||||
(lambda (u8-list)
|
|
||||||
(write-block (list->u8vector u8-list) out)
|
|
||||||
(flush out)))))
|
|
||||||
(proc ixp)))))
|
|
||||||
|
|
||||||
|
|
||||||
(define (main args)
|
|
||||||
(gauche-with-ixp (make-client-socket 'unix "/tmp/ns.neale.:0/wmii")
|
|
||||||
(lambda (ixp)
|
|
||||||
(let ((root-fid #xf00fb1ba)
|
|
||||||
(fid 1)
|
|
||||||
(username "the dink")
|
|
||||||
(filename "event")
|
|
||||||
(data "hello\n"))
|
|
||||||
(ixp-transaction ixp 'TVersion 4096 "9P2000")
|
|
||||||
(ixp-transaction ixp 'TAttach root-fid #xffffffff username "")
|
|
||||||
|
|
||||||
(ixp-transaction ixp 'TWalk root-fid fid (list filename))
|
|
||||||
(ixp-transaction ixp 'TOpen fid 1)
|
|
||||||
(ixp-transaction ixp 'TWrite fid 0 (list data))
|
|
||||||
(ixp-transaction ixp 'TClunk fid)
|
|
||||||
|
|
||||||
(ixp-transaction ixp 'TWalk root-fid fid (list filename))
|
|
||||||
(ixp-transaction ixp 'TOpen fid 0)
|
|
||||||
(write
|
|
||||||
(let ((cl (caddr (ixp-transaction ixp 'TRead fid 0 4096))))
|
|
||||||
(ixp-transaction ixp 'TClunk fid)
|
|
||||||
(u8-list->string cl)))
|
|
||||||
(newline))))
|
|
||||||
0)
|
|
|
@ -1,38 +0,0 @@
|
||||||
#! /bin/sh -x
|
|
||||||
|
|
||||||
JUNK=$HOME/Maildir/.Junk
|
|
||||||
|
|
||||||
deliver () {
|
|
||||||
fn=`date +%s`.$$.`hostname`
|
|
||||||
mv $1 $2/tmp/$fn
|
|
||||||
mv $2/tmp/$fn $2/new/
|
|
||||||
chmod 600 $2/new/$fn
|
|
||||||
}
|
|
||||||
|
|
||||||
if [ -d $JUNK ]; then
|
|
||||||
tmp=`tempfile`
|
|
||||||
trap "rm -f $tmp" 0
|
|
||||||
|
|
||||||
bogofilter -p -u > $tmp
|
|
||||||
case $? in
|
|
||||||
0) # spam
|
|
||||||
deliver $tmp $JUNK
|
|
||||||
;;
|
|
||||||
1) # ham
|
|
||||||
/usr/lib/dovecot/deliver < $tmp
|
|
||||||
;;
|
|
||||||
2) # unsure
|
|
||||||
for d in .maybe -maybe; do
|
|
||||||
if [ -d $JUNK$d ]; then
|
|
||||||
deliver $tmp $JUNK$d
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
# Fall-through
|
|
||||||
/usr/lib/dovecot/deliver < $tmp
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
else
|
|
||||||
exec /usr/lib/dovecot/deliver
|
|
||||||
fi
|
|
|
@ -1,102 +0,0 @@
|
||||||
/*
|
|
||||||
* Description: Neale's DWM config
|
|
||||||
* Author: Neale Pickett <neale@woozle.org>
|
|
||||||
* Time-stamp: <2008-03-31 11:52:28 neale>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define TERM "rxvt"
|
|
||||||
|
|
||||||
/* appearance */
|
|
||||||
#define BORDERPX 2
|
|
||||||
#define FONT "-adobe-helvetica-medium-r-*-*-10-*-*-*-*-*-*-*"
|
|
||||||
#define NORMBORDERCOLOR "#cfdde6"
|
|
||||||
#define SELBORDERCOLOR "#80d0ff"
|
|
||||||
#define NORMBGCOLOR "#69668b"
|
|
||||||
#define NORMFGCOLOR "#d3d1e6"
|
|
||||||
#define SELBGCOLOR "#ccb48f"
|
|
||||||
#define SELFGCOLOR "#000000"
|
|
||||||
|
|
||||||
/* tagging */
|
|
||||||
const char tags[][MAXTAGLEN] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" };
|
|
||||||
|
|
||||||
Rule rules[] = {
|
|
||||||
/* class:instance:title substr tags ref isfloating */
|
|
||||||
{ "Gimp", tags[5], True },
|
|
||||||
{ "KNetworkManager", tags[8], False },
|
|
||||||
};
|
|
||||||
|
|
||||||
/* layout(s) */
|
|
||||||
#define RESIZEHINTS True /* False - respect size hints in tiled resizals */
|
|
||||||
#define SNAP 32 /* snap pixel */
|
|
||||||
|
|
||||||
Layout layouts[] = {
|
|
||||||
/* symbol function isfloating */
|
|
||||||
{ "[]=", tilev, False }, /* first entry is default */
|
|
||||||
{ "><>", floating, True },
|
|
||||||
{ "[M]", monocle, False },
|
|
||||||
};
|
|
||||||
|
|
||||||
const char *layoutcycle[] = {"[]=", "[M]"};
|
|
||||||
|
|
||||||
void
|
|
||||||
nextlayout(const char *arg)
|
|
||||||
{
|
|
||||||
static int which = 0;
|
|
||||||
|
|
||||||
which = (which + 1) % LENGTH(layoutcycle);
|
|
||||||
setlayout(layoutcycle[which]);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
restart(const char *arg)
|
|
||||||
{
|
|
||||||
if (arg) {
|
|
||||||
execlp(arg, arg, NULL);
|
|
||||||
} else {
|
|
||||||
execlp("dwm", "dwm", NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* key definitions */
|
|
||||||
#define MODKEY Mod4Mask
|
|
||||||
Key keys[] = {
|
|
||||||
/* modifier key function argument */
|
|
||||||
{ MODKEY, XK_a, spawn,
|
|
||||||
"exec dmenu_run -fn '"FONT"' -nb '"NORMBGCOLOR"' -nf '"NORMFGCOLOR"' -sb '"SELBGCOLOR"' -sf '"SELFGCOLOR"'" },
|
|
||||||
{ MODKEY|ShiftMask, XK_Return, spawn, "exec " TERM },
|
|
||||||
{ MODKEY, XK_l, spawn, "exec screenlock" },
|
|
||||||
{ MODKEY, XK_m, spawn, "exec " TERM " -e ncmpc" },
|
|
||||||
{ MODKEY, XK_w, spawn, "exec mpc prev" },
|
|
||||||
{ MODKEY, XK_v, spawn, "exec mpc toggle" },
|
|
||||||
{ MODKEY, XK_z, spawn, "exec mpc next" },
|
|
||||||
|
|
||||||
{ MODKEY, XK_n, focusnext, NULL },
|
|
||||||
{ MODKEY, XK_t, focusprev, NULL },
|
|
||||||
{ MODKEY, XK_Return, zoom, NULL },
|
|
||||||
{ MODKEY, XK_equal, nextlayout, NULL },
|
|
||||||
{ MODKEY|ShiftMask, XK_equal, setlayout, "><>" },
|
|
||||||
{ MODKEY|ShiftMask, XK_space, togglefloating, NULL },
|
|
||||||
{ MODKEY, XK_grave, killclient, NULL },
|
|
||||||
{ MODKEY, XK_0, view, NULL },
|
|
||||||
{ MODKEY, XK_1, view, tags[0] },
|
|
||||||
{ MODKEY, XK_2, view, tags[1] },
|
|
||||||
{ MODKEY, XK_3, view, tags[2] },
|
|
||||||
{ MODKEY, XK_4, view, tags[3] },
|
|
||||||
{ MODKEY, XK_5, view, tags[4] },
|
|
||||||
{ MODKEY, XK_6, view, tags[5] },
|
|
||||||
{ MODKEY, XK_7, view, tags[6] },
|
|
||||||
{ MODKEY, XK_8, view, tags[7] },
|
|
||||||
{ MODKEY, XK_9, view, tags[8] },
|
|
||||||
{ MODKEY|ShiftMask, XK_0, tag, NULL },
|
|
||||||
{ MODKEY|ShiftMask, XK_1, tag, tags[0] },
|
|
||||||
{ MODKEY|ShiftMask, XK_2, tag, tags[1] },
|
|
||||||
{ MODKEY|ShiftMask, XK_3, tag, tags[2] },
|
|
||||||
{ MODKEY|ShiftMask, XK_4, tag, tags[3] },
|
|
||||||
{ MODKEY|ShiftMask, XK_5, tag, tags[4] },
|
|
||||||
{ MODKEY|ShiftMask, XK_6, tag, tags[5] },
|
|
||||||
{ MODKEY|ShiftMask, XK_7, tag, tags[6] },
|
|
||||||
{ MODKEY|ShiftMask, XK_8, tag, tags[7] },
|
|
||||||
{ MODKEY|ShiftMask, XK_9, tag, tags[8] },
|
|
||||||
{ MODKEY, XK_q, restart, NULL },
|
|
||||||
{ MODKEY|ShiftMask, XK_q, quit, NULL },
|
|
||||||
};
|
|
|
@ -1,389 +0,0 @@
|
||||||
(** A stupid adventure game
|
|
||||||
|
|
||||||
Nick wanted an adventure game framework. Here ya go, Nick.
|
|
||||||
|
|
||||||
Compile this with
|
|
||||||
ocamlc -o foo foo.ml
|
|
||||||
|
|
||||||
@author Neale Pickett <neale@woozle.org>
|
|
||||||
|
|
||||||
*)
|
|
||||||
|
|
||||||
(** Directions *)
|
|
||||||
type direction = North | South | East | West | Up | Down | Emad
|
|
||||||
|
|
||||||
(** An item *)
|
|
||||||
type item = {
|
|
||||||
names: string list;
|
|
||||||
i_full_name: string;
|
|
||||||
i_description: string;
|
|
||||||
actions: (string * (item -> unit)) list;
|
|
||||||
}
|
|
||||||
|
|
||||||
(** A room. Contents are mutable so that the player can pick stuff
|
|
||||||
up. Exits are mutable so that I can link them back and forth *)
|
|
||||||
type room = {
|
|
||||||
r_full_name: string;
|
|
||||||
r_description: string;
|
|
||||||
mutable contents: item list;
|
|
||||||
mutable exits: (direction * room) list;
|
|
||||||
}
|
|
||||||
|
|
||||||
(** The player *)
|
|
||||||
type player = {
|
|
||||||
mutable carrying: item list;
|
|
||||||
mutable location: room;
|
|
||||||
}
|
|
||||||
|
|
||||||
let player = {
|
|
||||||
carrying = [];
|
|
||||||
location = {
|
|
||||||
r_full_name = "Nowhere";
|
|
||||||
r_description = "Non-descript";
|
|
||||||
contents = [];
|
|
||||||
exits = []
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
(*
|
|
||||||
*
|
|
||||||
* General functions
|
|
||||||
*
|
|
||||||
*)
|
|
||||||
|
|
||||||
(** Relocate something
|
|
||||||
|
|
||||||
Note that this does no checks to make sure the item is actually in
|
|
||||||
src!
|
|
||||||
|
|
||||||
@param i item to relocate
|
|
||||||
@param src where it comes from
|
|
||||||
@param dst where it goes
|
|
||||||
@return (new src, new dst)
|
|
||||||
*)
|
|
||||||
let move i src dst =
|
|
||||||
(List.filter ((!=) i) src,
|
|
||||||
i :: dst)
|
|
||||||
|
|
||||||
|
|
||||||
(** Is the player carrying an item? *)
|
|
||||||
let carrying p i =
|
|
||||||
List.exists ((==) i) p.carrying
|
|
||||||
|
|
||||||
(** Drop something *)
|
|
||||||
let drop i =
|
|
||||||
if carrying player i then
|
|
||||||
let carrying, contents = move i player.carrying player.location.contents in
|
|
||||||
player.carrying <- carrying;
|
|
||||||
player.location.contents <- contents;
|
|
||||||
else
|
|
||||||
raise (Failure ("You're not carrying " ^ i.i_full_name ^ "!"))
|
|
||||||
|
|
||||||
|
|
||||||
(** Pick something up *)
|
|
||||||
let get i =
|
|
||||||
if carrying player i then
|
|
||||||
raise (Failure ("You already have " ^ i.i_full_name ^ "!"))
|
|
||||||
else if List.exists ((==) i) player.location.contents then
|
|
||||||
let contents, carrying = move i player.location.contents player.carrying in
|
|
||||||
player.carrying <- carrying;
|
|
||||||
player.location.contents <- contents;
|
|
||||||
else
|
|
||||||
raise (Failure ("You don't see " ^ i.i_full_name ^ " here!"))
|
|
||||||
|
|
||||||
|
|
||||||
(** Describe an item *)
|
|
||||||
let describe i =
|
|
||||||
print_endline i.i_description
|
|
||||||
|
|
||||||
(*
|
|
||||||
*
|
|
||||||
* Rooms
|
|
||||||
*
|
|
||||||
* There's really no need to clutter up the global namespace here,
|
|
||||||
* since all I really need is "start_location" to set the starting
|
|
||||||
* location.
|
|
||||||
*
|
|
||||||
*)
|
|
||||||
let start_location =
|
|
||||||
let bigroom = { (* Big room *)
|
|
||||||
r_full_name = "The big room";
|
|
||||||
r_description = "This is that big room just outside the computer lab " ^
|
|
||||||
"with the blue ceiling. It smells fresh, yet dirty at the same time. " ^
|
|
||||||
"Off to the north is a grassy knoll.";
|
|
||||||
contents = [
|
|
||||||
{ (* lantern *)
|
|
||||||
names = ["brass lantern"; "brass"; "lantern"; "lamp"; "light"];
|
|
||||||
i_full_name = "a brass lantern";
|
|
||||||
i_description = "This rusty lantern looks like it's been used in " ^
|
|
||||||
"one too many adventure games.";
|
|
||||||
actions = [
|
|
||||||
("rub",
|
|
||||||
fun self ->
|
|
||||||
print_endline "Nothing happens.";
|
|
||||||
);
|
|
||||||
("kick",
|
|
||||||
fun self ->
|
|
||||||
print_endline "There'll be a hot time in the old town tonight!";
|
|
||||||
)
|
|
||||||
]
|
|
||||||
};
|
|
||||||
{ (* stone *)
|
|
||||||
names = ["smooth"; "stone"; "rock"];
|
|
||||||
i_full_name = "a smooth stone";
|
|
||||||
i_description = "This stone is smooth. Yes it is.";
|
|
||||||
actions = [
|
|
||||||
("rub",
|
|
||||||
fun self ->
|
|
||||||
print_endline "Your worries seem to vanish.";
|
|
||||||
);
|
|
||||||
("throw",
|
|
||||||
fun self ->
|
|
||||||
print_endline "You throw the stone.";
|
|
||||||
let carrying, contents = (move self player.carrying
|
|
||||||
player.location.contents) in
|
|
||||||
drop self;
|
|
||||||
print_endline "It lands a stone's throw away.";
|
|
||||||
)
|
|
||||||
]
|
|
||||||
}
|
|
||||||
];
|
|
||||||
exits = []
|
|
||||||
}
|
|
||||||
in
|
|
||||||
let knoll = { (* Grassy knoll *)
|
|
||||||
r_full_name = "Grassy knoll";
|
|
||||||
r_description = "You find yourself standing on the top of a " ^
|
|
||||||
"small mound. The green carpeting of grass beneath your feet " ^
|
|
||||||
"beckons kite-flying or frisbee-throwing. Near the bottom of the " ^
|
|
||||||
"mound is a funny-looking man intensely examining a teacup. He " ^
|
|
||||||
"is wearing a nametag reading \"Emad\".";
|
|
||||||
contents = [];
|
|
||||||
exits = []
|
|
||||||
}
|
|
||||||
in
|
|
||||||
let emad = {
|
|
||||||
r_full_name = "Emad"; (* Emad *)
|
|
||||||
r_description = "You are in Emad. How unpleasant.";
|
|
||||||
contents = [
|
|
||||||
{ (* ham sandwich *)
|
|
||||||
names = ["ham and bacon sandwich"; "bacon sandwich"; "ham sandwich";
|
|
||||||
"sandwich"; "ham"; "bacon"];
|
|
||||||
i_full_name = "a delicious ham and bacon sandwich";
|
|
||||||
i_description = "Named after John Montagu, fourth Earl of Sandwich, " ^
|
|
||||||
"this savory instance is comprised of ham and bacon, \"sandwiched\" " ^
|
|
||||||
"as it were between two slices of whole-wheat bread.";
|
|
||||||
actions = [
|
|
||||||
("eat",
|
|
||||||
fun self ->
|
|
||||||
print_endline "A little acidic, but not bad."
|
|
||||||
)
|
|
||||||
]
|
|
||||||
}
|
|
||||||
];
|
|
||||||
exits = []
|
|
||||||
}
|
|
||||||
in
|
|
||||||
begin
|
|
||||||
bigroom.exits <- [(North, knoll)];
|
|
||||||
knoll.exits <- [(South, bigroom);
|
|
||||||
(Emad, emad)];
|
|
||||||
emad.exits <- [(Up, knoll)];
|
|
||||||
bigroom
|
|
||||||
end
|
|
||||||
|
|
||||||
let describe_room r =
|
|
||||||
let rec display_items = function
|
|
||||||
| [] ->
|
|
||||||
" nothing"
|
|
||||||
| [i] -> (* just one *)
|
|
||||||
(" " ^ i.i_full_name)
|
|
||||||
| [i; j] -> (* two *)
|
|
||||||
(" " ^ i.i_full_name ^
|
|
||||||
", and " ^ j.i_full_name)
|
|
||||||
| i :: j :: tl -> (* multiple *)
|
|
||||||
(" " ^ i.i_full_name ^ "," ^
|
|
||||||
display_items (j :: tl))
|
|
||||||
in
|
|
||||||
print_endline "";
|
|
||||||
print_endline r.r_full_name;
|
|
||||||
print_endline "";
|
|
||||||
print_endline r.r_description;
|
|
||||||
if (r.contents = []) then
|
|
||||||
print_endline ""
|
|
||||||
else
|
|
||||||
print_endline ("You see" ^ (display_items r.contents) ^ " here.")
|
|
||||||
|
|
||||||
|
|
||||||
(*
|
|
||||||
*
|
|
||||||
* Player functions
|
|
||||||
*
|
|
||||||
*)
|
|
||||||
|
|
||||||
|
|
||||||
let rec find_item name l =
|
|
||||||
match (name, l) with
|
|
||||||
| _, [] ->
|
|
||||||
raise Not_found
|
|
||||||
| name, i :: tl ->
|
|
||||||
if List.exists ((=) name) i.names then
|
|
||||||
i
|
|
||||||
else
|
|
||||||
find_item name tl
|
|
||||||
|
|
||||||
let rec find_action action l =
|
|
||||||
match (action, l) with
|
|
||||||
| _, [] ->
|
|
||||||
raise Not_found
|
|
||||||
| action, (name, func) :: tl ->
|
|
||||||
if (action = name) then
|
|
||||||
func
|
|
||||||
else
|
|
||||||
find_action action tl
|
|
||||||
|
|
||||||
(** Apply action to name
|
|
||||||
|
|
||||||
@param action What to do
|
|
||||||
@param name What to do it to
|
|
||||||
*)
|
|
||||||
let apply_action action name =
|
|
||||||
match action with
|
|
||||||
| "describe" | "look" | "l" ->
|
|
||||||
let i = try
|
|
||||||
find_item name player.carrying
|
|
||||||
with Not_found ->
|
|
||||||
try
|
|
||||||
find_item name player.location.contents
|
|
||||||
with Not_found ->
|
|
||||||
raise (Failure "You're not carrying that.")
|
|
||||||
in
|
|
||||||
describe i
|
|
||||||
| "take" | "get" ->
|
|
||||||
let i = try
|
|
||||||
find_item name player.location.contents
|
|
||||||
with Not_found ->
|
|
||||||
raise (Failure "You don't see that here.")
|
|
||||||
in
|
|
||||||
get i;
|
|
||||||
print_endline "Taken."
|
|
||||||
| "drop" ->
|
|
||||||
let i = try
|
|
||||||
find_item name player.carrying
|
|
||||||
with Not_found ->
|
|
||||||
raise (Failure "You're not carrying that.")
|
|
||||||
in
|
|
||||||
drop i;
|
|
||||||
print_endline "Dropped."
|
|
||||||
| _ ->
|
|
||||||
let i = try
|
|
||||||
find_item name player.carrying
|
|
||||||
with Not_found ->
|
|
||||||
raise (Failure "You don't have that.")
|
|
||||||
in
|
|
||||||
let a = try
|
|
||||||
find_action action i.actions
|
|
||||||
with Not_found ->
|
|
||||||
raise (Failure ("You can't do that to " ^ i.i_full_name ^ "."))
|
|
||||||
in
|
|
||||||
a i
|
|
||||||
|
|
||||||
(** Move the player
|
|
||||||
|
|
||||||
@param dir direction
|
|
||||||
*)
|
|
||||||
let go dir =
|
|
||||||
let moveout (d, room) =
|
|
||||||
if d = dir then
|
|
||||||
begin
|
|
||||||
player.location <- room;
|
|
||||||
describe_room player.location;
|
|
||||||
end
|
|
||||||
in
|
|
||||||
let here = player.location in
|
|
||||||
List.iter moveout player.location.exits;
|
|
||||||
if here == player.location then
|
|
||||||
raise (Failure "You can't get there from here.")
|
|
||||||
|
|
||||||
(** Display inventory
|
|
||||||
*)
|
|
||||||
let inventory () =
|
|
||||||
let print_item i =
|
|
||||||
print_endline ("* " ^ i.i_full_name)
|
|
||||||
in
|
|
||||||
if (player.carrying = []) then
|
|
||||||
print_endline "You are empty-handed."
|
|
||||||
else
|
|
||||||
begin
|
|
||||||
print_endline "You are carrying: ";
|
|
||||||
List.iter print_item player.carrying
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
(** Do something
|
|
||||||
|
|
||||||
@param action What to do
|
|
||||||
*)
|
|
||||||
let do_action action =
|
|
||||||
match action with
|
|
||||||
| "inventory" | "inv" | "i" ->
|
|
||||||
inventory ()
|
|
||||||
| "look" | "l" ->
|
|
||||||
describe_room player.location
|
|
||||||
| "north" | "n" ->
|
|
||||||
go North
|
|
||||||
| "south" | "s" ->
|
|
||||||
go South
|
|
||||||
| "east" | "e" ->
|
|
||||||
go East
|
|
||||||
| "west" | "w" ->
|
|
||||||
go West
|
|
||||||
| "up" | "u" ->
|
|
||||||
go Up
|
|
||||||
| "down" | "d" ->
|
|
||||||
go Down
|
|
||||||
| "emad" ->
|
|
||||||
go Emad
|
|
||||||
| _ ->
|
|
||||||
print_endline "I'm sorry, Dave, I'm afraid I can't do that."
|
|
||||||
|
|
||||||
(** Parse a line
|
|
||||||
|
|
||||||
@param str the line to parse
|
|
||||||
*)
|
|
||||||
let parse str =
|
|
||||||
try
|
|
||||||
let action, name =
|
|
||||||
let pos = String.index str ' ' in
|
|
||||||
(String.sub str 0 pos,
|
|
||||||
String.sub str (pos + 1) ((String.length str) - pos - 1))
|
|
||||||
in
|
|
||||||
apply_action action name
|
|
||||||
with Not_found ->
|
|
||||||
do_action str
|
|
||||||
|
|
||||||
(** Read-Eval-Print loop
|
|
||||||
*)
|
|
||||||
let rec repl () =
|
|
||||||
let line = read_line () in
|
|
||||||
print_endline "";
|
|
||||||
begin
|
|
||||||
try
|
|
||||||
parse (String.lowercase line)
|
|
||||||
with Failure str ->
|
|
||||||
print_endline str
|
|
||||||
end;
|
|
||||||
repl ()
|
|
||||||
|
|
||||||
let main () =
|
|
||||||
player.location <- start_location;
|
|
||||||
describe_room player.location;
|
|
||||||
repl ()
|
|
||||||
|
|
||||||
let _ =
|
|
||||||
try
|
|
||||||
main ()
|
|
||||||
with End_of_file ->
|
|
||||||
()
|
|
||||||
|
|
||||||
|
|
|
@ -1,38 +0,0 @@
|
||||||
#! /bin/sh
|
|
||||||
|
|
||||||
frm="$1"
|
|
||||||
ext="$2"
|
|
||||||
base="${HOME}/.gourmet"
|
|
||||||
|
|
||||||
num="`echo $ext | sed -n 's/^\([0-9]*\)-.*/\1/p'`"
|
|
||||||
|
|
||||||
if [ -z "$num" ]; then
|
|
||||||
# No number; not a gourmet address
|
|
||||||
exec cat
|
|
||||||
fi
|
|
||||||
|
|
||||||
if ! [ -d "$base" ]; then
|
|
||||||
mkdir "$base"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -f "$base/$ext" ]; then
|
|
||||||
num="`cat $base/$ext`"
|
|
||||||
fi
|
|
||||||
|
|
||||||
left=`expr "$num" - 1`
|
|
||||||
echo $left > "$base/$ext"
|
|
||||||
|
|
||||||
if [ "$num" -gt 0 ]; then
|
|
||||||
exec awk "
|
|
||||||
{
|
|
||||||
if (! p && /^Subject: /) {
|
|
||||||
sub(\"^Subject: \", \"Subject: <$ext: $left left> \");
|
|
||||||
p = 1;
|
|
||||||
}
|
|
||||||
print;
|
|
||||||
}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Must have sent too many, return permanent failure code
|
|
||||||
echo "Address has self-destructed." 1>&2
|
|
||||||
exit 69
|
|
|
@ -1,2 +0,0 @@
|
||||||
Title: Miscellaneous hacks
|
|
||||||
|
|
|
@ -1,86 +0,0 @@
|
||||||
#!/usr/bin/python
|
|
||||||
|
|
||||||
description = '''All Maildir++ folders are checked for old mail. Any messages older than
|
|
||||||
DAYS days than the newest message in a folder are removed. If there is
|
|
||||||
a file named"expire" in a maildir, its contents will be used instead of
|
|
||||||
DAYS for that folder. You can put "12345678" in the "expire" file to
|
|
||||||
set an expiration of 1413 years, which is probably longer than you will
|
|
||||||
care about the mail folder.
|
|
||||||
|
|
||||||
Specify a path in MAILDIR to check a specific Maildir. Subfolders will
|
|
||||||
not be checked in this case.
|
|
||||||
|
|
||||||
'''
|
|
||||||
|
|
||||||
import glob
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
import optparse
|
|
||||||
|
|
||||||
progname = sys.argv[0]
|
|
||||||
debug = 0
|
|
||||||
|
|
||||||
def expire(dirname, days):
|
|
||||||
expire = "%s/expire" % dirname
|
|
||||||
if os.path.exists(expire):
|
|
||||||
days = int(open(expire).read())
|
|
||||||
secs = long(days) * 24 * 60 * 60
|
|
||||||
messages = glob.glob("%s/cur/*" % dirname)
|
|
||||||
messages += glob.glob("%s/new/*" % dirname)
|
|
||||||
if not messages:
|
|
||||||
return
|
|
||||||
messages = [(os.path.getmtime(m), m) for m in messages]
|
|
||||||
messages.sort()
|
|
||||||
latest = messages[-1][0]
|
|
||||||
for m in messages:
|
|
||||||
if (m[0] + secs) < latest:
|
|
||||||
try:
|
|
||||||
_, flags = m[1].split(',')
|
|
||||||
except ValueError:
|
|
||||||
continue
|
|
||||||
if 'S' in flags:
|
|
||||||
# Only if the mail's been seen
|
|
||||||
if debug:
|
|
||||||
print m[1]
|
|
||||||
else:
|
|
||||||
os.remove(m[1])
|
|
||||||
|
|
||||||
def usage(err=None):
|
|
||||||
if err:
|
|
||||||
print "Error: %s" % err
|
|
||||||
print
|
|
||||||
print __doc__ % globals()
|
|
||||||
if err:
|
|
||||||
sys.exit(1)
|
|
||||||
else:
|
|
||||||
sys.exit()
|
|
||||||
|
|
||||||
def main():
|
|
||||||
import optparse
|
|
||||||
global debug
|
|
||||||
|
|
||||||
parser = optparse.OptionParser(usage='usage: %prog [options] [MAILDIR ...]',
|
|
||||||
description=description)
|
|
||||||
parser.add_option('-d', '--debug', dest='debug', action='store_true',
|
|
||||||
help="run in debug mode (don't do anything)")
|
|
||||||
parser.add_option('-t', '--time', dest='days', metavar='DAYS', type='int',
|
|
||||||
default=90,
|
|
||||||
help="Mail older than DAYS days will be removed (default 90)")
|
|
||||||
options, args = parser.parse_args()
|
|
||||||
|
|
||||||
debug = options.debug
|
|
||||||
|
|
||||||
if (len(args) == 0):
|
|
||||||
base = os.path.expanduser("~/Maildir")
|
|
||||||
files = [os.path.join(base, x) for x in os.listdir(base) if x[0] == '.']
|
|
||||||
dirs = [f for f in files if os.path.isdir(f)]
|
|
||||||
dirs.append(base)
|
|
||||||
else:
|
|
||||||
dirs = args
|
|
||||||
|
|
||||||
for d in dirs:
|
|
||||||
expire(d, options.days)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
|
@ -1,190 +0,0 @@
|
||||||
#! /usr/bin/python
|
|
||||||
|
|
||||||
import os
|
|
||||||
import glob
|
|
||||||
import time
|
|
||||||
from sets import Set
|
|
||||||
|
|
||||||
bogosity = {'U': "Unsure",
|
|
||||||
'S': "Spam",
|
|
||||||
'H': "Ham"}
|
|
||||||
|
|
||||||
def classification(filename):
|
|
||||||
f = file(filename)
|
|
||||||
for l in f:
|
|
||||||
if l.startswith('X-Bogosity: '):
|
|
||||||
return l[12]
|
|
||||||
elif not l.strip():
|
|
||||||
return None
|
|
||||||
|
|
||||||
def reclassify(oldtype, newtype, filenames):
|
|
||||||
cmd = 'bogofilter -b -v'
|
|
||||||
t = oldtype + newtype
|
|
||||||
if t == 'SH':
|
|
||||||
cmd += ' -Sn'
|
|
||||||
elif t == 'HS':
|
|
||||||
cmd += ' -Ns'
|
|
||||||
elif t == 'UH':
|
|
||||||
cmd += ' -n'
|
|
||||||
elif t == 'US':
|
|
||||||
cmd += ' -s'
|
|
||||||
else:
|
|
||||||
raise ValueError('Unable to reclassify %s' % t)
|
|
||||||
|
|
||||||
cmd += ' 2>/dev/null'
|
|
||||||
|
|
||||||
# Reclassify them
|
|
||||||
f = os.popen(cmd, 'w')
|
|
||||||
for fn in filenames:
|
|
||||||
f.write('%s\n' % fn)
|
|
||||||
ret = f.close()
|
|
||||||
if ret:
|
|
||||||
raise IOError("bogofilter puked on %s (%r)" % (fn, ret))
|
|
||||||
|
|
||||||
# Add new bogosity header
|
|
||||||
for fn in filenames:
|
|
||||||
base, filename = os.path.split(fn)
|
|
||||||
folder, _ = os.path.split(base)
|
|
||||||
tmpfn = os.path.join(folder, 'tmp', filename)
|
|
||||||
|
|
||||||
inf = file(fn)
|
|
||||||
outf = file(tmpfn, 'w')
|
|
||||||
|
|
||||||
headered = False
|
|
||||||
for l in inf:
|
|
||||||
if l.startswith('X-Bogosity: '):
|
|
||||||
l = (('X-Bogosity: %s (Reclassified), was ' % bogosity[newtype])
|
|
||||||
+ l[12:])
|
|
||||||
headered = True
|
|
||||||
elif not l.strip() and not headered:
|
|
||||||
l = (('X-Bogosity: %s (Reclassified)\n' % bogosity[newtype]))
|
|
||||||
headered = True
|
|
||||||
outf.write(l)
|
|
||||||
os.rename(tmpfn, fn)
|
|
||||||
|
|
||||||
def visit(path, folder_type):
|
|
||||||
# Read in list of already-processed files
|
|
||||||
visited = os.path.join(path, 'spamfairy-visited')
|
|
||||||
oldfiles = Set()
|
|
||||||
try:
|
|
||||||
f = file(visited)
|
|
||||||
for l in f:
|
|
||||||
oldfiles.add(l.strip())
|
|
||||||
f.close()
|
|
||||||
except IOError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
if folder_type == 'S':
|
|
||||||
subdirs = ('cur', 'new')
|
|
||||||
else:
|
|
||||||
subdirs = ('cur',)
|
|
||||||
|
|
||||||
for sd in subdirs:
|
|
||||||
# Read in list of current files in the directory
|
|
||||||
root = os.path.join(path, sd)
|
|
||||||
files = Set(os.listdir(root))
|
|
||||||
|
|
||||||
# We only consider the difference
|
|
||||||
todo = files - oldfiles
|
|
||||||
|
|
||||||
# Check new messages for reclassification
|
|
||||||
reclass = {} # {oldtype: [filenames]}
|
|
||||||
for fn in todo:
|
|
||||||
fn = os.path.join(root, fn)
|
|
||||||
c = classification(fn)
|
|
||||||
if not c:
|
|
||||||
continue
|
|
||||||
if c != folder_type:
|
|
||||||
l = reclass.setdefault(c, [])
|
|
||||||
l.append(fn)
|
|
||||||
|
|
||||||
# Reclassify anything that needs it
|
|
||||||
for c, filenames in reclass.iteritems():
|
|
||||||
try:
|
|
||||||
reclassify(c, folder_type, filenames)
|
|
||||||
except ValueError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
# Write out new list of processed files
|
|
||||||
new_visited = "%s.%d" % (visited, os.getpid())
|
|
||||||
f = file(new_visited, 'w')
|
|
||||||
for fn in files:
|
|
||||||
f.write('%s\n' % fn)
|
|
||||||
f.close()
|
|
||||||
os.rename(new_visited, visited)
|
|
||||||
|
|
||||||
|
|
||||||
def get_folder_type(path):
|
|
||||||
"""Auto-detect type of a maildir.
|
|
||||||
|
|
||||||
You can have the following files in your maildir:
|
|
||||||
spamfairy-ignore : skip this folder entirely
|
|
||||||
spamfairy-spam : treat this folder as spam
|
|
||||||
spamfairy-ham : treat this folder as ham
|
|
||||||
|
|
||||||
Otherwise, check the name of the folder:
|
|
||||||
Trash : skip
|
|
||||||
Drafts : skip
|
|
||||||
Sent : skip
|
|
||||||
Unsure : skip
|
|
||||||
Junk.maybe : skip
|
|
||||||
Junk : spam
|
|
||||||
|
|
||||||
Otherwise, treat it as a ham folder.
|
|
||||||
|
|
||||||
Return values are None for skip, 'S' for spam, 'H' for ham
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
path = os.path.realpath(path)
|
|
||||||
_, folder = os.path.split(path)
|
|
||||||
folder = folder.lower()
|
|
||||||
if os.path.exists(os.path.join(path, 'spamfairy-ignore')):
|
|
||||||
return None
|
|
||||||
elif os.path.exists(os.path.join(path, 'spamfairy-ham')):
|
|
||||||
return 'H'
|
|
||||||
elif os.path.exists(os.path.join(path, 'spamfairy-spam')):
|
|
||||||
return 'S'
|
|
||||||
elif folder in ('.sent', '.drafts', '.trash', '.unsure', '.junk.maybe'):
|
|
||||||
return None
|
|
||||||
elif folder in ('.junk', '.spam'):
|
|
||||||
return 'S'
|
|
||||||
else:
|
|
||||||
return 'H'
|
|
||||||
|
|
||||||
|
|
||||||
def sprinkle(folders):
|
|
||||||
"""Sprinkle magic spamfairy dust on the given folders"""
|
|
||||||
|
|
||||||
if not folders:
|
|
||||||
maildir = os.path.expanduser(os.path.join('~', 'Maildir'))
|
|
||||||
folders = [maildir]
|
|
||||||
folders += glob.glob(os.path.join(maildir, '.??*'))
|
|
||||||
|
|
||||||
# Only do maildirs
|
|
||||||
folders = filter(lambda d: os.path.isdir(os.path.join(d, 'cur')),
|
|
||||||
folders)
|
|
||||||
|
|
||||||
for path in folders:
|
|
||||||
folder_type = get_folder_type(path)
|
|
||||||
if not folder_type:
|
|
||||||
continue
|
|
||||||
visit(path, folder_type)
|
|
||||||
|
|
||||||
def compact(wordlist):
|
|
||||||
"""Compact bogofilter database"""
|
|
||||||
otime = os.path.getmtime(wordlist)
|
|
||||||
now = time.time()
|
|
||||||
if now - otime > 60*60*24*11:
|
|
||||||
new = '%s.new' % wordlist
|
|
||||||
ret = os.system('bogoutil -d %s | bogoutil -l %s' % (wordlist, new))
|
|
||||||
if not ret:
|
|
||||||
os.rename(new, wordlist)
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
import sys
|
|
||||||
|
|
||||||
wordlist = os.path.expanduser(os.path.join('~', '.bogofilter', 'wordlist.db'))
|
|
||||||
if os.path.exists(wordlist):
|
|
||||||
sprinkle(sys.argv[1:])
|
|
||||||
compact(wordlist)
|
|
|
@ -1,4 +0,0 @@
|
||||||
index.html: - 12dab84c3ad5b0dba380c051471c14d6 - -
|
|
||||||
index.ptml: 1042003175 - 39a0ed00cb554392574b5955dbdc0af9 -
|
|
||||||
links.html: - 962d7fd4c69ea67cfeb1d0cc88e892a6 - -
|
|
||||||
links.ptml: 1041913579 - bd8a21beca5f285bf5e8ba50e86f340f -
|
|
|
@ -1,562 +0,0 @@
|
||||||
%!PS-Adobe-2.0
|
|
||||||
%%Title: Alice in DIGITALand -- an example application of skel.ps
|
|
||||||
%%Creator: Neale Pickett <neale@lanl.gov>
|
|
||||||
%%CreationDate: Thu Nov 22 15:27:53 MST 1998
|
|
||||||
%% Time-stamp: <2002-10-22 09:34:24 neale>
|
|
||||||
%%EndComments
|
|
||||||
|
|
||||||
/FontSize 12 def
|
|
||||||
|
|
||||||
/RegFont /Times-Roman def
|
|
||||||
/BoldFont /Times-Bold def
|
|
||||||
/ItalFont /Times-Italic def
|
|
||||||
|
|
||||||
/RegFSet RegFont findfont FontSize scalefont def
|
|
||||||
/BoldFSet BoldFont findfont FontSize scalefont def
|
|
||||||
/HeadFSet BoldFont findfont FontSize 1.1 mul scalefont def
|
|
||||||
/ItalFSet ItalFont findfont FontSize scalefont def
|
|
||||||
|
|
||||||
/SetRegFont { RegFSet setfont } def
|
|
||||||
/SetBoldFont { BoldFSet setfont } def
|
|
||||||
/SetHeadFont { HeadFSet setfont } def
|
|
||||||
/SetItalFont { ItalFSet setfont } def
|
|
||||||
|
|
||||||
/LM 50 def
|
|
||||||
/BM 50 def
|
|
||||||
/RM 580 LM sub def
|
|
||||||
/TM 760 BM sub def
|
|
||||||
|
|
||||||
/indentLevel 30 def
|
|
||||||
|
|
||||||
% Re-set the margins
|
|
||||||
/reset_margins {
|
|
||||||
/lm LM def
|
|
||||||
/rm RM def
|
|
||||||
} def
|
|
||||||
|
|
||||||
reset_margins
|
|
||||||
|
|
||||||
% Move down just a little
|
|
||||||
/down {
|
|
||||||
reset_margins
|
|
||||||
lm indentation add currentpoint exch pop
|
|
||||||
FontSize 3 div sub
|
|
||||||
moveto
|
|
||||||
} def
|
|
||||||
|
|
||||||
% Move to the next line
|
|
||||||
/next {
|
|
||||||
reset_margins
|
|
||||||
lm indentation add currentpoint exch pop % LM Y
|
|
||||||
FontSize 1.1 mul sub % LM Y'
|
|
||||||
moveto
|
|
||||||
currentpoint exch pop
|
|
||||||
BM lt {
|
|
||||||
showpage
|
|
||||||
LM TM moveto
|
|
||||||
} {} ifelse
|
|
||||||
} def
|
|
||||||
|
|
||||||
% Move to the previous line
|
|
||||||
/prev {
|
|
||||||
lm indentation add currentpoint exch pop % LM Y
|
|
||||||
FontSize 1.1 mul add % LM Y'
|
|
||||||
moveto
|
|
||||||
} def
|
|
||||||
|
|
||||||
% Re-align the indentation
|
|
||||||
/align {
|
|
||||||
lm indentation add currentpoint exch pop moveto
|
|
||||||
} def
|
|
||||||
|
|
||||||
% Indent once
|
|
||||||
/indentation 0 def
|
|
||||||
/indent {
|
|
||||||
/indentation indentation indentLevel add def
|
|
||||||
align
|
|
||||||
} def
|
|
||||||
|
|
||||||
% Deindent
|
|
||||||
/deindent {
|
|
||||||
/indentation indentation indentLevel sub def
|
|
||||||
align
|
|
||||||
} def
|
|
||||||
|
|
||||||
% Show left justified
|
|
||||||
/lshow {
|
|
||||||
gsave
|
|
||||||
% Set the left margin
|
|
||||||
dup
|
|
||||||
stringwidth pop
|
|
||||||
LM add
|
|
||||||
/lm exch def
|
|
||||||
|
|
||||||
currentpoint exch pop % (str) Y
|
|
||||||
LM exch % (str) x Y
|
|
||||||
moveto show
|
|
||||||
grestore
|
|
||||||
} def
|
|
||||||
|
|
||||||
% Show centered
|
|
||||||
/cshow {
|
|
||||||
gsave
|
|
||||||
dup % (str) (str)
|
|
||||||
stringwidth pop % (str) x
|
|
||||||
2 div % (str) x/2
|
|
||||||
RM LM sub 2 div % (str) x/2 RM/2
|
|
||||||
exch sub LM add % (str) x'
|
|
||||||
currentpoint exch pop % (str) x' Y
|
|
||||||
moveto show
|
|
||||||
grestore
|
|
||||||
} def
|
|
||||||
|
|
||||||
% Show right justified
|
|
||||||
/rshow {
|
|
||||||
gsave
|
|
||||||
dup % (str) (str)
|
|
||||||
stringwidth pop % (str) x
|
|
||||||
|
|
||||||
% set the right margin
|
|
||||||
dup
|
|
||||||
RM exch sub padwidth sub
|
|
||||||
/rm exch def
|
|
||||||
|
|
||||||
RM exch sub % (str) x'
|
|
||||||
currentpoint exch pop % (str) x' Y
|
|
||||||
moveto show
|
|
||||||
grestore
|
|
||||||
} def
|
|
||||||
|
|
||||||
% Show in a bold font
|
|
||||||
/bshow {
|
|
||||||
SetBoldFont
|
|
||||||
show
|
|
||||||
SetRegFont
|
|
||||||
} def
|
|
||||||
|
|
||||||
% Show in a italics font
|
|
||||||
/ishow {
|
|
||||||
SetItalFont
|
|
||||||
show
|
|
||||||
SetRegFont
|
|
||||||
} def
|
|
||||||
|
|
||||||
% I totally stole this out of the blue book.
|
|
||||||
/wordbreak ( ) def
|
|
||||||
/BreakIntoLines {
|
|
||||||
/proc exch def
|
|
||||||
/linelength exch def
|
|
||||||
/textstring exch def
|
|
||||||
/curwidth exch def
|
|
||||||
|
|
||||||
/breakwidth wordbreak stringwidth pop def
|
|
||||||
/lastwordbreak 0 def
|
|
||||||
|
|
||||||
/startchar 0 def
|
|
||||||
/restoftext textstring def
|
|
||||||
|
|
||||||
{
|
|
||||||
restoftext wordbreak search
|
|
||||||
|
|
||||||
{
|
|
||||||
/done false def
|
|
||||||
} {
|
|
||||||
() exch
|
|
||||||
wordbreak exch
|
|
||||||
/done true def
|
|
||||||
} ifelse
|
|
||||||
|
|
||||||
/nextword exch def pop
|
|
||||||
/restoftext exch def
|
|
||||||
/wordwidth nextword stringwidth pop def
|
|
||||||
|
|
||||||
curwidth wordwidth add linelength gt
|
|
||||||
{
|
|
||||||
textstring startchar
|
|
||||||
lastwordbreak startchar sub
|
|
||||||
getinterval proc
|
|
||||||
/startchar lastwordbreak def
|
|
||||||
/curwidth wordwidth breakwidth add def
|
|
||||||
} {
|
|
||||||
/curwidth curwidth wordwidth add
|
|
||||||
breakwidth add def
|
|
||||||
} ifelse
|
|
||||||
|
|
||||||
/lastwordbreak lastwordbreak
|
|
||||||
nextword length add 1 add def
|
|
||||||
|
|
||||||
done {
|
|
||||||
exit
|
|
||||||
} {
|
|
||||||
} ifelse
|
|
||||||
} loop
|
|
||||||
/lastchar textstring length def
|
|
||||||
textstring startchar lastchar startchar sub
|
|
||||||
getinterval proc
|
|
||||||
} def
|
|
||||||
|
|
||||||
% Show some text, and word-wrap it if necessary, then move to the next line
|
|
||||||
/wshow {
|
|
||||||
0 exch
|
|
||||||
/x currentpoint pop def
|
|
||||||
rm x sub % Line length
|
|
||||||
{
|
|
||||||
show next
|
|
||||||
x currentpoint exch pop moveto
|
|
||||||
}
|
|
||||||
BreakIntoLines
|
|
||||||
} def
|
|
||||||
|
|
||||||
% Show indented, wrapped text
|
|
||||||
/iwshow {
|
|
||||||
indentLevel exch
|
|
||||||
/x currentpoint pop def
|
|
||||||
rm x sub
|
|
||||||
indentLevel 0 rmoveto
|
|
||||||
{
|
|
||||||
show next
|
|
||||||
x currentpoint exch pop moveto
|
|
||||||
}
|
|
||||||
BreakIntoLines
|
|
||||||
} def
|
|
||||||
|
|
||||||
% Show inverse-indented, wrapped text
|
|
||||||
/iiwshow {
|
|
||||||
indentLevel neg exch
|
|
||||||
/x currentpoint pop indentLevel add def
|
|
||||||
rm x sub
|
|
||||||
{
|
|
||||||
show next
|
|
||||||
x currentpoint exch pop moveto
|
|
||||||
}
|
|
||||||
BreakIntoLines
|
|
||||||
indentLevel neg 0 rmoveto
|
|
||||||
} def
|
|
||||||
|
|
||||||
|
|
||||||
LM TM moveto
|
|
||||||
SetRegFont
|
|
||||||
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
||||||
% Content goes here ;-)
|
|
||||||
|
|
||||||
(Alice in DIGITALand) cshow next
|
|
||||||
|
|
||||||
(Author: ) show (rals@pineapple.bbs.com) ishow next next align
|
|
||||||
|
|
||||||
("Where am I?" asked Alice, as she peered at the large 7-lettered sign
|
|
||||||
with the standard blue letters.) iwshow
|
|
||||||
|
|
||||||
("You're in Digitaland," replied the security guard, "May I see your
|
|
||||||
badge?") iwshow
|
|
||||||
|
|
||||||
("I don't have a badge.") iwshow
|
|
||||||
|
|
||||||
("Did you lose it?") iwshow
|
|
||||||
|
|
||||||
("No," answered Alice in a puzzled tone. "How could I lose something I
|
|
||||||
never had?") iwshow
|
|
||||||
|
|
||||||
("If it's not lost then you must show it to me.") iwshow
|
|
||||||
|
|
||||||
("I can't. I don't have one.") iwshow
|
|
||||||
|
|
||||||
("Then you'll have to have a temporary.") iwshow
|
|
||||||
|
|
||||||
("A temporary what?" asked Alice, more confused then ever.) iwshow
|
|
||||||
|
|
||||||
("A temporary Badge. What's your badge number?" requested the guard.) iwshow
|
|
||||||
|
|
||||||
("I don't have one") iwshow
|
|
||||||
|
|
||||||
("Of course not, Ken Olsen has 1. Give me your badge number, and your
|
|
||||||
cost center") iwshow
|
|
||||||
|
|
||||||
("I'm so confused. I can't do this. I've already said 3 times why. Do
|
|
||||||
I have to tell you 4?") iwshow
|
|
||||||
|
|
||||||
("Ahhh. 3XY, badge number 4. You must be very important to have such a
|
|
||||||
low badge number. I should have immediately recognized how low by your
|
|
||||||
state of extreme confusion. Here's your temporary. Go right on in.") iwshow
|
|
||||||
|
|
||||||
(Alice pasted the sticky paper to her dress and headed down the hall.
|
|
||||||
Not 10 feet ahead she saw a rather distressed looking rabbit coming
|
|
||||||
toward her. He was dressed in a pair of torn, faded jeans, and a dirty
|
|
||||||
tee shirt.) iwshow
|
|
||||||
|
|
||||||
("What's wrong?" Alice asked.) iwshow
|
|
||||||
|
|
||||||
("I'm late! I'm late!" exclaimed the rabbit as he peered at the PERT
|
|
||||||
chart dangling from his pocket protector.) iwshow
|
|
||||||
|
|
||||||
("Late for what?" asked Alice.) iwshow
|
|
||||||
|
|
||||||
("My date. I'm going to miss my date. I've got a deadline to meet and
|
|
||||||
I'm not going to make it.") iwshow
|
|
||||||
|
|
||||||
("Well, if it's already dead, it probably won't mind. In fact it isn't
|
|
||||||
likely to be going too far in such a state. I'm sure that however long
|
|
||||||
you take will be just fine.") iwshow
|
|
||||||
|
|
||||||
("You obviously don't understand. Everything takes longer than it
|
|
||||||
really does. It doesn't matter what you are doing, only that you meet
|
|
||||||
your date, and that's always impossible.") iwshow
|
|
||||||
|
|
||||||
("Well if it's impossible, why would anyone expect you to meet it?"
|
|
||||||
Almost at once regretting that she had asked. Was this was going to be
|
|
||||||
as confusing as badges?) iwshow
|
|
||||||
|
|
||||||
("It's really very simple. In order to move forward, you need a goal.
|
|
||||||
Any goal will do. It just has to be impossible to do. To motivate the
|
|
||||||
troops, you have to make goals very challenging. It's really only
|
|
||||||
there to get a stake in the ground, you know. After that we march in
|
|
||||||
step until we reach our objective. The date really doesn't mean
|
|
||||||
anything. You simple have to understand that we are going to do the
|
|
||||||
right thing.") iwshow
|
|
||||||
|
|
||||||
("But the if the goal is impossible, and really doesn't mean anything
|
|
||||||
why are you trying to go there. Wouldn't it be simpler to first figure
|
|
||||||
out what you are really going to do, then figure out how to get there?")
|
|
||||||
iwshow
|
|
||||||
|
|
||||||
("You obviously don't understand the process. And as I said before I'm
|
|
||||||
late so there is obviously only one thing to do.") iwshow
|
|
||||||
|
|
||||||
("Hurry up and rush off?" Alice asked, hoping it would sound more like
|
|
||||||
a suggestion than a question.) iwshow
|
|
||||||
|
|
||||||
("No. No. No. A meeting. Let me find the Mad Manager and a number of
|
|
||||||
involved, interested, or warm bodies.") iwshow
|
|
||||||
|
|
||||||
("That will obviously take a lot of time. I don't think you have any to
|
|
||||||
waste.) iwshow
|
|
||||||
|
|
||||||
("No it won't. All we have to do is find a conference room. There are
|
|
||||||
lots of them right over here.") iwshow
|
|
||||||
|
|
||||||
("But," started Alice, "those rooms are all full of people. Don't we
|
|
||||||
need an empty conference room?") iwshow
|
|
||||||
|
|
||||||
("Silly thought. If we want to find the Mad Manager and some meeting
|
|
||||||
attendees, why would we look in an empty conference room? Anyway, it's
|
|
||||||
impossible to ever find an empty conference room.") iwshow
|
|
||||||
|
|
||||||
(The rabbit took Alice by the hand, and promptly lead her into the
|
|
||||||
largest, fullest conference room. Alice immediately noticed that the
|
|
||||||
wastebasket was quite full of foam cups, and overhead projector bulbs.
|
|
||||||
These people had obviously been here for a long time.) iwshow
|
|
||||||
|
|
||||||
(At the head of the table sat a man with a rather funny suit wearing a
|
|
||||||
large hat.) iwshow
|
|
||||||
|
|
||||||
("Why" whispered Alice to the rabbit, "is that man wearing that funny
|
|
||||||
hat? Who is he?") iwshow
|
|
||||||
|
|
||||||
("I'm the Mad Manager," answered the man at the end of the table,
|
|
||||||
obviously overhearing the question, " And I'll be happy to tell you
|
|
||||||
why I'm wearing this Hat, but that topic is not on the agenda.") iwshow
|
|
||||||
|
|
||||||
("Why don't we change the agenda?" asked a person in the corner.) iwshow
|
|
||||||
|
|
||||||
("Is that a topic for another meeting?" replied the manager.) iwshow
|
|
||||||
|
|
||||||
("Is what a topic for another meeting?" voiced a third. "The reason
|
|
||||||
for the hat, or why we don't change the agenda?") iwshow
|
|
||||||
|
|
||||||
("Why don't we take this off line?" queried another.) iwshow
|
|
||||||
|
|
||||||
("Does everyone agree that these are all topics we should address?"
|
|
||||||
asked the mad manager.) iwshow
|
|
||||||
|
|
||||||
("Possibly so. " injected the person in the corner. "Could it be that
|
|
||||||
we have a hidden agenda?") iwshow
|
|
||||||
|
|
||||||
("Oh no!" the Mad Manager began, the dismay obvious on his face,
|
|
||||||
"someone has hidden the agenda again! Let me put on my process hat and
|
|
||||||
we'll see if we can work this issue.") iwshow
|
|
||||||
|
|
||||||
(With that, he removed his rather amusing top hat, and place a big green
|
|
||||||
fedora on his head.) iwshow
|
|
||||||
|
|
||||||
("Now, with my process hat on, I'd like to address the issue of the
|
|
||||||
hidden agenda. Since we can't have a productive meeting without an
|
|
||||||
agenda, it is up to all of us to find it.") iwshow
|
|
||||||
|
|
||||||
("But, " a voice from the corner piped in, "who is going to drive this
|
|
||||||
issue?") iwshow
|
|
||||||
|
|
||||||
("Do we have an action item here?" asked another attendee.) iwshow
|
|
||||||
|
|
||||||
("Does anyone here want to work this?" asked the mad manager.) iwshow
|
|
||||||
|
|
||||||
("Who originally brought this up?" asked another.) iwshow
|
|
||||||
|
|
||||||
("I believe that the woman who came in with the rabbit proposed this.
|
|
||||||
Shouldn't she own it?") iwshow
|
|
||||||
|
|
||||||
("Well" the Manager stated, pointing to Alice. "I'd say that this is
|
|
||||||
your issue.") iwshow
|
|
||||||
|
|
||||||
("What issue. I don't have any issues. " retorted Alice, nervously
|
|
||||||
fingering her temporary badge. "I only posed a simple question.") iwshow
|
|
||||||
|
|
||||||
("I'm not sure we can accept that," the manager declared. "We need a
|
|
||||||
date.") iwshow
|
|
||||||
|
|
||||||
("But, " Alice began, remembering what the rabbit told her about dates,
|
|
||||||
"a date is impossible.") iwshow
|
|
||||||
|
|
||||||
(From the back of the room another voice asked, "How about a date for a
|
|
||||||
date?") iwshow
|
|
||||||
|
|
||||||
("The least we can ask it that you give us a date when you will be able
|
|
||||||
to give us the date for the date." stated the person in the corner.)
|
|
||||||
iwshow
|
|
||||||
|
|
||||||
("I'm not sure I can do that," Alice opened, "since I don't know what
|
|
||||||
I'm supposed to give you a date for. I'm having a problem trying to
|
|
||||||
figure out what you want me to do.") iwshow
|
|
||||||
|
|
||||||
("We don't have any problems here, only opportunities!" Piped a chorus
|
|
||||||
of voices.) iwshow
|
|
||||||
|
|
||||||
("It's really quite obvious," the mad manager declared as he reached
|
|
||||||
behind him for a striped blue and gray beret, "let me put on my Digital
|
|
||||||
hat for a moment," he continued doffing the fedora and flipping on his
|
|
||||||
latest selection, "You must do the right thing.") iwshow
|
|
||||||
|
|
||||||
("Yes. yes. " chimed the chorus of attendees, "Do the right thing.)
|
|
||||||
iwshow
|
|
||||||
|
|
||||||
("Now, who is keeping the minutes?" the manager asked as he pitched the
|
|
||||||
beret and placed the fedora back on his head. "We need to record this
|
|
||||||
action item so we can come back to it later.") iwshow
|
|
||||||
|
|
||||||
("We obviously can't deal with this issue until we can determine whose
|
|
||||||
meeting this is?") iwshow
|
|
||||||
|
|
||||||
("Should we schedule some time to cover that topic?" asked one of the
|
|
||||||
attendees.) iwshow
|
|
||||||
|
|
||||||
("Whose going to drive this?" asked another.) iwshow
|
|
||||||
|
|
||||||
(Just at the Mad Manager was pulling out a rather worn pith helmet, a
|
|
||||||
voice in the back suggested "Let's take a break and work some of this
|
|
||||||
1x1 off line") iwshow
|
|
||||||
|
|
||||||
(Being closest to the door Alice was the first to leave. She quickly
|
|
||||||
dashed down the hall, and ran up the first flight of stairs she
|
|
||||||
encountered, relieved to be free of the madness.) iwshow
|
|
||||||
|
|
||||||
(When she opened the door the scene that confronted her made her wonder
|
|
||||||
if returning to the meeting wasn't a bad idea. Seated around a large
|
|
||||||
oval table were what appeared to be playing cards, each dressed in a
|
|
||||||
gray or navy blue three piece suit. Around each neck was a rather
|
|
||||||
oddly shaped handle \(or were they nooses?\) made of silk, or polyester.)
|
|
||||||
iwshow
|
|
||||||
|
|
||||||
("Off with her head!" screamed the queen of hearts who was sitting at
|
|
||||||
the head of the table. Alice noticed that her tie was silk, and each
|
|
||||||
card seated near her was dressed in a suit and noose combination
|
|
||||||
similar to the queen's.) iwshow
|
|
||||||
|
|
||||||
("Why would you want to remove my head?" Alice asked. By now she was
|
|
||||||
feeling beyond confused.) iwshow
|
|
||||||
|
|
||||||
("It's not a modern, iconic, user friendly, menu driven, color, PC
|
|
||||||
compatible user interface," replied the queen, in a tone that would
|
|
||||||
need to come up two notches to be vaguely considered condescending.)
|
|
||||||
iwshow
|
|
||||||
|
|
||||||
("It happens to suit me just fine," retorted Alice.) iwshow
|
|
||||||
|
|
||||||
("What are you an engineer or something?" asked the 7 of spades.) iwshow
|
|
||||||
|
|
||||||
("No, I'm Alice. Who are you?") iwshow
|
|
||||||
|
|
||||||
("Marketing." they replied in perfect fifty-two part harmony.) iwshow
|
|
||||||
|
|
||||||
("And what is that?" asked Alice.) iwshow
|
|
||||||
|
|
||||||
(There was a brief interlude of silence as each of the cards fidgeted
|
|
||||||
with their ties, checked their watches and scribbled notes on the pads
|
|
||||||
of paper contained in a handsome genuine imitation leather folder
|
|
||||||
embossed with the company logo. Then one by one, as dominoes would do,
|
|
||||||
they turned to the person on the left until they all stared at the
|
|
||||||
queen of hearts.) iwshow
|
|
||||||
|
|
||||||
(The queen cleared her throat, adjusted her tie a second time and stared
|
|
||||||
directly at Alice. "We provide the strategic thinking necessary to
|
|
||||||
grow the business.") iwshow
|
|
||||||
|
|
||||||
("Oh," said Alice, "you figure out what products to build!") iwshow
|
|
||||||
|
|
||||||
("Heavens, no!" exclaimed the Queen, "That's too tactical. We feel
|
|
||||||
it's our job to develop the vision for the long term.") iwshow
|
|
||||||
|
|
||||||
("You develop things," began Alice, "so you build the products?") iwshow
|
|
||||||
|
|
||||||
(In unison each member of the table made a face reminiscent of the look
|
|
||||||
a small child gets upon tasting spoiled dead roaches for the first
|
|
||||||
time.) iwshow
|
|
||||||
|
|
||||||
("Uggggh, that's even more tactical," jeered the chorus.) iwshow
|
|
||||||
|
|
||||||
("No! No!" shouted the Queen. "You still do not understand. We take
|
|
||||||
the pulse of the key market leaders demand curve.") iwshow
|
|
||||||
|
|
||||||
("I see now." said Alice, "You sell the products.") iwshow
|
|
||||||
|
|
||||||
(By now the chorus of cards chanting "Tac-ti-cal! Tac-ti-cal!" was
|
|
||||||
becoming too much.) iwshow
|
|
||||||
|
|
||||||
(The queen was furious and repeated her original greeting. "Off with
|
|
||||||
her head! Off With her head") iwshow
|
|
||||||
|
|
||||||
("WAIT!" demanded Alice. "I believe I understand. You are all
|
|
||||||
responsible for driving the solution opportunities for the key client
|
|
||||||
supply perceptions through strategic vision management!") iwshow
|
|
||||||
|
|
||||||
(Alice wondered if she should add something about the claws catching,
|
|
||||||
and frumious bandersnatches and thought that she'd best leave it at
|
|
||||||
that before she became ill.) iwshow
|
|
||||||
|
|
||||||
("Yes," screamed the cards, "That's exactly right!") iwshow
|
|
||||||
|
|
||||||
("And how, might I ask, do you accomplish these lofty and important
|
|
||||||
goals?") iwshow
|
|
||||||
|
|
||||||
("By calling a BOD," the queen responded.) iwshow
|
|
||||||
|
|
||||||
("And what, pray tell, might that be?" inquired Alice as she looked for
|
|
||||||
the quickest escape route, hoping that this jabber would keep her head
|
|
||||||
attached long enough to get out.) iwshow
|
|
||||||
|
|
||||||
("A Board of Directors," began the queen, just as Alice noticed the door
|
|
||||||
to the left of the table. "It's a type of high level meeting.") iwshow
|
|
||||||
|
|
||||||
("A meeting????!!!!" exclaimed Alice. "Not another meeting!" With
|
|
||||||
that she bolted for the door, no longer fearing for her head. Her only
|
|
||||||
hope was that she make it through before the agenda hit the overhead.
|
|
||||||
In a dead run, she passed through the door just as the projector lamp
|
|
||||||
flicked on. The sound of the fan was the last sound to fade as the
|
|
||||||
door closed.) iwshow
|
|
||||||
|
|
||||||
(Breathlessly she looked up to see a large open area. Directly in front
|
|
||||||
of her was an enclosed area lined on one side with triple chrome table.
|
|
||||||
A stack of plastic trays was at the foyer.) iwshow
|
|
||||||
|
|
||||||
(As she wandered through an assortment of sandwiches, prepared foods,
|
|
||||||
soft drinks and salad began their daily spiel. "Eat Me! Drink Me! Eat
|
|
||||||
Me!") iwshow
|
|
||||||
|
|
||||||
("Oh no," answered Alice, "I may know nothing about dates, and problems
|
|
||||||
and meetings and agendas, and marketing and badges, but I do know food.
|
|
||||||
I'm not gonna touch any of you. After the morning I've had I deserve a
|
|
||||||
nice cheese steak \(no lettuce\)!") iwshow
|
|
||||||
|
|
||||||
(With that, Alice opened the nearest exit door and left. A resounding
|
|
||||||
high pitched whine sang its midday good-byes as Alice returned to the
|
|
||||||
real world.) iwshow
|
|
||||||
|
|
||||||
showpage
|
|
|
@ -1,111 +0,0 @@
|
||||||
%!PS-Adobe-2.0
|
|
||||||
%%Description: Boilerplate for multi-page banners
|
|
||||||
|
|
||||||
% --- Leave this alone, go to the bottom to start writing stuff ---
|
|
||||||
|
|
||||||
% Define margins
|
|
||||||
/LM 50 def
|
|
||||||
/BM 50 def
|
|
||||||
/RM 580 LM sub def
|
|
||||||
/TM 760 BM sub def
|
|
||||||
|
|
||||||
% font types
|
|
||||||
/times {
|
|
||||||
/font /Times-Roman def
|
|
||||||
} def
|
|
||||||
|
|
||||||
/courier {
|
|
||||||
/font /Courier def
|
|
||||||
} def
|
|
||||||
|
|
||||||
% font sizes
|
|
||||||
/monstrous {
|
|
||||||
/FontSize 312 def
|
|
||||||
/font findfont FontSize scalefont setfont
|
|
||||||
} def
|
|
||||||
|
|
||||||
/huge {
|
|
||||||
/FontSize 288 def
|
|
||||||
font findfont FontSize scalefont setfont
|
|
||||||
} def
|
|
||||||
|
|
||||||
/jumbo {
|
|
||||||
/FontSize 188 def
|
|
||||||
font findfont FontSize scalefont setfont
|
|
||||||
} def
|
|
||||||
|
|
||||||
/large {
|
|
||||||
/FontSize 122 def
|
|
||||||
font findfont FontSize scalefont setfont
|
|
||||||
} def
|
|
||||||
|
|
||||||
|
|
||||||
% Line kerning
|
|
||||||
/smooshed {
|
|
||||||
/Spacing .5 def
|
|
||||||
} def
|
|
||||||
|
|
||||||
/even {
|
|
||||||
/Spacing .75 def
|
|
||||||
} def
|
|
||||||
|
|
||||||
/wide {
|
|
||||||
/Spacing 1 def
|
|
||||||
} def
|
|
||||||
|
|
||||||
% Show text in landscape
|
|
||||||
/lshow {
|
|
||||||
gsave
|
|
||||||
90 rotate
|
|
||||||
show
|
|
||||||
grestore
|
|
||||||
} def
|
|
||||||
|
|
||||||
% start on line 1
|
|
||||||
/offset 0 def
|
|
||||||
|
|
||||||
% Form feed
|
|
||||||
/ff {
|
|
||||||
showpage
|
|
||||||
/offset 0 def
|
|
||||||
} def
|
|
||||||
|
|
||||||
% Line feed (in current font)
|
|
||||||
/lf {
|
|
||||||
/offset offset Spacing FontSize mul add def
|
|
||||||
} def
|
|
||||||
|
|
||||||
% Show top text
|
|
||||||
/disp {
|
|
||||||
lf
|
|
||||||
LM offset add RM gt {
|
|
||||||
ff
|
|
||||||
lf
|
|
||||||
} {
|
|
||||||
} ifelse
|
|
||||||
LM offset add BM moveto
|
|
||||||
lshow
|
|
||||||
} def
|
|
||||||
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
||||||
|
|
||||||
%% Start writing your data here
|
|
||||||
|
|
||||||
% How do you want it to appear?
|
|
||||||
courier jumbo wide
|
|
||||||
|
|
||||||
% Even bigger font: times, letters closely spaced
|
|
||||||
%times huge smooshed
|
|
||||||
|
|
||||||
% Smaller times, normal spacing
|
|
||||||
%times large even
|
|
||||||
|
|
||||||
% Monstrous, the biggest of all
|
|
||||||
%times monstrous smooshed
|
|
||||||
|
|
||||||
(This) disp
|
|
||||||
(is some) disp
|
|
||||||
(really) disp
|
|
||||||
(large) disp
|
|
||||||
(text.) disp
|
|
||||||
ff
|
|
Before Width: | Height: | Size: 26 KiB |
|
@ -1,357 +0,0 @@
|
||||||
%!PS-Adobe-2.0
|
|
||||||
%%Creator: Neale Pickett
|
|
||||||
%%Title: Emergency card
|
|
||||||
%%Pages: 2
|
|
||||||
%%PageOrder: Ascend
|
|
||||||
%%BoundingBox: 50 50 358 294
|
|
||||||
%%EndComments
|
|
||||||
|
|
||||||
% A credit card is 0 0 154 244, this page is twice that so you can fold
|
|
||||||
% it in half. Store phone numbers inside or whatever.
|
|
||||||
|
|
||||||
/RegFont /Times-Roman findfont 8 scalefont def
|
|
||||||
/BoldFont /Times-Bold findfont 8 scalefont def
|
|
||||||
|
|
||||||
RegFont setfont
|
|
||||||
|
|
||||||
/bshow {
|
|
||||||
BoldFont setfont
|
|
||||||
show
|
|
||||||
RegFont setfont
|
|
||||||
} def
|
|
||||||
|
|
||||||
/h1 {
|
|
||||||
/Times-Bold findfont 11 scalefont setfont
|
|
||||||
show
|
|
||||||
RegFont setfont
|
|
||||||
} def
|
|
||||||
|
|
||||||
/nl {
|
|
||||||
currentpoint exch pop 10 exch 10 sub moveto
|
|
||||||
} def
|
|
||||||
|
|
||||||
/tab {
|
|
||||||
currentpoint exch pop moveto
|
|
||||||
} def
|
|
||||||
|
|
||||||
/hl {
|
|
||||||
gsave
|
|
||||||
currentpoint exch pop 10 exch moveto
|
|
||||||
0.3 setlinewidth
|
|
||||||
134 0 rlineto
|
|
||||||
closepath stroke
|
|
||||||
grestore
|
|
||||||
nl
|
|
||||||
} def
|
|
||||||
|
|
||||||
/star-of-life {
|
|
||||||
gsave
|
|
||||||
translate
|
|
||||||
0.13 -0.13 scale
|
|
||||||
[] 0 setdash
|
|
||||||
1 setlinewidth
|
|
||||||
0 setlinejoin
|
|
||||||
0 setlinecap
|
|
||||||
currentrgbcolor % push color
|
|
||||||
gsave [1 0 0 1 0 0] concat
|
|
||||||
gsave
|
|
||||||
1 1 1 setrgbcolor
|
|
||||||
newpath
|
|
||||||
71.9375 6.84375 moveto
|
|
||||||
71.9375 51.09375 lineto
|
|
||||||
33.625 28.96875 lineto
|
|
||||||
8 73.375 lineto
|
|
||||||
46.3125 95.46875 lineto
|
|
||||||
8 117.59375 lineto
|
|
||||||
33.625 162.03125 lineto
|
|
||||||
71.9375 139.90625 lineto
|
|
||||||
71.9375 184.15625 lineto
|
|
||||||
123.25 184.15625 lineto
|
|
||||||
123.25 139.9375 lineto
|
|
||||||
161.53125 162.03125 lineto
|
|
||||||
187.1875 117.59375 lineto
|
|
||||||
148.875 95.5 lineto
|
|
||||||
187.1875 73.375 lineto
|
|
||||||
161.53125 28.96875 lineto
|
|
||||||
123.25 51.0625 lineto
|
|
||||||
123.25 6.84375 lineto
|
|
||||||
71.9375 6.84375 lineto
|
|
||||||
closepath
|
|
||||||
fill
|
|
||||||
grestore
|
|
||||||
setrgbcolor currentrgbcolor
|
|
||||||
[] 0 setdash
|
|
||||||
1.7 setlinewidth
|
|
||||||
0 setlinejoin
|
|
||||||
1 setlinecap
|
|
||||||
newpath
|
|
||||||
71.9375 6.84375 moveto
|
|
||||||
71.9375 51.09375 lineto
|
|
||||||
33.625 28.96875 lineto
|
|
||||||
8 73.375 lineto
|
|
||||||
46.3125 95.46875 lineto
|
|
||||||
8 117.59375 lineto
|
|
||||||
33.625 162.03125 lineto
|
|
||||||
71.9375 139.90625 lineto
|
|
||||||
71.9375 184.15625 lineto
|
|
||||||
123.25 184.15625 lineto
|
|
||||||
123.25 139.9375 lineto
|
|
||||||
161.53125 162.03125 lineto
|
|
||||||
187.1875 117.59375 lineto
|
|
||||||
148.875 95.5 lineto
|
|
||||||
187.1875 73.375 lineto
|
|
||||||
161.53125 28.96875 lineto
|
|
||||||
123.25 51.0625 lineto
|
|
||||||
123.25 6.84375 lineto
|
|
||||||
71.9375 6.84375 lineto
|
|
||||||
closepath
|
|
||||||
stroke
|
|
||||||
gsave
|
|
||||||
setrgbcolor currentrgbcolor
|
|
||||||
newpath
|
|
||||||
75.09375 10 moveto
|
|
||||||
75.09375 56.53125 lineto
|
|
||||||
34.78125 33.25 lineto
|
|
||||||
12.28125 72.21875 lineto
|
|
||||||
52.59375 95.5 lineto
|
|
||||||
12.28125 118.75 lineto
|
|
||||||
34.78125 157.71875 lineto
|
|
||||||
75.09375 134.4375 lineto
|
|
||||||
75.09375 181 lineto
|
|
||||||
120.09375 181 lineto
|
|
||||||
120.09375 134.46875 lineto
|
|
||||||
160.375 157.71875 lineto
|
|
||||||
182.875 118.75 lineto
|
|
||||||
142.5625 95.5 lineto
|
|
||||||
182.875 72.21875 lineto
|
|
||||||
160.375 33.25 lineto
|
|
||||||
120.09375 56.5 lineto
|
|
||||||
120.09375 10 lineto
|
|
||||||
75.09375 10 lineto
|
|
||||||
closepath
|
|
||||||
fill
|
|
||||||
grestore
|
|
||||||
gsave
|
|
||||||
1 1 1 setrgbcolor
|
|
||||||
newpath
|
|
||||||
92.517151 28.749341 moveto
|
|
||||||
92.408986 25.487473 95.364102 22.444786 98.522226 22.444786 curveto
|
|
||||||
100.78169 22.444786 103.56391 24.163507 103.49852 27.028713 curveto
|
|
||||||
102.70837 61.652668 100.60467 131.89502 99.809866 166.84929 curveto
|
|
||||||
99.785836 167.9063 98.454636 167.43783 98.406332 166.35356 curveto
|
|
||||||
96.861909 131.68636 93.680464 63.830863 92.517151 28.749341 curveto
|
|
||||||
closepath
|
|
||||||
eofill
|
|
||||||
grestore
|
|
||||||
setrgbcolor currentrgbcolor
|
|
||||||
[] 0 setdash
|
|
||||||
0.60000002 setlinewidth
|
|
||||||
0 setlinejoin
|
|
||||||
0 setlinecap
|
|
||||||
newpath
|
|
||||||
92.517151 28.749341 moveto
|
|
||||||
92.408986 25.487473 95.364102 22.444786 98.522226 22.444786 curveto
|
|
||||||
100.78169 22.444786 103.56391 24.163507 103.49852 27.028713 curveto
|
|
||||||
102.70837 61.652668 100.60467 131.89502 99.809866 166.84929 curveto
|
|
||||||
99.785836 167.9063 98.454636 167.43783 98.406332 166.35356 curveto
|
|
||||||
96.861909 131.68636 93.680464 63.830863 92.517151 28.749341 curveto
|
|
||||||
closepath
|
|
||||||
stroke
|
|
||||||
gsave
|
|
||||||
1 1 1 setrgbcolor
|
|
||||||
newpath
|
|
||||||
94.036939 33.435356 moveto
|
|
||||||
96.542562 33.435356 97.667652 34.958914 99.217717 36.299367 curveto
|
|
||||||
100.71504 37.594206 101.88918 38.77889 101.88918 40.05277 curveto
|
|
||||||
101.88918 41.391534 100.90645 40.990382 99.865157 41.482074 curveto
|
|
||||||
99.316637 41.74108 99.365585 42.300792 98.469657 42.300792 curveto
|
|
||||||
96.316099 42.300792 95.45867 40.274406 92.51715 40.274406 curveto
|
|
||||||
90.093039 40.274406 86.944591 43.179145 86.944591 48.506596 curveto
|
|
||||||
86.944591 56.552685 90.047493 60.158311 93.720316 62.944591 curveto
|
|
||||||
94.100263 72.506596 lineto
|
|
||||||
90.174142 70.860159 80.042216 61.931473 80.042216 49.519789 curveto
|
|
||||||
80.042216 38.718116 87.055227 33.435356 94.036939 33.435356 curveto
|
|
||||||
closepath
|
|
||||||
eofill
|
|
||||||
grestore
|
|
||||||
setrgbcolor currentrgbcolor
|
|
||||||
[] 0 setdash
|
|
||||||
0.60000002 setlinewidth
|
|
||||||
0 setlinejoin
|
|
||||||
0 setlinecap
|
|
||||||
newpath
|
|
||||||
94.036939 33.435356 moveto
|
|
||||||
96.542562 33.435356 97.667652 34.958914 99.217717 36.299367 curveto
|
|
||||||
100.71504 37.594206 101.88918 38.77889 101.88918 40.05277 curveto
|
|
||||||
101.88918 41.391534 100.90645 40.990382 99.865157 41.482074 curveto
|
|
||||||
99.316637 41.74108 99.365585 42.300792 98.469657 42.300792 curveto
|
|
||||||
96.316099 42.300792 95.45867 40.274406 92.51715 40.274406 curveto
|
|
||||||
90.093039 40.274406 86.944591 43.179145 86.944591 48.506596 curveto
|
|
||||||
86.944591 56.552685 90.047493 60.158311 93.720316 62.944591 curveto
|
|
||||||
94.100263 72.506596 lineto
|
|
||||||
90.174142 70.860159 80.042216 61.931473 80.042216 49.519789 curveto
|
|
||||||
80.042216 38.718116 87.055227 33.435356 94.036939 33.435356 curveto
|
|
||||||
closepath
|
|
||||||
stroke
|
|
||||||
gsave
|
|
||||||
setrgbcolor currentrgbcolor
|
|
||||||
newpath
|
|
||||||
94.986808 36.126649 moveto
|
|
||||||
96.778096 35.842684 96.597917 36.918831 97.39314 37.614775 curveto
|
|
||||||
95.554706 37.669411 95.147378 36.898305 94.986808 36.126649 curveto
|
|
||||||
closepath
|
|
||||||
eofill
|
|
||||||
grestore
|
|
||||||
gsave
|
|
||||||
1 1 1 setrgbcolor
|
|
||||||
newpath
|
|
||||||
102.52243 66.934037 moveto
|
|
||||||
102.26913 76.05277 lineto
|
|
||||||
102.26913 81.62722 87.514512 91.407424 87.514512 101.38259 curveto
|
|
||||||
87.514512 109.06464 93.688655 113.98417 95.968338 115.12401 curveto
|
|
||||||
95.683377 107.08179 lineto
|
|
||||||
95.683377 107.08179 92.897098 105.20276 92.897098 102.01583 curveto
|
|
||||||
92.897098 97.506158 109.86807 85.891676 109.86807 77.002639 curveto
|
|
||||||
109.86807 70.699933 105.56201 68.348285 102.52243 66.934037 curveto
|
|
||||||
closepath
|
|
||||||
eofill
|
|
||||||
grestore
|
|
||||||
setrgbcolor currentrgbcolor
|
|
||||||
[] 0 setdash
|
|
||||||
0.60000002 setlinewidth
|
|
||||||
0 setlinejoin
|
|
||||||
0 setlinecap
|
|
||||||
newpath
|
|
||||||
102.52243 66.934037 moveto
|
|
||||||
102.26913 76.05277 lineto
|
|
||||||
102.26913 81.62722 87.514512 91.407424 87.514512 101.38259 curveto
|
|
||||||
87.514512 109.06464 93.688655 113.98417 95.968338 115.12401 curveto
|
|
||||||
95.683377 107.08179 lineto
|
|
||||||
95.683377 107.08179 92.897098 105.20276 92.897098 102.01583 curveto
|
|
||||||
92.897098 97.506158 109.86807 85.891676 109.86807 77.002639 curveto
|
|
||||||
109.86807 70.699933 105.56201 68.348285 102.52243 66.934037 curveto
|
|
||||||
closepath
|
|
||||||
stroke
|
|
||||||
gsave
|
|
||||||
1 1 1 setrgbcolor
|
|
||||||
newpath
|
|
||||||
101.35093 111.54617 moveto
|
|
||||||
101.35093 111.54617 107.14512 115.37689 107.14512 120.18997 curveto
|
|
||||||
107.14512 124.30746 103.98764 128.07412 100.25762 131.96931 curveto
|
|
||||||
95.900204 136.51968 94.980033 142.21601 97.551452 148.17942 curveto
|
|
||||||
97.773087 153.0554 lineto
|
|
||||||
95.905013 151.53561 92.960422 146.78869 92.960422 138.87071 curveto
|
|
||||||
92.960422 129.33988 101.12929 126.47258 101.12929 117.68866 curveto
|
|
||||||
101.35093 111.54617 lineto
|
|
||||||
closepath
|
|
||||||
eofill
|
|
||||||
grestore
|
|
||||||
setrgbcolor currentrgbcolor
|
|
||||||
[] 0 setdash
|
|
||||||
0.60000002 setlinewidth
|
|
||||||
0 setlinejoin
|
|
||||||
0 setlinecap
|
|
||||||
newpath
|
|
||||||
101.35093 111.54617 moveto
|
|
||||||
101.35093 111.54617 107.14512 115.37689 107.14512 120.18997 curveto
|
|
||||||
107.14512 124.30746 103.98764 128.07412 100.25762 131.96931 curveto
|
|
||||||
95.900204 136.51968 94.980033 142.21601 97.551452 148.17942 curveto
|
|
||||||
97.773087 153.0554 lineto
|
|
||||||
95.905013 151.53561 92.960422 146.78869 92.960422 138.87071 curveto
|
|
||||||
92.960422 129.33988 101.12929 126.47258 101.12929 117.68866 curveto
|
|
||||||
101.35093 111.54617 lineto
|
|
||||||
closepath
|
|
||||||
stroke
|
|
||||||
gsave
|
|
||||||
1 1 1 setrgbcolor
|
|
||||||
newpath
|
|
||||||
100.21108 151.25066 moveto
|
|
||||||
100.21108 151.25066 102.90238 152.69861 102.90238 156.47493 curveto
|
|
||||||
102.90238 160.02958 98.451601 163.27556 97.773087 163.75726 curveto
|
|
||||||
97.11579 164.2239 96.863869 163.61619 97.39314 163.12401 curveto
|
|
||||||
97.939619 162.61583 100.17942 159.61423 100.17942 156.15831 curveto
|
|
||||||
100.21108 151.25066 lineto
|
|
||||||
closepath
|
|
||||||
eofill
|
|
||||||
grestore
|
|
||||||
setrgbcolor
|
|
||||||
[] 0 setdash
|
|
||||||
0.60000002 setlinewidth
|
|
||||||
0 setlinejoin
|
|
||||||
0 setlinecap
|
|
||||||
newpath
|
|
||||||
100.21108 151.25066 moveto
|
|
||||||
100.21108 151.25066 102.90238 152.69861 102.90238 156.47493 curveto
|
|
||||||
102.90238 160.02958 98.451601 163.27556 97.773087 163.75726 curveto
|
|
||||||
97.11579 164.2239 96.863869 163.61619 97.39314 163.12401 curveto
|
|
||||||
97.939619 162.61583 100.17942 159.61423 100.17942 156.15831 curveto
|
|
||||||
100.21108 151.25066 lineto
|
|
||||||
closepath
|
|
||||||
stroke
|
|
||||||
grestore
|
|
||||||
|
|
||||||
|
|
||||||
grestore
|
|
||||||
} def
|
|
||||||
|
|
||||||
%%Page: 1
|
|
||||||
|
|
||||||
% Get away from the edge of the paper
|
|
||||||
50 50 translate
|
|
||||||
|
|
||||||
% Draw some lines for cutting
|
|
||||||
gsave
|
|
||||||
0.9 setgray
|
|
||||||
|
|
||||||
154 0 moveto
|
|
||||||
154 244 lineto
|
|
||||||
closepath stroke
|
|
||||||
|
|
||||||
0 0 moveto
|
|
||||||
308 0 lineto
|
|
||||||
308 244 lineto
|
|
||||||
0 244 lineto
|
|
||||||
closepath stroke
|
|
||||||
grestore
|
|
||||||
|
|
||||||
125 240 star-of-life
|
|
||||||
|
|
||||||
10 230 moveto
|
|
||||||
(Name) bshow 50 tab (John Smith) show nl
|
|
||||||
(Address) bshow 50 tab (21 Jump Street) show nl
|
|
||||||
50 tab (New York, NY USA) show nl
|
|
||||||
|
|
||||||
nl
|
|
||||||
30 tab (Notify In Emergency) h1 hl
|
|
||||||
|
|
||||||
(Name) bshow 50 tab (Sally Smith) show nl
|
|
||||||
50 tab (+1 800-555-1212) show nl
|
|
||||||
(Name) bshow 50 tab (Joseph Smith) show nl
|
|
||||||
50 tab (+1 800-555-1212) show nl
|
|
||||||
(Doctor) bshow 50 tab (Mahatma Ghandi) show nl
|
|
||||||
50 tab (+1 800-555-1212) show nl
|
|
||||||
|
|
||||||
hl
|
|
||||||
|
|
||||||
(Conditions) bshow 50 tab (None) show nl
|
|
||||||
(Allergies) bshow 50 tab (None) show nl
|
|
||||||
(Meds) bshow 50 tab (None) show nl
|
|
||||||
(Blood) bshow 50 tab (A+++) show
|
|
||||||
70 tab (I'm an Organ Donor!) bshow
|
|
||||||
|
|
||||||
% Next page
|
|
||||||
154 0 translate
|
|
||||||
|
|
||||||
5 240 star-of-life
|
|
||||||
|
|
||||||
40 225 moveto
|
|
||||||
(info on other side) h1 nl
|
|
||||||
nl
|
|
||||||
nl
|
|
||||||
(You can put whatever you want here.) show nl
|
|
||||||
|
|
||||||
showpage
|
|
||||||
|
|
||||||
% Local Variables:
|
|
||||||
% mode: ps
|
|
||||||
% End:
|
|
|
@ -1,32 +0,0 @@
|
||||||
%!PS-Adobe-3.0
|
|
||||||
%%Title: A sheet of graph paper
|
|
||||||
%%Creator: Neale Pickett
|
|
||||||
%%CreationDate: Sun Oct 20 17:10:42 2002
|
|
||||||
%%EndComments
|
|
||||||
|
|
||||||
64 dict begin
|
|
||||||
|
|
||||||
% How wide do you want the cells to be? (in mm)
|
|
||||||
/l 5 def
|
|
||||||
|
|
||||||
% How light should the lines be? 0.0 is black, 1.0 is white (no lines).
|
|
||||||
0.9 setgray
|
|
||||||
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
||||||
% You don't need to change anything below here
|
|
||||||
|
|
||||||
% One millimeter in points
|
|
||||||
/mm 2.8452756 def
|
|
||||||
|
|
||||||
0 l mm mul 900 {
|
|
||||||
dup 0 moveto
|
|
||||||
0 900 rlineto
|
|
||||||
|
|
||||||
0 exch moveto
|
|
||||||
900 0 rlineto
|
|
||||||
} for
|
|
||||||
stroke
|
|
||||||
|
|
||||||
end
|
|
||||||
showpage
|
|
||||||
%%EOF
|
|
|
@ -1,5 +0,0 @@
|
||||||
Title: PostScript Hacks
|
|
||||||
|
|
||||||
One morning I woke up wondering, "how difficult could PostScript really be?"
|
|
||||||
|
|
||||||
Answer: Not very.
|
|
|
@ -1,34 +0,0 @@
|
||||||
%!PS-Adobe-3.0 EPSF-3.0
|
|
||||||
%%BoundingBox: 0 0 612 792
|
|
||||||
%%Title: Some functions to make PostScript feel like LOGO
|
|
||||||
%%Creator: Neale Pickett
|
|
||||||
%%CreationDate: Tue Oct 22 09:23:22 2002
|
|
||||||
%%EndComments
|
|
||||||
|
|
||||||
64 dict begin
|
|
||||||
/pen true def
|
|
||||||
/pu { /pen false def } def
|
|
||||||
/pd { /pen true def } def
|
|
||||||
/fd { /l exch def pen { 0 l rlineto } { 0 l rmoveto } ifelse } def
|
|
||||||
/rt { rotate } def
|
|
||||||
/lt { -1 mul rotate } def
|
|
||||||
/home { 306 496 moveto } def
|
|
||||||
home
|
|
||||||
|
|
||||||
%% Your LOGO-like program starts here
|
|
||||||
|
|
||||||
% a square
|
|
||||||
40 fd
|
|
||||||
90 rt
|
|
||||||
40 fd
|
|
||||||
90 rt
|
|
||||||
40 fd
|
|
||||||
90 rt
|
|
||||||
40 fd
|
|
||||||
stroke
|
|
||||||
|
|
||||||
%% Your LOGO-like program ends here
|
|
||||||
|
|
||||||
end
|
|
||||||
showpage
|
|
||||||
%%EOF
|
|
|
@ -1,117 +0,0 @@
|
||||||
%!PS-Adobe-2.0
|
|
||||||
%Description: Displays dimensions of the page, and where your printer clips.
|
|
||||||
|
|
||||||
/TM 792 def
|
|
||||||
/RM 612 def
|
|
||||||
|
|
||||||
/margin 18 def
|
|
||||||
/linelen 18 def
|
|
||||||
|
|
||||||
/step 18 def
|
|
||||||
|
|
||||||
|
|
||||||
.1 setlinewidth
|
|
||||||
/ruler {
|
|
||||||
newpath
|
|
||||||
|
|
||||||
0 0 moveto
|
|
||||||
0 1 18 {
|
|
||||||
0 6 rlineto
|
|
||||||
1 -6 rmoveto
|
|
||||||
} for
|
|
||||||
|
|
||||||
0 0 moveto
|
|
||||||
0 3 18 {
|
|
||||||
0 12 rlineto
|
|
||||||
3 -12 rmoveto
|
|
||||||
} for
|
|
||||||
|
|
||||||
9 0 moveto
|
|
||||||
0 15 rlineto
|
|
||||||
|
|
||||||
0 0 moveto
|
|
||||||
0 18 rlineto
|
|
||||||
18 0 moveto
|
|
||||||
0 18 rlineto
|
|
||||||
|
|
||||||
stroke
|
|
||||||
} def
|
|
||||||
|
|
||||||
|
|
||||||
/Times-Roman findfont 10 scalefont setfont
|
|
||||||
|
|
||||||
|
|
||||||
/str 20 string def
|
|
||||||
0 step TM {
|
|
||||||
dup dup
|
|
||||||
margin exch
|
|
||||||
gsave
|
|
||||||
translate
|
|
||||||
|
|
||||||
0 0 moveto
|
|
||||||
step 2 mul le {
|
|
||||||
pop
|
|
||||||
} {
|
|
||||||
18 0 rmoveto
|
|
||||||
str cvs str show
|
|
||||||
} ifelse
|
|
||||||
0 18 translate
|
|
||||||
-90 rotate
|
|
||||||
ruler
|
|
||||||
|
|
||||||
grestore
|
|
||||||
} for
|
|
||||||
|
|
||||||
/str 20 string def
|
|
||||||
newpath
|
|
||||||
0 step RM {
|
|
||||||
dup dup
|
|
||||||
margin
|
|
||||||
gsave
|
|
||||||
translate
|
|
||||||
0 0 moveto
|
|
||||||
|
|
||||||
step 2 mul le {
|
|
||||||
pop
|
|
||||||
} {
|
|
||||||
0 18 rmoveto
|
|
||||||
str cvs str show
|
|
||||||
} ifelse
|
|
||||||
ruler
|
|
||||||
grestore
|
|
||||||
} for
|
|
||||||
|
|
||||||
1 setlinewidth
|
|
||||||
|
|
||||||
% Score 1" in on all sides
|
|
||||||
newpath
|
|
||||||
|
|
||||||
72 0 moveto
|
|
||||||
0 36 rlineto
|
|
||||||
|
|
||||||
72 TM moveto
|
|
||||||
0 -36 rlineto
|
|
||||||
|
|
||||||
RM 72 sub 0 moveto
|
|
||||||
0 36 rlineto
|
|
||||||
|
|
||||||
RM 72 sub TM moveto
|
|
||||||
0 -36 rlineto
|
|
||||||
|
|
||||||
|
|
||||||
0 72 moveto
|
|
||||||
36 0 rlineto
|
|
||||||
|
|
||||||
RM 72 moveto
|
|
||||||
-36 0 rlineto
|
|
||||||
|
|
||||||
0 TM 72 sub moveto
|
|
||||||
36 0 rlineto
|
|
||||||
|
|
||||||
RM TM 72 sub moveto
|
|
||||||
-37 0 rlineto
|
|
||||||
|
|
||||||
stroke
|
|
||||||
|
|
||||||
|
|
||||||
showpage
|
|
|
@ -1,95 +0,0 @@
|
||||||
%!PS-Adobe-3.0
|
|
||||||
%%Title: A sheet of ruled paper
|
|
||||||
%%Creator: Neale Pickett
|
|
||||||
%%CreationDate: Sun Oct 20 17:10:42 2002
|
|
||||||
%%Pages: 1
|
|
||||||
%%BoundingBox: 0 0 612 792
|
|
||||||
%%EndComments
|
|
||||||
|
|
||||||
|
|
||||||
% Body height (in mm)
|
|
||||||
% 9 - big chief
|
|
||||||
% 5 - wide
|
|
||||||
% 4 - average
|
|
||||||
% 3 - teensy
|
|
||||||
/bh 9 def
|
|
||||||
|
|
||||||
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
||||||
% You don't need to change anything below here
|
|
||||||
|
|
||||||
|
|
||||||
% How much additional space between lines (mm)?
|
|
||||||
/ls 0 def
|
|
||||||
|
|
||||||
% Show waist line?
|
|
||||||
/wl true def
|
|
||||||
|
|
||||||
% Show ascenders and descenders?
|
|
||||||
/ad false def
|
|
||||||
|
|
||||||
9 bh le {
|
|
||||||
/ls 4 def
|
|
||||||
/wl true def
|
|
||||||
/ad true def
|
|
||||||
} if
|
|
||||||
|
|
||||||
5 bh eq {
|
|
||||||
/ls 2 def
|
|
||||||
} if
|
|
||||||
|
|
||||||
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
||||||
% You really don't need to change anything below here
|
|
||||||
|
|
||||||
% One millimeter in points
|
|
||||||
/mm 2.8452756 def
|
|
||||||
|
|
||||||
% Distance from baseline to baseline, in points
|
|
||||||
/lp bh 2 mul ls add mm mul def
|
|
||||||
|
|
||||||
% Body height, in points
|
|
||||||
/bp bh mm mul def
|
|
||||||
|
|
||||||
792 lp sub lp neg 0 {
|
|
||||||
20 exch moveto
|
|
||||||
|
|
||||||
ad {
|
|
||||||
% ascender and descender
|
|
||||||
gsave
|
|
||||||
0.9 setgray
|
|
||||||
0 bp 2 div rmoveto
|
|
||||||
900 0 rlineto
|
|
||||||
-900 bp rmoveto
|
|
||||||
900 0 rlineto
|
|
||||||
stroke
|
|
||||||
grestore
|
|
||||||
} if
|
|
||||||
|
|
||||||
% waist line
|
|
||||||
wl {
|
|
||||||
gsave
|
|
||||||
0.7 setgray
|
|
||||||
0 bp rmoveto
|
|
||||||
900 0 rlineto
|
|
||||||
stroke
|
|
||||||
grestore
|
|
||||||
} if
|
|
||||||
|
|
||||||
% left margin
|
|
||||||
gsave
|
|
||||||
0.3 setgray
|
|
||||||
0 bp rlineto
|
|
||||||
stroke
|
|
||||||
grestore
|
|
||||||
|
|
||||||
% base line
|
|
||||||
gsave
|
|
||||||
0.3 setgray
|
|
||||||
900 0 rlineto
|
|
||||||
stroke
|
|
||||||
grestore
|
|
||||||
} for
|
|
||||||
|
|
||||||
showpage
|
|
||||||
%%EOF
|
|
|
@ -1,273 +0,0 @@
|
||||||
%!PS-Adobe-2.0
|
|
||||||
%%Title: Skeleton for typesetting in PostScript.
|
|
||||||
%%Creator: Neale Pickett <neale@lanl.gov>
|
|
||||||
%%CreationDate: Thu Nov 22 15:27:53 MST 1998
|
|
||||||
%% Time-stamp: <2002-10-22 09:34:13 neale>
|
|
||||||
%%EndComments
|
|
||||||
|
|
||||||
/FontSize 12 def
|
|
||||||
|
|
||||||
/RegFont /Times-Roman def
|
|
||||||
/BoldFont /Times-Bold def
|
|
||||||
/ItalFont /Times-Italic def
|
|
||||||
|
|
||||||
/RegFSet RegFont findfont FontSize scalefont def
|
|
||||||
/BoldFSet BoldFont findfont FontSize scalefont def
|
|
||||||
/HeadFSet BoldFont findfont FontSize 1.1 mul scalefont def
|
|
||||||
/ItalFSet ItalFont findfont FontSize scalefont def
|
|
||||||
|
|
||||||
/SetRegFont { RegFSet setfont } def
|
|
||||||
/SetBoldFont { BoldFSet setfont } def
|
|
||||||
/SetHeadFont { HeadFSet setfont } def
|
|
||||||
/SetItalFont { ItalFSet setfont } def
|
|
||||||
|
|
||||||
/LM 50 def
|
|
||||||
/BM 50 def
|
|
||||||
/RM 580 LM sub def
|
|
||||||
/TM 760 BM sub def
|
|
||||||
|
|
||||||
/indentLevel 30 def
|
|
||||||
|
|
||||||
% Re-set the margins
|
|
||||||
/reset_margins {
|
|
||||||
/lm LM def
|
|
||||||
/rm RM def
|
|
||||||
} def
|
|
||||||
|
|
||||||
reset_margins
|
|
||||||
|
|
||||||
% Move down just a little
|
|
||||||
/down {
|
|
||||||
reset_margins
|
|
||||||
lm indentation add currentpoint exch pop
|
|
||||||
FontSize 3 div sub
|
|
||||||
moveto
|
|
||||||
} def
|
|
||||||
|
|
||||||
% Move to the next line
|
|
||||||
/next {
|
|
||||||
reset_margins
|
|
||||||
lm indentation add currentpoint exch pop % LM Y
|
|
||||||
FontSize 1.1 mul sub % LM Y'
|
|
||||||
moveto
|
|
||||||
currentpoint exch pop
|
|
||||||
BM lt {
|
|
||||||
showpage
|
|
||||||
LM TM moveto
|
|
||||||
} {} ifelse
|
|
||||||
} def
|
|
||||||
|
|
||||||
% Move to the previous line
|
|
||||||
/prev {
|
|
||||||
lm indentation add currentpoint exch pop % LM Y
|
|
||||||
FontSize 1.1 mul add % LM Y'
|
|
||||||
moveto
|
|
||||||
} def
|
|
||||||
|
|
||||||
% Re-align the indentation
|
|
||||||
/align {
|
|
||||||
lm indentation add currentpoint exch pop moveto
|
|
||||||
} def
|
|
||||||
|
|
||||||
% Indent once
|
|
||||||
/indentation 0 def
|
|
||||||
/indent {
|
|
||||||
/indentation indentation indentLevel add def
|
|
||||||
align
|
|
||||||
} def
|
|
||||||
|
|
||||||
% Deindent
|
|
||||||
/deindent {
|
|
||||||
/indentation indentation indentLevel sub def
|
|
||||||
align
|
|
||||||
} def
|
|
||||||
|
|
||||||
% Show left justified
|
|
||||||
/lshow {
|
|
||||||
gsave
|
|
||||||
% Set the left margin
|
|
||||||
dup
|
|
||||||
stringwidth pop
|
|
||||||
LM add
|
|
||||||
/lm exch def
|
|
||||||
|
|
||||||
currentpoint exch pop % (str) Y
|
|
||||||
LM exch % (str) x Y
|
|
||||||
moveto show
|
|
||||||
grestore
|
|
||||||
} def
|
|
||||||
|
|
||||||
% Show centered
|
|
||||||
/cshow {
|
|
||||||
gsave
|
|
||||||
dup % (str) (str)
|
|
||||||
stringwidth pop % (str) x
|
|
||||||
2 div % (str) x/2
|
|
||||||
RM LM sub 2 div % (str) x/2 RM/2
|
|
||||||
exch sub LM add % (str) x'
|
|
||||||
currentpoint exch pop % (str) x' Y
|
|
||||||
moveto show
|
|
||||||
grestore
|
|
||||||
} def
|
|
||||||
|
|
||||||
% Show right justified
|
|
||||||
/rshow {
|
|
||||||
gsave
|
|
||||||
dup % (str) (str)
|
|
||||||
stringwidth pop % (str) x
|
|
||||||
|
|
||||||
% set the right margin
|
|
||||||
dup
|
|
||||||
RM exch sub padwidth sub
|
|
||||||
/rm exch def
|
|
||||||
|
|
||||||
RM exch sub % (str) x'
|
|
||||||
currentpoint exch pop % (str) x' Y
|
|
||||||
moveto show
|
|
||||||
grestore
|
|
||||||
} def
|
|
||||||
|
|
||||||
% Show in a bold font
|
|
||||||
/bshow {
|
|
||||||
SetBoldFont
|
|
||||||
show
|
|
||||||
SetRegFont
|
|
||||||
} def
|
|
||||||
|
|
||||||
% Show in a italics font
|
|
||||||
/ishow {
|
|
||||||
SetItalFont
|
|
||||||
show
|
|
||||||
SetRegFont
|
|
||||||
} def
|
|
||||||
|
|
||||||
% Special parsing stuff; returns true if it's a printing character
|
|
||||||
/parse_special {
|
|
||||||
/word exch def
|
|
||||||
(<b>) word eq {
|
|
||||||
SetBoldFont
|
|
||||||
false
|
|
||||||
} {
|
|
||||||
(<i>) word eq {
|
|
||||||
SetItalFont
|
|
||||||
false
|
|
||||||
} {
|
|
||||||
(<r>) word eq {
|
|
||||||
SetRegFont
|
|
||||||
false
|
|
||||||
} {
|
|
||||||
true
|
|
||||||
} ifelse
|
|
||||||
} ifelse
|
|
||||||
} ifelse
|
|
||||||
} def
|
|
||||||
|
|
||||||
% I totally stole this out of the blue book. But I changed it a lot, so
|
|
||||||
% you might not recognize it if not for the name.
|
|
||||||
/wordbreak ( ) def
|
|
||||||
/BreakIntoLines {
|
|
||||||
/proc exch def
|
|
||||||
/linelength exch def
|
|
||||||
/textstring exch def
|
|
||||||
/curwidth exch def
|
|
||||||
|
|
||||||
/breakwidth wordbreak stringwidth pop def
|
|
||||||
/lastwordbreak 0 def
|
|
||||||
|
|
||||||
/startchar 0 def
|
|
||||||
/restoftext textstring def
|
|
||||||
|
|
||||||
SetRegFont
|
|
||||||
{
|
|
||||||
restoftext wordbreak search
|
|
||||||
|
|
||||||
{
|
|
||||||
/done false def
|
|
||||||
} {
|
|
||||||
() exch
|
|
||||||
wordbreak exch
|
|
||||||
/done true def
|
|
||||||
} ifelse
|
|
||||||
|
|
||||||
/nextword exch def pop
|
|
||||||
/restoftext exch def
|
|
||||||
|
|
||||||
nextword parse_special {
|
|
||||||
/wordwidth nextword stringwidth pop def
|
|
||||||
curwidth wordwidth add linelength gt
|
|
||||||
{
|
|
||||||
% This word should go on the next line
|
|
||||||
proc
|
|
||||||
/curwidth exch def
|
|
||||||
} if
|
|
||||||
|
|
||||||
/curwidth curwidth wordwidth add
|
|
||||||
breakwidth add def
|
|
||||||
nextword show
|
|
||||||
wordbreak show
|
|
||||||
|
|
||||||
/lastwordbreak lastwordbreak
|
|
||||||
nextword length add 1 add def
|
|
||||||
|
|
||||||
done {
|
|
||||||
exit
|
|
||||||
} {
|
|
||||||
} ifelse
|
|
||||||
} if
|
|
||||||
} loop
|
|
||||||
/lastchar textstring length def
|
|
||||||
textstring startchar lastchar startchar sub
|
|
||||||
getinterval proc
|
|
||||||
} def
|
|
||||||
|
|
||||||
% Show some text, and word-wrap it if necessary, then move to the next line
|
|
||||||
/wshow {
|
|
||||||
0 exch
|
|
||||||
/x currentpoint pop def
|
|
||||||
rm x sub % Line length
|
|
||||||
{
|
|
||||||
next
|
|
||||||
x currentpoint exch pop moveto
|
|
||||||
0
|
|
||||||
}
|
|
||||||
BreakIntoLines
|
|
||||||
} def
|
|
||||||
|
|
||||||
% Show indented, wrapped text
|
|
||||||
/iwshow {
|
|
||||||
indentLevel exch
|
|
||||||
/x currentpoint pop def
|
|
||||||
rm x sub
|
|
||||||
indentLevel 0 rmoveto
|
|
||||||
{
|
|
||||||
next
|
|
||||||
x currentpoint exch pop moveto
|
|
||||||
0
|
|
||||||
}
|
|
||||||
BreakIntoLines
|
|
||||||
} def
|
|
||||||
|
|
||||||
% Show inverse-indented, wrapped text
|
|
||||||
/iiwshow {
|
|
||||||
indentLevel neg exch
|
|
||||||
/x currentpoint pop indentLevel add def
|
|
||||||
rm x sub
|
|
||||||
{
|
|
||||||
next
|
|
||||||
x currentpoint exch pop moveto
|
|
||||||
0
|
|
||||||
}
|
|
||||||
BreakIntoLines
|
|
||||||
indentLevel neg 0 rmoveto
|
|
||||||
} def
|
|
||||||
|
|
||||||
|
|
||||||
LM TM moveto
|
|
||||||
SetRegFont
|
|
||||||
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
||||||
% Content goes here ;-)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
showpage
|
|
|
@ -1,4 +0,0 @@
|
||||||
Title: pysieved: Python Managesieve Server
|
|
||||||
|
|
||||||
pysieved is a GPL managesieve server. It is now hosted on gitorious, at
|
|
||||||
<http://www.gitorious.net/pysieved/pages/Home>.
|
|
|
@ -1 +0,0 @@
|
||||||
../pysieved.mdwn
|
|
|
@ -1,100 +0,0 @@
|
||||||
#! /usr/bin/env python
|
|
||||||
|
|
||||||
## htmlpp -- Python HTML/CSS pretty-printer
|
|
||||||
##
|
|
||||||
## Thanks to ActiveState's ASPN (which rules, thanks guys) for leading
|
|
||||||
## me to this idea. AFAIK, they got the idea from MoinMoin.
|
|
||||||
##
|
|
||||||
## This is a part of epy: http://woozle.org/~neale/src/epy/
|
|
||||||
|
|
||||||
from __future__ import generators
|
|
||||||
import cgi
|
|
||||||
import sys
|
|
||||||
import keyword
|
|
||||||
import token
|
|
||||||
import tokenize
|
|
||||||
|
|
||||||
def prettyprint(fd):
|
|
||||||
"""Pretty print code into HTML/CSS.
|
|
||||||
|
|
||||||
This returns a generator, which generates tokens to be printed to
|
|
||||||
some HTML document. You'll need to define a style sheet to get the
|
|
||||||
colors you like.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
end = (0, 0)
|
|
||||||
last = (None,) * 5
|
|
||||||
for tok in tokenize.generate_tokens(fd.readline):
|
|
||||||
start = tok[2]
|
|
||||||
if start[1] != end[1]:
|
|
||||||
if start[0] != end[0]:
|
|
||||||
# What to do here? Punt.
|
|
||||||
yield '\n<strong>prettyprint punting: %s %s</strong>\n' % (tok, end)
|
|
||||||
else:
|
|
||||||
yield tok[4][end[1]:start[1]]
|
|
||||||
end = tok[3]
|
|
||||||
if end[1] == len(tok[4]):
|
|
||||||
# Prevent punting on newlines
|
|
||||||
end = (end[0] + 1, 0)
|
|
||||||
if tok[0] == token.NAME:
|
|
||||||
if keyword.iskeyword(tok[1]):
|
|
||||||
style = 'KEYWORD'
|
|
||||||
elif last[1] in ('class', 'def'):
|
|
||||||
style = 'FUNCTION'
|
|
||||||
else:
|
|
||||||
style = 'NAME'
|
|
||||||
else:
|
|
||||||
style = token.tok_name.get(tok[0])
|
|
||||||
s = tok[1].expandtabs()
|
|
||||||
txt = cgi.escape(s)
|
|
||||||
if style:
|
|
||||||
last = tok
|
|
||||||
yield ('<span class="%s">%s</span>'
|
|
||||||
% (style, txt))
|
|
||||||
else:
|
|
||||||
yield s
|
|
||||||
|
|
||||||
def pp_fd(f, out=sys.stdout):
|
|
||||||
"""Pretty print a file object."""
|
|
||||||
|
|
||||||
for item in prettyprint(f):
|
|
||||||
out.write(item)
|
|
||||||
|
|
||||||
def pp_file(filename, out=sys.stdout):
|
|
||||||
"""Pretty print a filename.
|
|
||||||
|
|
||||||
Open and pretty-print python source in filename. Output goes to out
|
|
||||||
(default, sys.stdout).
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
pp_fd(open(filename), out)
|
|
||||||
|
|
||||||
def pp_string(string, out=sys.stdout):
|
|
||||||
"""Pretty print a string."""
|
|
||||||
|
|
||||||
import cStringIO as StringIO
|
|
||||||
|
|
||||||
f = StringIO.StringIO(string)
|
|
||||||
pp_fd(f, out)
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
import sys
|
|
||||||
|
|
||||||
print '''<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
|
|
||||||
"http://www.w3.org/TR/html4/strict.dtd">
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>Bee-yoo-ti-ful source code</title>
|
|
||||||
<link rel="stylesheet" type="text/css"
|
|
||||||
href="http://woozle.org/~neale/default.css">
|
|
||||||
</head>
|
|
||||||
<body>'''
|
|
||||||
print '<pre>'
|
|
||||||
# write colorized version to stdout
|
|
||||||
for item in prettyprint(sys.stdin):
|
|
||||||
sys.stdout.write(item)
|
|
||||||
print '</pre></body></html>'
|
|
||||||
|
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
Title: Python hacks
|
|
||||||
|
|
||||||
Here's some junk I did in Python.
|
|
|
@ -1,42 +0,0 @@
|
||||||
#! /usr/bin/env python
|
|
||||||
|
|
||||||
# Description: Knuth-Morris-Pratt algorithm
|
|
||||||
|
|
||||||
"""Knuth-Morris-Pratt algorithm
|
|
||||||
|
|
||||||
This is a direct transaltion of the KMP algorithm in the book
|
|
||||||
"Introduction to Algorithms" by Cormen, Lieserson, and Rivest. See that
|
|
||||||
book for an explanation of why this algorithm works. It's pretty cool.
|
|
||||||
|
|
||||||
The only things I changed were some offsets, to cope with the fact that
|
|
||||||
Python arrays are 0-offset.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
__author__ = 'Neale Pickett <neale@woozle.org>'
|
|
||||||
|
|
||||||
def compute_prefix_function(p):
|
|
||||||
m = len(p)
|
|
||||||
pi = [0] * m
|
|
||||||
k = 0
|
|
||||||
for q in range(1, m):
|
|
||||||
while k > 0 and p[k] != p[q]:
|
|
||||||
k = pi[k - 1]
|
|
||||||
if p[k] == p[q]:
|
|
||||||
k = k + 1
|
|
||||||
pi[q] = k
|
|
||||||
return pi
|
|
||||||
|
|
||||||
def kmp_matcher(t, p):
|
|
||||||
n = len(t)
|
|
||||||
m = len(p)
|
|
||||||
pi = compute_prefix_function(p)
|
|
||||||
q = 0
|
|
||||||
for i in range(n):
|
|
||||||
while q > 0 and p[q] != t[i]:
|
|
||||||
q = pi[q - 1]
|
|
||||||
if p[q] == t[i]:
|
|
||||||
q = q + 1
|
|
||||||
if q == m:
|
|
||||||
return i - m + 1
|
|
||||||
return -1
|
|
|
@ -1,68 +0,0 @@
|
||||||
#! /usr/bin/python
|
|
||||||
|
|
||||||
## cronit -- A lightweight (aka "lousy") anacron replacement
|
|
||||||
## Copyright (C) 2007 Neale Pickett
|
|
||||||
##
|
|
||||||
## This program is free software: you can redistribute it and/or modify
|
|
||||||
## it under the terms of the GNU General Public License as published by
|
|
||||||
## the Free Software Foundation, either version 3 of the License, or (at
|
|
||||||
## your option) any later version.
|
|
||||||
##
|
|
||||||
## This program is distributed in the hope that it will be useful, but
|
|
||||||
## WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
## General Public License for more details.
|
|
||||||
##
|
|
||||||
## You should have received a copy of the GNU General Public License
|
|
||||||
## along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
import time
|
|
||||||
import os
|
|
||||||
import popen2
|
|
||||||
import socket
|
|
||||||
|
|
||||||
basedir = os.path.expanduser('~/lib/cron')
|
|
||||||
|
|
||||||
os.chdir(os.path.expanduser('~'))
|
|
||||||
|
|
||||||
now = time.time()
|
|
||||||
periods = (('test', -1),
|
|
||||||
('hourly', 3600),
|
|
||||||
('daily', 86400),
|
|
||||||
('weekly', 604800),
|
|
||||||
('monthly', 18144000), # more or less
|
|
||||||
('yearly', 2204892000))
|
|
||||||
|
|
||||||
def run_parts(dir):
|
|
||||||
out = []
|
|
||||||
for script in os.listdir(dir):
|
|
||||||
if script.endswith('~') or script.startswith('.'):
|
|
||||||
continue
|
|
||||||
fn = os.path.join(dir, script)
|
|
||||||
proc = popen2.Popen4(fn)
|
|
||||||
proc.tochild.close()
|
|
||||||
outstr = proc.fromchild.read()
|
|
||||||
ret = proc.wait()
|
|
||||||
if outstr or ret:
|
|
||||||
out.append((fn, outstr, ret))
|
|
||||||
return out
|
|
||||||
|
|
||||||
def cronit(basedir):
|
|
||||||
for name, interval in periods:
|
|
||||||
dir = os.path.join(basedir, name)
|
|
||||||
if not os.path.exists(dir):
|
|
||||||
continue
|
|
||||||
tsfile = os.path.join(dir, '.timestamp.%s' % socket.gethostname())
|
|
||||||
try:
|
|
||||||
ts = int(file(tsfile).read().strip())
|
|
||||||
except:
|
|
||||||
ts = 0
|
|
||||||
if ts + interval < now:
|
|
||||||
problems = run_parts(dir)
|
|
||||||
file(tsfile, 'w').write('%d\n' % now)
|
|
||||||
for script, output, ret in problems:
|
|
||||||
print '====== %s exited with code %d' % (script, ret/256)
|
|
||||||
print output
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
cronit(basedir)
|
|
|
@ -1,46 +0,0 @@
|
||||||
# maildir.py -- Maildir utilities
|
|
||||||
#
|
|
||||||
# Released into the public domain
|
|
||||||
|
|
||||||
"""Maildir utilities"""
|
|
||||||
|
|
||||||
__author__ = 'Neale Pickett <neale@woozle.org>'
|
|
||||||
|
|
||||||
import os
|
|
||||||
import socket
|
|
||||||
import time
|
|
||||||
|
|
||||||
# Counter gets incremented by one for every message delivered
|
|
||||||
count = 0
|
|
||||||
|
|
||||||
# Local hostname
|
|
||||||
HOST = socket.gethostname()
|
|
||||||
|
|
||||||
def create(mdir):
|
|
||||||
os.umask(0022)
|
|
||||||
for i in ('tmp', 'cur', 'new'):
|
|
||||||
os.makedirs('%s/%s' % (mdir, i))
|
|
||||||
|
|
||||||
def write(mdir, message, info=None):
|
|
||||||
"""Write a message out to a maildir.
|
|
||||||
|
|
||||||
"""
|
|
||||||
global count
|
|
||||||
|
|
||||||
mdir = time.strftime('%Y-%m')
|
|
||||||
if not os.path.exists(mdir):
|
|
||||||
maildir_create(mdir)
|
|
||||||
|
|
||||||
filename = '%d.%d_%04d.%s' % (time.time(), os.getpid(),
|
|
||||||
count, HOST)
|
|
||||||
f = open('%s/tmp/%s' % (mdir, filename),
|
|
||||||
'w')
|
|
||||||
f.write(message)
|
|
||||||
f.close()
|
|
||||||
if info:
|
|
||||||
os.rename('%s/tmp/%s' % (mdir, filename),
|
|
||||||
'%s/cur/%s:2,%s' % (mdir, filename, info))
|
|
||||||
else:
|
|
||||||
os.rename('%s/tmp/%s' % (mdir, filename),
|
|
||||||
'%s/new/%s' % (mdir, filename))
|
|
||||||
count += 1
|
|
|
@ -1,54 +0,0 @@
|
||||||
#! /usr/bin/python
|
|
||||||
|
|
||||||
### ndstrunc -- Trims .nds ROM files
|
|
||||||
|
|
||||||
|
|
||||||
import struct
|
|
||||||
import optparse
|
|
||||||
import os
|
|
||||||
|
|
||||||
parser = optparse.OptionParser(description='Trims .nds ROM files.')
|
|
||||||
parser.add_option('-d', '--dry-run',
|
|
||||||
action='store_false', dest='writeout', default=True,
|
|
||||||
help="Don't actually modify any files.")
|
|
||||||
parser.add_option('-f', '--force',
|
|
||||||
action='store_true', dest='force', default=False,
|
|
||||||
help="Force truncation even if it seems like too much.")
|
|
||||||
(options, args) = parser.parse_args()
|
|
||||||
|
|
||||||
for fn in args:
|
|
||||||
f = file(fn, 'rb+')
|
|
||||||
f.seek(0x80)
|
|
||||||
(size,) = struct.unpack('<I', f.read(4))
|
|
||||||
|
|
||||||
ondisk = os.path.getsize(fn)
|
|
||||||
reduction = 100 - (size * 100.0 / ondisk)
|
|
||||||
print fn
|
|
||||||
|
|
||||||
if size == ondisk:
|
|
||||||
print ' Already truncated.'
|
|
||||||
continue
|
|
||||||
# I read in some source code that wifi games need 138 extra bytes.
|
|
||||||
# Why? I don't understand, but I figure you can afford 256 bytes
|
|
||||||
# extra to be on the safe side. Compared to the size of typical ROM
|
|
||||||
# images it's a pittance.
|
|
||||||
size += 256
|
|
||||||
if size >= ondisk:
|
|
||||||
print ' Already truncated.'
|
|
||||||
continue
|
|
||||||
|
|
||||||
print ' On disk:', ondisk
|
|
||||||
print ' Header says:', size
|
|
||||||
print ' Would save: %dB (%2.0f%%)' % (ondisk-size, reduction)
|
|
||||||
if size < (ondisk >> 2):
|
|
||||||
if options.force:
|
|
||||||
print ' Truncating anyway, as requested.'
|
|
||||||
else:
|
|
||||||
print ' Would truncate too much!!'
|
|
||||||
continue
|
|
||||||
if options.writeout:
|
|
||||||
f.truncate(size)
|
|
||||||
print ' Truncated.'
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,116 +0,0 @@
|
||||||
#!/usr/bin/env python
|
|
||||||
|
|
||||||
"""robotfindskitten -- A zen simulation.
|
|
||||||
|
|
||||||
This is a web version of the classic text-based game. The text-based
|
|
||||||
version is much better. Go check it out at http://robotfindskitten.org/
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
import cgitb; cgitb.enable()
|
|
||||||
import cgi
|
|
||||||
import whrandom
|
|
||||||
import sys
|
|
||||||
|
|
||||||
symbols = list('0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"$%&\'()*+,-./:;<=>?@[\]^_`{|}~')
|
|
||||||
width = 50
|
|
||||||
height = 30
|
|
||||||
|
|
||||||
def color():
|
|
||||||
def c():
|
|
||||||
return whrandom.choice(('44', '88', 'cc', 'ff'))
|
|
||||||
|
|
||||||
return c() + c() + c()
|
|
||||||
|
|
||||||
print 'Content-type: text/html'
|
|
||||||
print
|
|
||||||
|
|
||||||
def main():
|
|
||||||
nki = []
|
|
||||||
f = open('messages.h')
|
|
||||||
for line in f.xreadlines():
|
|
||||||
if line.startswith(' "'):
|
|
||||||
line = line.strip()
|
|
||||||
if line[-1] == ',':
|
|
||||||
line = line[1:-2]
|
|
||||||
else:
|
|
||||||
line = line[1:-1]
|
|
||||||
line = line.replace(r'\"', '"')
|
|
||||||
nki.append(line)
|
|
||||||
|
|
||||||
print '''<html><head>
|
|
||||||
<title>robotfindskitten: a zen simulation</title>
|
|
||||||
<link rel="stylesheet" type="text/css"
|
|
||||||
href="http://woozle.org/~neale/default.css">
|
|
||||||
<style type="text/css">
|
|
||||||
a {
|
|
||||||
text-decoration: none;
|
|
||||||
cursor: default;
|
|
||||||
}
|
|
||||||
a:visited {
|
|
||||||
color: #%s;
|
|
||||||
}
|
|
||||||
pre {
|
|
||||||
background-color: black;
|
|
||||||
border: solid white;
|
|
||||||
text-align: center;
|
|
||||||
padding: .75em;
|
|
||||||
cursor: default;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>''' % color()
|
|
||||||
|
|
||||||
print '<html>'
|
|
||||||
|
|
||||||
print '<h1>robotfindskitten</h1>'
|
|
||||||
|
|
||||||
print '''
|
|
||||||
<p>
|
|
||||||
You are robot. Your mission: find kitten.
|
|
||||||
|
|
||||||
|
|
||||||
Hold the mouse cursor over an object you suspect to be kitten.
|
|
||||||
After a few seconds, your browser will tell you what you have
|
|
||||||
found. Older browsers may not be able to relay what an object
|
|
||||||
actually is, so the experience may be diminished somewhat.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
'''
|
|
||||||
|
|
||||||
|
|
||||||
print '<pre>'
|
|
||||||
|
|
||||||
screen = []
|
|
||||||
for i in range(height):
|
|
||||||
screen.append([' '] * width)
|
|
||||||
|
|
||||||
for i in range(30):
|
|
||||||
x = whrandom.randrange(width)
|
|
||||||
y = whrandom.randrange(height)
|
|
||||||
|
|
||||||
n = whrandom.randrange(len(symbols))
|
|
||||||
s = symbols[n]
|
|
||||||
del symbols[n]
|
|
||||||
s = cgi.escape(s)
|
|
||||||
|
|
||||||
n = whrandom.randrange(len(nki))
|
|
||||||
t = nki[n]
|
|
||||||
del nki[n]
|
|
||||||
t = cgi.escape(t)
|
|
||||||
t = t.replace('"', '"')
|
|
||||||
|
|
||||||
screen[y][x] = ('<span style="color: #%s;" title="%s">%s</span>'
|
|
||||||
% (color(), t, s))
|
|
||||||
# place kitten!
|
|
||||||
screen[y][x] = '<a href="http://robotfindskitten.org" title="You found kitten! Way to go, robot!">%s</a>' % s
|
|
||||||
|
|
||||||
for row in screen:
|
|
||||||
print ''.join(row)
|
|
||||||
|
|
||||||
print '</pre>'
|
|
||||||
|
|
||||||
print '</html>'
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
||||||
|
|
|
@ -1,538 +0,0 @@
|
||||||
#! /usr/bin/env python
|
|
||||||
|
|
||||||
# Description: SNPP client class for Python
|
|
||||||
|
|
||||||
'''SNPP client class.
|
|
||||||
|
|
||||||
Author: Neale Pickett <neale@woozle.org>
|
|
||||||
|
|
||||||
This was modified from the Python 1.5 library SMTP lib.
|
|
||||||
Which was modified from the Python 1.5 library HTTP lib.
|
|
||||||
|
|
||||||
Basically, I took smtplib, did an s/SMTP/SNPP/, and changed about ten
|
|
||||||
other things. If only all projects were this easy :-)
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
>>> import snpplib
|
|
||||||
>>> s = snpplib.SNPP("localhost")
|
|
||||||
>>> print s.help()[1]
|
|
||||||
|
|
||||||
Level 1 commands accepted:
|
|
||||||
|
|
||||||
PAGEr <pager ID>
|
|
||||||
MESSage <alpha or numeric message>
|
|
||||||
RESEt
|
|
||||||
SEND
|
|
||||||
QUIT
|
|
||||||
HELP
|
|
||||||
|
|
||||||
Level 2 commands accepted:
|
|
||||||
|
|
||||||
DATA
|
|
||||||
LOGIn <loginid> [password]
|
|
||||||
LEVEl <ServiceLevel>
|
|
||||||
COVErage <AlternateArea>
|
|
||||||
HOLDuntil <YYMMDDHHMMSS> [+/-GMTdifference]
|
|
||||||
CALLerid <CallerID>
|
|
||||||
|
|
||||||
Level 3 commands accepted:
|
|
||||||
|
|
||||||
none
|
|
||||||
|
|
||||||
OK
|
|
||||||
>>> s.putcmd("rese")
|
|
||||||
>>> s.getreply()
|
|
||||||
(250, 'Reset ok')
|
|
||||||
>>> s.quit()
|
|
||||||
'''
|
|
||||||
|
|
||||||
import socket
|
|
||||||
import re
|
|
||||||
import rfc822
|
|
||||||
import types
|
|
||||||
|
|
||||||
SNPP_PORT = 444
|
|
||||||
CRLF="\r\n"
|
|
||||||
|
|
||||||
# Exception classes used by this module.
|
|
||||||
class SNPPException(Exception):
|
|
||||||
"""Base class for all exceptions raised by this module."""
|
|
||||||
|
|
||||||
class SNPPServerDisconnected(SNPPException):
|
|
||||||
"""Not connected to any SNPP server.
|
|
||||||
|
|
||||||
This exception is raised when the server unexpectedly disconnects,
|
|
||||||
or when an attempt is made to use the SNPP instance before
|
|
||||||
connecting it to a server.
|
|
||||||
"""
|
|
||||||
|
|
||||||
class SNPPResponseException(SNPPException):
|
|
||||||
"""Base class for all exceptions that include an SNPP error code.
|
|
||||||
|
|
||||||
These exceptions are generated in some instances when the SNPP
|
|
||||||
server returns an error code. The error code is stored in the
|
|
||||||
`snpp_code' attribute of the error, and the `snpp_error' attribute
|
|
||||||
is set to the error message.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, code, msg):
|
|
||||||
self.snpp_code = code
|
|
||||||
self.snpp_error = msg
|
|
||||||
self.args = (code, msg)
|
|
||||||
|
|
||||||
class SNPPSenderRefused(SNPPResponseException):
|
|
||||||
"""Caller ID refused.
|
|
||||||
|
|
||||||
In addition to the attributes set by on all SNPPResponseException
|
|
||||||
exceptions, this sets `sender' to the string that the SNPP refused
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, code, msg, sender):
|
|
||||||
self.snpp_code = code
|
|
||||||
self.snpp_error = msg
|
|
||||||
self.sender = sender
|
|
||||||
self.args = (code, msg, sender)
|
|
||||||
|
|
||||||
class SMTPRecipientsRefused(SNPPResponseException):
|
|
||||||
"""All recipient addresses refused.
|
|
||||||
|
|
||||||
The errors for each recipient are accessable thru the attribute
|
|
||||||
'recipients', which is a dictionary of exactly the same sort as
|
|
||||||
SNPP.sendpage() returns.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, recipients):
|
|
||||||
self.recipients = recipients
|
|
||||||
self.args = ( recipients,)
|
|
||||||
|
|
||||||
|
|
||||||
class SNPPDataError(SNPPResponseException):
|
|
||||||
"""The SNPP server didn't accept the data."""
|
|
||||||
|
|
||||||
class SNPPConnectError(SNPPResponseException):
|
|
||||||
"""Error during connection establishment"""
|
|
||||||
|
|
||||||
def quotedata(data):
|
|
||||||
"""Quote data for email.
|
|
||||||
|
|
||||||
Double leading '.', and change Unix newline '\n', or Mac '\r' into
|
|
||||||
Internet CRLF end-of-line.
|
|
||||||
"""
|
|
||||||
return re.sub(r'(?m)^\.', '..',
|
|
||||||
re.sub(r'(?:\r\n|\n|\r(?!\n))', CRLF, data))
|
|
||||||
|
|
||||||
class SNPP:
|
|
||||||
"""This class manages a connection to an SNPP server.
|
|
||||||
SNPP Objects:
|
|
||||||
|
|
||||||
For method docs, see each method's docstrings. In general, there is
|
|
||||||
a method of the same name to perform each SNPP command, and there
|
|
||||||
is a method called 'sendpage' that will do an entire page
|
|
||||||
transaction.
|
|
||||||
"""
|
|
||||||
debuglevel = 0
|
|
||||||
file = None
|
|
||||||
|
|
||||||
def __init__(self, host = '', port = 0):
|
|
||||||
"""Initialize a new instance.
|
|
||||||
|
|
||||||
If specified, `host' is the name of the remote host to which to
|
|
||||||
connect. If specified, `port' specifies the port to which to connect.
|
|
||||||
By default, snpplib.SNPP_PORT is used. An SNPPConnectError is
|
|
||||||
raised if the specified `host' doesn't respond correctly.
|
|
||||||
|
|
||||||
"""
|
|
||||||
self.esnpp_features = {}
|
|
||||||
if host:
|
|
||||||
(code, msg) = self.connect(host, port)
|
|
||||||
if code != 220:
|
|
||||||
raise SNPPConnectError(code, msg)
|
|
||||||
|
|
||||||
def set_debuglevel(self, debuglevel):
|
|
||||||
"""Set the debug output level.
|
|
||||||
|
|
||||||
A non-false value results in debug messages for connection and for all
|
|
||||||
messages sent to and received from the server.
|
|
||||||
|
|
||||||
"""
|
|
||||||
self.debuglevel = debuglevel
|
|
||||||
|
|
||||||
def connect(self, host='localhost', port = 0):
|
|
||||||
"""Connect to a host on a given port.
|
|
||||||
|
|
||||||
If the hostname ends with a colon (`:') followed by a number, and
|
|
||||||
there is no port specified, that suffix will be stripped off and the
|
|
||||||
number interpreted as the port number to use.
|
|
||||||
|
|
||||||
Note: This method is automatically invoked by __init__, if a host is
|
|
||||||
specified during instantiation.
|
|
||||||
|
|
||||||
"""
|
|
||||||
if not port:
|
|
||||||
i = host.find(':')
|
|
||||||
if i >= 0:
|
|
||||||
host, port = host[:i], host[i+1:]
|
|
||||||
try:
|
|
||||||
port = int(port)
|
|
||||||
except ValueError:
|
|
||||||
raise socket.error, "nonnumeric port"
|
|
||||||
if not port: port = SNPP_PORT
|
|
||||||
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
||||||
if self.debuglevel > 0: print 'connect:', (host, port)
|
|
||||||
self.sock.connect((host, port))
|
|
||||||
(code,msg)=self.getreply()
|
|
||||||
if self.debuglevel >0 : print "connect:", msg
|
|
||||||
return (code,msg)
|
|
||||||
|
|
||||||
def sendstr(self, str):
|
|
||||||
"""Send `str' to the server."""
|
|
||||||
if self.debuglevel > 0: print 'send:', `str`
|
|
||||||
if self.sock:
|
|
||||||
try:
|
|
||||||
self.sock.send(str)
|
|
||||||
except socket.error:
|
|
||||||
raise SNPPServerDisconnected('Server not connected')
|
|
||||||
else:
|
|
||||||
raise SNPPServerDisconnected('please run connect() first')
|
|
||||||
|
|
||||||
def putcmd(self, cmd, args=""):
|
|
||||||
"""Send a command to the server."""
|
|
||||||
str = '%s %s%s' % (cmd, args, CRLF)
|
|
||||||
self.sendstr(str)
|
|
||||||
|
|
||||||
def getreply(self):
|
|
||||||
"""Get a reply from the server.
|
|
||||||
|
|
||||||
Returns a tuple consisting of:
|
|
||||||
|
|
||||||
- server response code (e.g. '250', or such, if all goes well)
|
|
||||||
Note: returns -1 if it can't read response code.
|
|
||||||
|
|
||||||
- server response string corresponding to response code (multiline
|
|
||||||
responses are converted to a single, multiline string).
|
|
||||||
|
|
||||||
Raises SNPPServerDisconnected if end-of-file is reached.
|
|
||||||
"""
|
|
||||||
resp=[]
|
|
||||||
if self.file is None:
|
|
||||||
self.file = self.sock.makefile('rb')
|
|
||||||
while 1:
|
|
||||||
line = self.file.readline()
|
|
||||||
if line == '':
|
|
||||||
self.close()
|
|
||||||
raise SNPPServerDisconnected("Connection unexpectedly closed")
|
|
||||||
if self.debuglevel > 0: print 'reply:', `line`
|
|
||||||
resp.append(line[4:].strip())
|
|
||||||
code=line[:3]
|
|
||||||
# Check that the error code is syntactically correct.
|
|
||||||
# Don't attempt to read a continuation line if it is broken.
|
|
||||||
try:
|
|
||||||
errcode = int(code)
|
|
||||||
except ValueError:
|
|
||||||
errcode = -1
|
|
||||||
break
|
|
||||||
# Check if multiline response.
|
|
||||||
if errcode != 214:
|
|
||||||
break
|
|
||||||
|
|
||||||
errmsg = '\n'.join(resp)
|
|
||||||
if self.debuglevel > 0:
|
|
||||||
print 'reply: retcode (%s); Msg: %s' % (errcode,errmsg)
|
|
||||||
return errcode, errmsg
|
|
||||||
|
|
||||||
def docmd(self, cmd, args=""):
|
|
||||||
"""Send a command, and return its response code."""
|
|
||||||
self.putcmd(cmd,args)
|
|
||||||
return self.getreply()
|
|
||||||
|
|
||||||
def help(self, args=''):
|
|
||||||
"""SNPP 'help' command.
|
|
||||||
Returns help text from server."""
|
|
||||||
return self.docmd("help", args)
|
|
||||||
|
|
||||||
def rese(self):
|
|
||||||
"""SNPP 'rese' command -- resets session."""
|
|
||||||
return self.docmd("rese")
|
|
||||||
|
|
||||||
def page(self, pagerid, password=""):
|
|
||||||
"""SNPP 'page' command -- specifies a pager ID.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
if password:
|
|
||||||
args = "%s %s" % (pagerid, password)
|
|
||||||
else:
|
|
||||||
args = pagerid
|
|
||||||
return self.docmd("page", args)
|
|
||||||
|
|
||||||
def mess(self, msg):
|
|
||||||
"""SNPP 'mess' command -- sends a single-line message."""
|
|
||||||
return self.docmd("mess", msg)
|
|
||||||
|
|
||||||
def send(self):
|
|
||||||
"""SNPP 'send' command -- sends a message."""
|
|
||||||
return self.docmd("send")
|
|
||||||
|
|
||||||
def data(self, msg):
|
|
||||||
"""SNPP 'DATA' command -- sends message data to server.
|
|
||||||
|
|
||||||
Automatically quotes lines beginning with a period per rfc821.
|
|
||||||
Raises SNPPDataError if there is an unexpected reply to the
|
|
||||||
DATA command; the return value from this method is the final
|
|
||||||
response code received when the all data is sent.
|
|
||||||
"""
|
|
||||||
self.putcmd("data")
|
|
||||||
(code,repl)=self.getreply()
|
|
||||||
if self.debuglevel >0 : print "data:", (code,repl)
|
|
||||||
if code <> 354:
|
|
||||||
raise SNPPDataError(code,repl)
|
|
||||||
else:
|
|
||||||
self.sendstr(quotedata(msg))
|
|
||||||
self.sendstr("%s.%s" % (CRLF, CRLF))
|
|
||||||
(code,msg)=self.getreply()
|
|
||||||
if self.debuglevel >0 : print "data:", (code,msg)
|
|
||||||
return (code,msg)
|
|
||||||
|
|
||||||
# Level 2 - Optional Extensions
|
|
||||||
|
|
||||||
def logi(self, loginid, password=""):
|
|
||||||
"""SNPP 'logi' command -- logs in to the server.
|
|
||||||
|
|
||||||
This command allows for a session login ID to be specified. It
|
|
||||||
is used to validate the person attempting to access the paging
|
|
||||||
terminal. If no LOGIn command is issued, "anonymous" user
|
|
||||||
status is assumed.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
if password:
|
|
||||||
args = "%s %s" % (loginid, password)
|
|
||||||
else:
|
|
||||||
args = loginid
|
|
||||||
return self.docmd("logi", args)
|
|
||||||
|
|
||||||
def leve(self, servicelevel):
|
|
||||||
"""SNPP 'leve' command -- sets server level for next PAGE.
|
|
||||||
|
|
||||||
The LEVEl function is used to specify an optional alternate
|
|
||||||
level of service for the next PAGEr command. Ideally,
|
|
||||||
"ServiceLevel" should be an integer between 0 and 11 inclusive.
|
|
||||||
The TME protocol specifies ServiceLevel as follows:
|
|
||||||
|
|
||||||
0 - Priority
|
|
||||||
1 - Normal (default)
|
|
||||||
2 - Five minutes
|
|
||||||
3 - Fifteen minutes
|
|
||||||
4 - One hour
|
|
||||||
5 - Four hours
|
|
||||||
6 - Twelve hours
|
|
||||||
7 - Twenty Four hours
|
|
||||||
8 - Carrier specific '1'
|
|
||||||
9 - Carrier specific '2'
|
|
||||||
10 - Carrier specific '3'
|
|
||||||
11 - Carrier specific '4'
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
return self.docmd("leve", servicelevel)
|
|
||||||
|
|
||||||
def aler(self, alertoverride):
|
|
||||||
"""SNPP 'aler' command -- override alert setting.
|
|
||||||
|
|
||||||
The optional ALERt command may be used to override the default
|
|
||||||
setting and specify whether or not to alert the subscriber upon
|
|
||||||
receipt of a message. This option, like the previous command,
|
|
||||||
alters the parameters submitted to the paging terminal using
|
|
||||||
the PAGEr command. The TME protocol specifies AlertOverride as
|
|
||||||
either 0-DoNotAlert, or 1-Alert.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
return self.docmd("aler", alertoverride)
|
|
||||||
|
|
||||||
def cove(self, alternatearea):
|
|
||||||
"""SNPP 'cove' command -- override coverage area.
|
|
||||||
|
|
||||||
The optional COVErage command is used to override the
|
|
||||||
subscriber's default coverage area, and allow for the selection
|
|
||||||
of an alternate region. This option, like the previous
|
|
||||||
command, alters the parameters submitted to the paging terminal
|
|
||||||
using the PAGEr command. AlternateArea is a designator for one
|
|
||||||
of the following:
|
|
||||||
|
|
||||||
- A subscriber-specific alternate coverage area
|
|
||||||
- A carrier-defined region available to subscribers
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
return self.docmd("cove", alternatearea)
|
|
||||||
|
|
||||||
def hold(self, timespec, gmtdiff=""):
|
|
||||||
"""SNPP 'hold' command -- hold until specified time.
|
|
||||||
|
|
||||||
The HOLDuntil command allows for the delayed delivery of a
|
|
||||||
message, to a particular subscriber, until after the time
|
|
||||||
specified. The time may be specified in local time (e.g. local
|
|
||||||
to the paging terminal), or with an added parameter specifying
|
|
||||||
offset from GMT (in other words, "-0600" specifies Eastern
|
|
||||||
Standard Time). This option, like the previous command, alters
|
|
||||||
the parameters submitted to the paging terminal using the PAGEr
|
|
||||||
command.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
if gmtdiff:
|
|
||||||
args = "%s %s" % (timespec, gmtdiff)
|
|
||||||
else:
|
|
||||||
args = timespec
|
|
||||||
|
|
||||||
return self.docmd("hold", args)
|
|
||||||
|
|
||||||
def call(self, callerid):
|
|
||||||
"""SNPP 'call' command -- specify caller ID.
|
|
||||||
|
|
||||||
The CALLerid function is a message-oriented function (as opposed
|
|
||||||
to the subscriber-oriented functions just described). This
|
|
||||||
allows for the specification of the CallerIdentifier function as
|
|
||||||
described in TME. This parameter is optional, and is at the
|
|
||||||
discretion of the carrier as to how it should be implemented or
|
|
||||||
used.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
return self.docmd("call", callerid)
|
|
||||||
|
|
||||||
def subj(self, messagesubject):
|
|
||||||
"""SNPP 'subj' command -- specify a message subject.
|
|
||||||
|
|
||||||
The SUBJect function allows is a message-oriented function that
|
|
||||||
allows the sender to specify a subject for the next message to
|
|
||||||
be sent. This parameter is optional and is at the discretion of
|
|
||||||
the carrier as to how it should be implemented or used.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
return self.docmd("subj", messagesubject)
|
|
||||||
|
|
||||||
|
|
||||||
# Level 3 -- Two-Way Extensions
|
|
||||||
|
|
||||||
# I didn't implement these because I got tired of typing this stuff
|
|
||||||
# in, and I doubt anyone's going to use this anyhow, seeing as how
|
|
||||||
# qpage doesn't do any of these extensions. Although this may
|
|
||||||
# change.
|
|
||||||
|
|
||||||
# some useful methods
|
|
||||||
def sendpage(self, from_id, to_ids, msg):
|
|
||||||
"""This command performs an entire mail transaction.
|
|
||||||
|
|
||||||
The arguments are:
|
|
||||||
- from_id : The CallerID sending this mail, or None to
|
|
||||||
not send any CallerID.
|
|
||||||
- to_ids : A list of pager IDs to send this page to. A
|
|
||||||
bare string will be treated as a list with 1
|
|
||||||
address.
|
|
||||||
- msg : The message to send.
|
|
||||||
|
|
||||||
This method will return normally if the page is accepted for at
|
|
||||||
least one recipient. It returns a dictionary, with one entry for
|
|
||||||
each recipient that was refused. Each entry contains a tuple of
|
|
||||||
the SNPP error code and the accompanying error message sent by
|
|
||||||
the server.
|
|
||||||
|
|
||||||
This method may raise the following exceptions:
|
|
||||||
|
|
||||||
SNPPRecipientsRefused The server rejected for ALL recipients
|
|
||||||
(no mail was sent).
|
|
||||||
SNPPSenderRefused The server didn't accept the from_id.
|
|
||||||
SNPPDataError The server replied with an unexpected
|
|
||||||
error code
|
|
||||||
|
|
||||||
Note: the connection will be open even after an exception is raised.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
>>> import snpplib
|
|
||||||
>>> s=snpplib.SNPP("localhost")
|
|
||||||
>>> tolist=["parsingh","rhiannon","saffola","bob"]
|
|
||||||
>>> msg = 'Hey guys, what say we have pizza for dinner?'
|
|
||||||
>>> s.sendpage("neale",tolist,msg)
|
|
||||||
{ "bob" : ( 550 ,"User unknown" ) }
|
|
||||||
>>> s.quit()
|
|
||||||
|
|
||||||
In the above example, the message was accepted for delivery to three
|
|
||||||
of the four addresses, and one was rejected, with the error code
|
|
||||||
550. If all addresses are accepted, then the method will return an
|
|
||||||
empty dictionary.
|
|
||||||
|
|
||||||
"""
|
|
||||||
(code,resp) = self.call(from_id)
|
|
||||||
if code <> 250:
|
|
||||||
# CallerID command not implemented, too bad.
|
|
||||||
pass
|
|
||||||
senderrs={}
|
|
||||||
if type(to_ids) == types.StringType:
|
|
||||||
to_ids = [to_ids]
|
|
||||||
for each in to_ids:
|
|
||||||
(code,resp)=self.page(each)
|
|
||||||
if (code <> 250) and (code <> 251):
|
|
||||||
senderrs[each]=(code,resp)
|
|
||||||
if len(senderrs)==len(to_ids):
|
|
||||||
# the server refused all our recipients
|
|
||||||
self.rese()
|
|
||||||
raise SNPPRecipientsRefused(senderrs)
|
|
||||||
(code,resp)=self.data(msg)
|
|
||||||
if code <> 250:
|
|
||||||
self.rese()
|
|
||||||
raise SNPPDataError(code, resp)
|
|
||||||
(code,resp)=self.send()
|
|
||||||
if code <> 250:
|
|
||||||
self.rese()
|
|
||||||
raise SNPPDataError(code, resp)
|
|
||||||
#if we got here then somebody got our page
|
|
||||||
return senderrs
|
|
||||||
|
|
||||||
|
|
||||||
def close(self):
|
|
||||||
"""Close the connection to the SNPP server."""
|
|
||||||
if self.file:
|
|
||||||
self.file.close()
|
|
||||||
self.file = None
|
|
||||||
if self.sock:
|
|
||||||
self.sock.close()
|
|
||||||
self.sock = None
|
|
||||||
|
|
||||||
|
|
||||||
def quit(self):
|
|
||||||
"""Terminate the SNPP session."""
|
|
||||||
self.docmd("quit")
|
|
||||||
self.close()
|
|
||||||
|
|
||||||
|
|
||||||
# Test the sendmail method, which tests most of the others.
|
|
||||||
# Note: This always sends to localhost.
|
|
||||||
if __name__ == '__main__':
|
|
||||||
import sys, rfc822
|
|
||||||
|
|
||||||
def prompt(prompt):
|
|
||||||
sys.stdout.write(prompt + ": ")
|
|
||||||
return sys.stdin.readline().strip()
|
|
||||||
|
|
||||||
fromaddr = prompt("From")
|
|
||||||
toaddrs = prompt("To").split(',')
|
|
||||||
print "Enter message, end with ^D:"
|
|
||||||
msg = ''
|
|
||||||
while 1:
|
|
||||||
line = sys.stdin.readline()
|
|
||||||
if not line:
|
|
||||||
break
|
|
||||||
msg = msg + line
|
|
||||||
print "Message length is " + `len(msg)`
|
|
||||||
|
|
||||||
server = SNPP('localhost')
|
|
||||||
server.set_debuglevel(1)
|
|
||||||
server.sendpage(fromaddr, toaddrs, msg)
|
|
||||||
server.quit()
|
|
|
@ -1,325 +0,0 @@
|
||||||
#! /usr/bin/env python
|
|
||||||
|
|
||||||
### spampot.py -- Spam honeypot SMTP server
|
|
||||||
### Copyright (C) 2003 Neale Pikett <neale@woozle.org>
|
|
||||||
### Time-stamp: <2003-05-06 09:08:52 neale>
|
|
||||||
###
|
|
||||||
### This is free software; you can redistribute it and/or modify it
|
|
||||||
### under the terms of the GNU General Public License as published by
|
|
||||||
### the Free Software Foundation; either version 2, or (at your option)
|
|
||||||
### any later version.
|
|
||||||
###
|
|
||||||
### This program is distributed in the hope that it will be useful, but
|
|
||||||
### WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
### General Public License for more details.
|
|
||||||
###
|
|
||||||
### You should have received a copy of the GNU General Public License
|
|
||||||
### along with this software; see the file COPYING. If not, write to
|
|
||||||
### the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139,
|
|
||||||
### USA.
|
|
||||||
|
|
||||||
"""Spam honeypot SMTP server.
|
|
||||||
|
|
||||||
This just sits on port 25 of whatever IP you pass in as an argument, and
|
|
||||||
spools every message out to MAILDIR. It tries to look like an old
|
|
||||||
Sendmail server, to maximize chances of being tagged as an open relay.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
import cStringIO as StringIO
|
|
||||||
import asynchat
|
|
||||||
import asyncore
|
|
||||||
import syslog
|
|
||||||
import smtplib
|
|
||||||
import rfc822
|
|
||||||
import socket
|
|
||||||
import time
|
|
||||||
import sys
|
|
||||||
import os
|
|
||||||
import re
|
|
||||||
import struct
|
|
||||||
import maildir # get maildir.py from the same place you got this file
|
|
||||||
|
|
||||||
# suid to this user
|
|
||||||
USER = 'spam'
|
|
||||||
|
|
||||||
# host to relay probes for us
|
|
||||||
SMARTHOST = '127.0.0.1'
|
|
||||||
|
|
||||||
# save multiple messages from the same IP? You probably don't want this
|
|
||||||
# -- it can consume a gigabyte a day.
|
|
||||||
SAVEDUPES = False
|
|
||||||
|
|
||||||
# slow down if multiple mails are getting sent over a single connection?
|
|
||||||
# This could save bandwidth.
|
|
||||||
TARPIT = True
|
|
||||||
|
|
||||||
# chroot to this directory and spool messages there
|
|
||||||
MAILDIR = '/home/spam/Maildir/spampot'
|
|
||||||
|
|
||||||
# My hostname
|
|
||||||
HOST = socket.gethostname()
|
|
||||||
|
|
||||||
# write to this PID file
|
|
||||||
PIDFILE = '/var/run/spampot.pid'
|
|
||||||
|
|
||||||
# syslog levels (you shouldn't need to change this)
|
|
||||||
LEVELS = {'info': syslog.LOG_INFO,
|
|
||||||
'warning': syslog.LOG_WARNING,
|
|
||||||
'error': syslog.LOG_ERR}
|
|
||||||
|
|
||||||
###
|
|
||||||
|
|
||||||
# Hosts seen
|
|
||||||
seen = {}
|
|
||||||
|
|
||||||
def shescape(str):
|
|
||||||
return "'" + str.replace("'", "'\"'\"'") + "'"
|
|
||||||
|
|
||||||
|
|
||||||
class Daemon:
|
|
||||||
"""Helpful class to make a process a daemon"""
|
|
||||||
|
|
||||||
def __init__(self, pidfile):
|
|
||||||
try:
|
|
||||||
f = file(pidfile, "r")
|
|
||||||
pid = int(f.read())
|
|
||||||
f.close()
|
|
||||||
os.kill(pid, 0)
|
|
||||||
print "Already running at pid %d" % pid
|
|
||||||
sys.exit(1)
|
|
||||||
except (IOError, OSError, ValueError):
|
|
||||||
pass
|
|
||||||
self.pidf = file(pidfile, 'w')
|
|
||||||
|
|
||||||
def daemonize(self):
|
|
||||||
self.pid = os.fork()
|
|
||||||
if self.pid:
|
|
||||||
self.pidf.write("%d\n" % self.pid)
|
|
||||||
sys.exit(0)
|
|
||||||
# Decouple from parent
|
|
||||||
self.pidf.close()
|
|
||||||
os.chdir("/")
|
|
||||||
os.setsid()
|
|
||||||
os.umask(0)
|
|
||||||
os.close(sys.stdin.fileno())
|
|
||||||
os.close(sys.stdout.fileno())
|
|
||||||
os.close(sys.stderr.fileno())
|
|
||||||
syslog.syslog(syslog.LOG_INFO, "starting")
|
|
||||||
return self.pid
|
|
||||||
|
|
||||||
def jail(self, root, user=None, group=None):
|
|
||||||
uid, gid = None, None
|
|
||||||
if group:
|
|
||||||
import grp
|
|
||||||
|
|
||||||
gr = grp.getgrnam(group)
|
|
||||||
gid = gr[2]
|
|
||||||
if user:
|
|
||||||
import pwd
|
|
||||||
|
|
||||||
pw = pwd.getpwnam(user)
|
|
||||||
uid = pw[2]
|
|
||||||
if not gid: gid = pw[3]
|
|
||||||
os.chroot(root)
|
|
||||||
os.chdir('/')
|
|
||||||
if gid: os.setgid(gid)
|
|
||||||
if uid: os.setuid(uid)
|
|
||||||
|
|
||||||
|
|
||||||
class Listener(asyncore.dispatcher):
|
|
||||||
"""Listens for incoming socket connections and spins off
|
|
||||||
dispatchers created by a factory callable.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, bindaddr, port,
|
|
||||||
factory, factoryArgs=()):
|
|
||||||
asyncore.dispatcher.__init__(self)
|
|
||||||
self.factory = factory
|
|
||||||
self.factoryArgs = factoryArgs
|
|
||||||
self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
||||||
self.set_reuse_addr()
|
|
||||||
self.bind((bindaddr, port))
|
|
||||||
self.listen(40)
|
|
||||||
syslog.syslog(syslog.LOG_INFO, 'Listening on %s:%d' % (bindaddr, port))
|
|
||||||
|
|
||||||
def handle_accept(self):
|
|
||||||
# If an incoming connection is instantly reset, eg. by following a
|
|
||||||
# link in the web interface then instantly following another one or
|
|
||||||
# hitting stop, handle_accept() will be triggered but accept() will
|
|
||||||
# return None.
|
|
||||||
result = self.accept()
|
|
||||||
if result:
|
|
||||||
clientSocket, clientAddress = result
|
|
||||||
args = [clientSocket] + list(self.factoryArgs)
|
|
||||||
self.factory(*args)
|
|
||||||
|
|
||||||
|
|
||||||
class Server(asynchat.async_chat):
|
|
||||||
"""A stupid SMTP server."""
|
|
||||||
|
|
||||||
def __init__(self, sock):
|
|
||||||
self.msg_count = 0
|
|
||||||
self.host = 'internal.nat'
|
|
||||||
self.request = ''
|
|
||||||
self.hello = None
|
|
||||||
self.reset()
|
|
||||||
asynchat.async_chat.__init__(self)
|
|
||||||
self.set_socket(sock)
|
|
||||||
|
|
||||||
def reset(self):
|
|
||||||
self.mailfrom = None
|
|
||||||
self.rcptto = []
|
|
||||||
|
|
||||||
def log(self, message):
|
|
||||||
syslog.syslog(syslog.LOG_INFO, message)
|
|
||||||
|
|
||||||
def log_info(self, message, type='info'):
|
|
||||||
lvl = LEVELS.get(type, syslog.LOG_INFO)
|
|
||||||
syslog.syslog(lvl, message)
|
|
||||||
|
|
||||||
def handle_connect(self):
|
|
||||||
self.peername = self.getpeername()
|
|
||||||
self.sockname = self.getsockname()
|
|
||||||
self.socknamehex = "%X" % struct.unpack('L', socket.inet_aton(self.sockname[0]))
|
|
||||||
self.set_terminator('\r\n')
|
|
||||||
|
|
||||||
self.log('Connect from %s' % (self.peername,))
|
|
||||||
now = time.localtime()
|
|
||||||
ts = time.strftime('%a, ' + str(now[2]) + ' %b %y %H:%M:%S %Z')
|
|
||||||
self.push("220 %s Sendmail ready at %s\r\n" % (self.host, ts))
|
|
||||||
|
|
||||||
def handle_close(self):
|
|
||||||
self.log('Close from %s; relayed %d messages' % (self.peername, self.msg_count))
|
|
||||||
self.close()
|
|
||||||
|
|
||||||
def collect_incoming_data(self, data):
|
|
||||||
self.request += data
|
|
||||||
|
|
||||||
def envelope_found_terminator(self):
|
|
||||||
data = self.request
|
|
||||||
self.request = ""
|
|
||||||
command = data[:4].upper()
|
|
||||||
if command in ["HELO", "EHLO"]:
|
|
||||||
whom = data[5:].strip()
|
|
||||||
self.hello = whom
|
|
||||||
self.push("250 Hello %s, pleased to meet you.\r\n" % whom)
|
|
||||||
elif command == 'MAIL':
|
|
||||||
whom = data[10:].strip()
|
|
||||||
self.mailfrom = whom
|
|
||||||
self.push("250 %s... Sender ok\r\n" % whom)
|
|
||||||
elif command == 'RCPT':
|
|
||||||
whom = data[8:].strip()
|
|
||||||
self.rcptto.append(whom)
|
|
||||||
self.push("250 %s... Recipient ok\r\n" % whom)
|
|
||||||
elif command == "DATA":
|
|
||||||
self.set_terminator('\r\n.\r\n')
|
|
||||||
self.found_terminator = self.data_found_terminator
|
|
||||||
self.push('354 Enter mail, end with "." on a line by itself\r\n')
|
|
||||||
elif command == "QUIT":
|
|
||||||
self.push("221 %s closing connection\r\n" % self.host)
|
|
||||||
self.close_when_done()
|
|
||||||
elif command == "RSET":
|
|
||||||
self.reset()
|
|
||||||
self.push('250 Reset state\r\n')
|
|
||||||
else:
|
|
||||||
self.push("500 Command unrecognized\r\n")
|
|
||||||
found_terminator = envelope_found_terminator
|
|
||||||
|
|
||||||
def data_found_terminator(self):
|
|
||||||
self.message = self.request
|
|
||||||
self.request = ''
|
|
||||||
self.set_terminator('\r\n')
|
|
||||||
self.found_terminator = self.envelope_found_terminator
|
|
||||||
self.deliver_message()
|
|
||||||
self.push("250 Mail accepted\r\n")
|
|
||||||
self.reset()
|
|
||||||
|
|
||||||
def relay_message(self):
|
|
||||||
s = os.popen("/usr/lib/sendmail -f %s %s"
|
|
||||||
% (shescape(self.string),
|
|
||||||
' '.join([shescape(s) for s in self.rcptto])),
|
|
||||||
'w')
|
|
||||||
s.write(self.message)
|
|
||||||
s.close()
|
|
||||||
|
|
||||||
probe_re = None
|
|
||||||
|
|
||||||
def is_probe(self):
|
|
||||||
"""Returns true if the current message is a probe message"""
|
|
||||||
|
|
||||||
# Compile the probe regular expression the first time through
|
|
||||||
if not self.probe_re:
|
|
||||||
self.probe_re = re.compile(r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}|%s:25' % self.socknamehex,
|
|
||||||
re.IGNORECASE)
|
|
||||||
|
|
||||||
# If it's not the first message this connection, it's probably
|
|
||||||
# not a probe.
|
|
||||||
if self.msg_count:
|
|
||||||
return False
|
|
||||||
|
|
||||||
# Probes also don't have multiple recipients
|
|
||||||
if len(self.rcptto) != 1:
|
|
||||||
return False
|
|
||||||
|
|
||||||
# And they're short
|
|
||||||
if len(self.message) > 1024:
|
|
||||||
return False
|
|
||||||
|
|
||||||
# Check for the probe regex
|
|
||||||
if self.probe_re.search(self.message):
|
|
||||||
# we have a bite: now do some more intense investigation
|
|
||||||
f = StringIO.StringIO(self.message)
|
|
||||||
m = rfc822.Message(f)
|
|
||||||
|
|
||||||
# IP address in subject?
|
|
||||||
subj = m.get('Subject')
|
|
||||||
if subj and subj.find(self.sockname[0]) != -1:
|
|
||||||
return True
|
|
||||||
|
|
||||||
# Hex-encoded IP address anywhere in message?
|
|
||||||
if m.find(self.socknamehex) != -1:
|
|
||||||
return True
|
|
||||||
|
|
||||||
return False
|
|
||||||
|
|
||||||
def deliver_message(self):
|
|
||||||
global seen
|
|
||||||
|
|
||||||
headers = [
|
|
||||||
"SMTP-Date: %s" % time.ctime(),
|
|
||||||
"SMTP-Sock: %s:%d" % self.sockname,
|
|
||||||
"SMTP-Peer: %s:%d" % self.peername,
|
|
||||||
"SMTP-Hello: %s" % self.hello,
|
|
||||||
"SMTP-Mail-From: %s" % self.mailfrom,
|
|
||||||
"SMTP-Messages-This-Connection: %s" % self.msg_count,
|
|
||||||
]
|
|
||||||
for t in self.rcptto:
|
|
||||||
headers.append("SMTP-Rcpt-To: %s" % t)
|
|
||||||
if self.is_probe():
|
|
||||||
self.relay_message()
|
|
||||||
self.log('Relayed probe from=%s to=%s' % (self.mailfrom, self.rcptto))
|
|
||||||
headers.append("SMTP-Relayed: Yes")
|
|
||||||
msg_count = seen.get(self.peername) + 1
|
|
||||||
seen[self.peername] = msg_count
|
|
||||||
if msg_count in (0, 1, 2, 3, 4, 8, 64, 512, 4096, 32768, 262144):
|
|
||||||
# Hopefully nobody running this will ever hit that last one ;)
|
|
||||||
msg = '\r\n'.join(headers) + '\r\n' + self.message
|
|
||||||
m = maildir.write(time.strftime('%Y-%m'), msg)
|
|
||||||
self.log('Trapped from=%s to=%s msg_count=%d' % (self.mailfrom, self.rcptto, msg_count))
|
|
||||||
self.msg_count += 1
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
dmn = Daemon(PIDFILE)
|
|
||||||
syslog.openlog('spampot', syslog.LOG_PID, syslog.LOG_MAIL)
|
|
||||||
listener = Listener(sys.argv[1], 25, Server)
|
|
||||||
dmn.jail(MAILDIR, USER)
|
|
||||||
dmn.daemonize()
|
|
||||||
asyncore.loop()
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
||||||
|
|
|
@ -1,329 +0,0 @@
|
||||||
#! /usr/bin/python
|
|
||||||
|
|
||||||
"""Status dealiemajigger for dzen2 (or others, probably).
|
|
||||||
|
|
||||||
This outputs:
|
|
||||||
|
|
||||||
* Debian packages in need of upgrade (if you have the apt module)
|
|
||||||
* master volume (if you have alsa)
|
|
||||||
* battery life (if you have a battery)
|
|
||||||
* load average if it goes over 0.25
|
|
||||||
* current date and time
|
|
||||||
|
|
||||||
It prints it again whenever any of these change. It also watches for Mute,
|
|
||||||
Volume Up, and Volume Down key events on multimedia keyboards, and adjusts
|
|
||||||
the mixer appropriately.
|
|
||||||
|
|
||||||
Lastly, it registers itself with D-Bus so you can send yourself notices
|
|
||||||
like so:
|
|
||||||
|
|
||||||
$ dbus-send --dest=org.woozle.Status \
|
|
||||||
/org/woozle/Status \
|
|
||||||
org.woozle.Status.notice \
|
|
||||||
string:'this is where your message goes'
|
|
||||||
|
|
||||||
They will show up green in dzen2.
|
|
||||||
|
|
||||||
This only polls the ALSA mixer settings, and those only every minute.
|
|
||||||
Master mixer changes will take from 0 to 60 seconds to register if you
|
|
||||||
don't use the multimedia keys on your keyboard.
|
|
||||||
|
|
||||||
You need to be running HAL for this to do much other than tell you
|
|
||||||
the time. Don't worry, HAL is pretty small.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
import signal
|
|
||||||
import dbus
|
|
||||||
import dbus.service
|
|
||||||
import sys
|
|
||||||
import os
|
|
||||||
import gobject
|
|
||||||
import time
|
|
||||||
from sets import Set
|
|
||||||
try:
|
|
||||||
import apt
|
|
||||||
import socket
|
|
||||||
except ImportError:
|
|
||||||
apt = None
|
|
||||||
|
|
||||||
try:
|
|
||||||
import alsaaudio
|
|
||||||
except ImportError:
|
|
||||||
alsaaudio = None
|
|
||||||
|
|
||||||
# Set to true if you want dzen2 colors
|
|
||||||
dzen2 = False
|
|
||||||
|
|
||||||
def color(name, text):
|
|
||||||
if dzen2:
|
|
||||||
return '^fg(%s)%s^fg()' % (name, text)
|
|
||||||
else:
|
|
||||||
return '-=[ %s ]=-' % text
|
|
||||||
|
|
||||||
class Status(dbus.service.Object):
|
|
||||||
debug = False
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
dbus.service.Object.__init__(self, *args, **kwargs)
|
|
||||||
|
|
||||||
self.system_bus = dbus.SystemBus()
|
|
||||||
|
|
||||||
self.hal_manager = self.system_bus.get_object('org.freedesktop.Hal',
|
|
||||||
'/org/freedesktop/Hal/Manager')
|
|
||||||
self.hal_computer = self.system_bus.get_object('org.freedesktop.Hal',
|
|
||||||
'/org/freedesktop/Hal/devices/computer')
|
|
||||||
|
|
||||||
# Listen for HAL events
|
|
||||||
self.system_bus.add_signal_receiver(self.handle_hal_event,
|
|
||||||
dbus_interface='org.freedesktop.Hal.Device',
|
|
||||||
path_keyword='path',
|
|
||||||
member_keyword='member')
|
|
||||||
|
|
||||||
# For now I only care about battery 0.
|
|
||||||
batteries = self.hal_manager.FindDeviceByCapability('battery',
|
|
||||||
dbus_interface='org.freedesktop.Hal.Manager')
|
|
||||||
if batteries:
|
|
||||||
bat = self.system_bus.get_object('org.freedesktop.Hal',
|
|
||||||
batteries[0])
|
|
||||||
self.battery = dbus.Interface(bat,
|
|
||||||
dbus_interface='org.freedesktop.Hal.Device')
|
|
||||||
else:
|
|
||||||
self.battery = None
|
|
||||||
|
|
||||||
# Audio mixer, if we have the ALSA module installed.
|
|
||||||
if alsaaudio:
|
|
||||||
try:
|
|
||||||
self.mixer = alsaaudio.Mixer()
|
|
||||||
except alsaaudio.ALSAAudioError:
|
|
||||||
# Some weird mixers have no Master control (eg. Mac Mini)
|
|
||||||
self.mixer = alsaaudio.Mixer('PCM')
|
|
||||||
except ImportError:
|
|
||||||
self.mixer = None
|
|
||||||
else:
|
|
||||||
self.mixer = None
|
|
||||||
|
|
||||||
# How many debian packages can be upgraded?
|
|
||||||
self.upgradable = []
|
|
||||||
|
|
||||||
# All my children
|
|
||||||
self.pids = Set()
|
|
||||||
|
|
||||||
def run(self, file, *args):
|
|
||||||
pid = os.spawnlp(os.P_NOWAIT, file, file, *args)
|
|
||||||
self.pids.add(pid)
|
|
||||||
|
|
||||||
def battery_level(self):
|
|
||||||
if self.battery:
|
|
||||||
return self.battery.GetProperty('battery.charge_level.percentage')
|
|
||||||
|
|
||||||
def battery_capacity_state(self):
|
|
||||||
if self.battery:
|
|
||||||
try:
|
|
||||||
return self.battery.GetProperty('battery.charge_level.capacity_state')
|
|
||||||
except dbus.exceptions.DBusException:
|
|
||||||
bat = self.battery_level()
|
|
||||||
if bat > 20:
|
|
||||||
return 'ok'
|
|
||||||
else:
|
|
||||||
return 'battery low'
|
|
||||||
|
|
||||||
def suspend(self, num_secs_to_wakeup=0):
|
|
||||||
def ignore(*d):
|
|
||||||
pass
|
|
||||||
|
|
||||||
self.run('screenlock')
|
|
||||||
self.hal_computer.Suspend(num_secs_to_wakeup,
|
|
||||||
dbus_interface='org.freedesktop.Hal.Device.SystemPowerManagement',
|
|
||||||
reply_handler=ignore,
|
|
||||||
error_handler=ignore)
|
|
||||||
|
|
||||||
def muted(self):
|
|
||||||
if self.mixer:
|
|
||||||
try:
|
|
||||||
return self.mixer.getmute()[0]
|
|
||||||
except alsaaudio.ALSAAudioError:
|
|
||||||
pass
|
|
||||||
raise ValueError('No mute control')
|
|
||||||
|
|
||||||
def toggle_mute(self):
|
|
||||||
try:
|
|
||||||
mute = self.muted()
|
|
||||||
self.mixer.setmute(not mute)
|
|
||||||
self.update()
|
|
||||||
except ValueError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
@dbus.service.method('org.woozle.Status',
|
|
||||||
in_signature='d')
|
|
||||||
def adjust_volume(self, adj):
|
|
||||||
if self.mixer:
|
|
||||||
vol = self.mixer.getvolume()[0]
|
|
||||||
vol += adj
|
|
||||||
vol = min(vol, 100)
|
|
||||||
vol = max(vol, 0)
|
|
||||||
self.mixer.setvolume(vol)
|
|
||||||
self.update()
|
|
||||||
|
|
||||||
def volume(self):
|
|
||||||
if self.mixer:
|
|
||||||
try:
|
|
||||||
mute = self.muted()
|
|
||||||
except ValueError:
|
|
||||||
mute = False
|
|
||||||
if mute:
|
|
||||||
return '--'
|
|
||||||
else:
|
|
||||||
return str(self.mixer.getvolume()[0])
|
|
||||||
|
|
||||||
def handle_button_pressed(self, button, path):
|
|
||||||
if button == 'lid':
|
|
||||||
lid = self.system_bus.get_object('org.freedesktop.Hal',
|
|
||||||
path)
|
|
||||||
if (lid.GetProperty('button.state.value',
|
|
||||||
dbus_interface='org.freedesktop.Hal.Device') and
|
|
||||||
not os.path.exists(os.path.expanduser('~/nosusp'))):
|
|
||||||
self.suspend()
|
|
||||||
elif button == 'mute':
|
|
||||||
self.toggle_mute()
|
|
||||||
elif button == 'volume-down':
|
|
||||||
self.adjust_volume(-5)
|
|
||||||
elif button == 'volume-up':
|
|
||||||
self.adjust_volume(+5)
|
|
||||||
elif button == 'sleep':
|
|
||||||
self.suspend()
|
|
||||||
elif self.debug:
|
|
||||||
self.update('button pressed: %s' % button)
|
|
||||||
|
|
||||||
def handle_property_modified(self, name, added, removed):
|
|
||||||
if name == 'battery.charge_level.percentage':
|
|
||||||
self.update()
|
|
||||||
elif name.startswith('battery.'):
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
self.update('property modified: %s' % name)
|
|
||||||
|
|
||||||
def handle_hal_event(self, *d, **k):
|
|
||||||
member = k.get('member')
|
|
||||||
if member == 'Condition':
|
|
||||||
if d[0] == 'ButtonPressed':
|
|
||||||
self.handle_button_pressed(d[1], k.get('path'))
|
|
||||||
elif member == 'PropertyModified':
|
|
||||||
assert int(d[0]) == len(d[1])
|
|
||||||
for p in d[1]:
|
|
||||||
self.handle_property_modified(*p)
|
|
||||||
else:
|
|
||||||
self.update('%s: %s' % (d, kwargs))
|
|
||||||
|
|
||||||
def update(self, msg=None):
|
|
||||||
out = []
|
|
||||||
if msg:
|
|
||||||
out.append(color('green', msg))
|
|
||||||
|
|
||||||
if self.upgradable:
|
|
||||||
out.append(color('cyan', '%d upgradable packages' % self.upgradable))
|
|
||||||
|
|
||||||
la = file('/proc/loadavg').read()
|
|
||||||
load = la.split()[0]
|
|
||||||
if float(load) > 0.2:
|
|
||||||
out.append('L %s' % load)
|
|
||||||
|
|
||||||
vol = self.volume()
|
|
||||||
if vol:
|
|
||||||
out.append('V %s' % vol)
|
|
||||||
|
|
||||||
bat = self.battery_level()
|
|
||||||
if bat:
|
|
||||||
out.append('B %s%%' % bat)
|
|
||||||
|
|
||||||
cap_state = self.battery_capacity_state()
|
|
||||||
if cap_state != 'ok':
|
|
||||||
out.append(color('green', cap))
|
|
||||||
|
|
||||||
out.append(time.strftime('%b %e %l:%M%P'))
|
|
||||||
|
|
||||||
print ' '.join(out)
|
|
||||||
sys.stdout.flush()
|
|
||||||
|
|
||||||
try:
|
|
||||||
pid, status = os.waitpid(0, os.WNOHANG)
|
|
||||||
self.pids.remove(pid)
|
|
||||||
except (OSError, KeyError):
|
|
||||||
pass
|
|
||||||
|
|
||||||
return True
|
|
||||||
|
|
||||||
@dbus.service.method('org.woozle.Status',
|
|
||||||
in_signature='s')
|
|
||||||
def notice(self, msg):
|
|
||||||
self.update(msg)
|
|
||||||
|
|
||||||
@dbus.service.method('org.woozle.Status',
|
|
||||||
in_signature='')
|
|
||||||
def restart(self):
|
|
||||||
re_exec()
|
|
||||||
|
|
||||||
@dbus.service.method('org.woozle.Status',
|
|
||||||
in_signature='b')
|
|
||||||
def set_debug(self, debug):
|
|
||||||
self.debug = debug
|
|
||||||
|
|
||||||
def debcheck(self):
|
|
||||||
# I used to do this in a thread. Unfortunately, this expensive
|
|
||||||
# operation kept the entire apt cache around in RAM forever,
|
|
||||||
# making the status program the biggest memory user on my entire
|
|
||||||
# machine. That offends my sense of aesthetics, so now we fork
|
|
||||||
# and read from a pipe.
|
|
||||||
def cb(source, cb_condition):
|
|
||||||
s = source.recv(8192)
|
|
||||||
self.upgradable = int(s)
|
|
||||||
return False
|
|
||||||
|
|
||||||
a,b = socket.socketpair()
|
|
||||||
if os.fork():
|
|
||||||
gobject.io_add_watch(a, gobject.IO_IN, cb)
|
|
||||||
else:
|
|
||||||
l = [p for p in apt.Cache() if p.isUpgradable]
|
|
||||||
b.send(str(len(l)))
|
|
||||||
sys.exit(0)
|
|
||||||
return True
|
|
||||||
|
|
||||||
def start(self):
|
|
||||||
self.update()
|
|
||||||
gobject.timeout_add(12 * 1000, self.update)
|
|
||||||
if apt:
|
|
||||||
self.debcheck()
|
|
||||||
gobject.timeout_add(900 * 1000, self.debcheck)
|
|
||||||
|
|
||||||
|
|
||||||
def re_exec(*ign):
|
|
||||||
os.execv(sys.argv[0], sys.argv)
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
import signal
|
|
||||||
import gobject
|
|
||||||
import dbus.mainloop.glib
|
|
||||||
|
|
||||||
# Set up main loop
|
|
||||||
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
|
|
||||||
|
|
||||||
# kill -HUP makes this re-exec itself
|
|
||||||
signal.signal(signal.SIGHUP, re_exec)
|
|
||||||
|
|
||||||
# Register ourselves as a service
|
|
||||||
session_bus = dbus.SessionBus()
|
|
||||||
dbus_name = dbus.service.BusName('org.woozle.Status',
|
|
||||||
session_bus)
|
|
||||||
|
|
||||||
# Our founder
|
|
||||||
s = Status(session_bus, '/org/woozle/Status')
|
|
||||||
|
|
||||||
# Go!
|
|
||||||
loop = gobject.MainLoop()
|
|
||||||
s.start()
|
|
||||||
loop.run()
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
|
@ -1,130 +0,0 @@
|
||||||
#!/usr/bin/python
|
|
||||||
|
|
||||||
"""watch.py -- Web site change notification tool
|
|
||||||
Author: Neale Pickett <neale@woozle.org>
|
|
||||||
Time-stamp: <2007-09-19 15:00:43 neale>
|
|
||||||
|
|
||||||
Usage: urlwatch [-c|--config WATCHRC]
|
|
||||||
|
|
||||||
This is something you can run from a cron job to notify you of changes
|
|
||||||
to a web site. You just set up a ~/.watchrc file, and run watcher.py
|
|
||||||
from cron. It mails you when a page has changed.
|
|
||||||
|
|
||||||
I use this to check for new software releases on sites that just change
|
|
||||||
web pages; my wife uses it to check pages for classes she's in.
|
|
||||||
|
|
||||||
You'll want a ~/.watchrc that looks something like this:
|
|
||||||
|
|
||||||
to: your.email.address@example.com
|
|
||||||
http://www.example.com/path/to/some/page.html
|
|
||||||
|
|
||||||
The 'to:' line tells watch.py where to send change notification email.
|
|
||||||
You can also specify 'from:' for an address the message should come from
|
|
||||||
(defaults to whatever to: is), and 'host:' for what SMTP server to send
|
|
||||||
the message through (defaults to localhost).
|
|
||||||
|
|
||||||
When watch.py checks a URL for the first time, it will send you a
|
|
||||||
message (so you know it's working) and write some funny characters after
|
|
||||||
the URL in the .watchrc file. This is normal--watch.py uses these
|
|
||||||
characters to remember what the page looked like the last time it
|
|
||||||
checked.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
import os
|
|
||||||
import urllib2 as urllib
|
|
||||||
import sha
|
|
||||||
import smtplib
|
|
||||||
import sys
|
|
||||||
|
|
||||||
host = 'localhost'
|
|
||||||
fromaddr = None
|
|
||||||
toaddr = None
|
|
||||||
|
|
||||||
rc = os.path.expanduser('~/.watchrc')
|
|
||||||
|
|
||||||
def usage(errmsg=None):
|
|
||||||
if errmsg:
|
|
||||||
print "error: %s" % errmsg
|
|
||||||
print
|
|
||||||
|
|
||||||
print globals()['__doc__']
|
|
||||||
|
|
||||||
if errmsg:
|
|
||||||
sys.exit(1)
|
|
||||||
sys.exit(0)
|
|
||||||
|
|
||||||
def myhash(data):
|
|
||||||
return sha.new(data).hexdigest()
|
|
||||||
|
|
||||||
def notify(fromaddr, toaddr, url):
|
|
||||||
msg = """From: URL Watcher <%(from)s>
|
|
||||||
To: %(to)s
|
|
||||||
Subject: %(url)s changed
|
|
||||||
|
|
||||||
%(url)s has changed!
|
|
||||||
""" % {'from': fromaddr,
|
|
||||||
'to': toaddr,
|
|
||||||
'url': url}
|
|
||||||
s = smtplib.SMTP(host)
|
|
||||||
s.sendmail(fromaddr, [toaddr], msg)
|
|
||||||
s.quit()
|
|
||||||
|
|
||||||
def watch(rcfile):
|
|
||||||
global host, fromaddr, toaddr
|
|
||||||
|
|
||||||
f = open(rcfile)
|
|
||||||
outlines = []
|
|
||||||
for line in f.xreadlines():
|
|
||||||
if line[0] == '#':
|
|
||||||
continue
|
|
||||||
|
|
||||||
line = line.strip()
|
|
||||||
if not line:
|
|
||||||
continue
|
|
||||||
|
|
||||||
splits = line.split(' ', 1)
|
|
||||||
url = splits[0]
|
|
||||||
if url == 'from:':
|
|
||||||
fromaddr = splits[1]
|
|
||||||
elif url == 'to:':
|
|
||||||
toaddr = splits[1]
|
|
||||||
if not fromaddr:
|
|
||||||
fromaddr = toaddr
|
|
||||||
elif url == 'mailhost:':
|
|
||||||
host = splits[1]
|
|
||||||
else:
|
|
||||||
if (not fromaddr) or (not toaddr):
|
|
||||||
raise ValueError("must set to: before any urls")
|
|
||||||
page = urllib.urlopen(url).read()
|
|
||||||
ph = myhash(page)
|
|
||||||
|
|
||||||
try:
|
|
||||||
h = splits[1]
|
|
||||||
except IndexError:
|
|
||||||
h = None
|
|
||||||
if h != ph:
|
|
||||||
notify(fromaddr, toaddr, url)
|
|
||||||
line = '%s %s' % (url, ph)
|
|
||||||
outlines.append(line)
|
|
||||||
|
|
||||||
f.close()
|
|
||||||
|
|
||||||
f = open(rcfile, 'w')
|
|
||||||
f.write('\n'.join(outlines) + '\n')
|
|
||||||
f.close()
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
import getopt
|
|
||||||
import sys
|
|
||||||
|
|
||||||
opts, args = getopt.getopt(sys.argv[1:], 'c:h', ['config=', 'help'])
|
|
||||||
for k,v in opts:
|
|
||||||
if k in ('-c', '--config'):
|
|
||||||
rc = v
|
|
||||||
elif k in ('-h', '--help'):
|
|
||||||
usage()
|
|
||||||
else:
|
|
||||||
usage("Unknown option: %s" % k)
|
|
||||||
|
|
||||||
watch(rc)
|
|
107
src/xss.md
|
@ -1,107 +0,0 @@
|
||||||
Title: xss: X Screensaver Construction Kit
|
|
||||||
Author: Neale Pickett <neale@woozle.org>
|
|
||||||
|
|
||||||
[xss](http://woozle.org/neale/g.cgi/x11/xss) is a suite of X screensaver
|
|
||||||
utilities. You can use shell scripts to glue the tools together to
|
|
||||||
build your own screen saver and/or locker. You can use any
|
|
||||||
`xscreensaver` hack instead of the built-in `magic` hack, or you can use
|
|
||||||
`xlock` if you prefer.
|
|
||||||
|
|
||||||
|
|
||||||
The programs
|
|
||||||
------------
|
|
||||||
|
|
||||||
`xss` uses the decades-old MIT-SCREEN-SAVER extension to launch a
|
|
||||||
program when the X server turns on the built-in screen saver. Unlike
|
|
||||||
`xautolock`, `xss` blocks until the X server says it's time to do
|
|
||||||
something.
|
|
||||||
|
|
||||||
`xsswin` makes a full-screen black window and runs some other program,
|
|
||||||
passing along the window ID in the environment (`$XSS_WINDOW`) and
|
|
||||||
possibly as an argument (`XSS_WINDOW` in argv is replaced with the ID).
|
|
||||||
|
|
||||||
`xkeygrab` grabs the keyboard and mouse, and echoes all typed lines to
|
|
||||||
stdout.
|
|
||||||
|
|
||||||
`xcursorpos` prints out the x and y coordinates of the cursor.
|
|
||||||
|
|
||||||
`xbell` sounds the X server's bell.
|
|
||||||
|
|
||||||
`magic` is a reimplementation of the "magic" screen saver from After
|
|
||||||
Dark. It might look weird at 8bpp.
|
|
||||||
|
|
||||||
|
|
||||||
Examples
|
|
||||||
--------
|
|
||||||
|
|
||||||
Tell the X server to launch the screen saver after 90 seconds idle:
|
|
||||||
|
|
||||||
$ xset s 90
|
|
||||||
|
|
||||||
Run like `xautolock`:
|
|
||||||
|
|
||||||
$ xss xlock -mode qix &
|
|
||||||
|
|
||||||
Just run a screen saver, don't lock
|
|
||||||
|
|
||||||
$ xss -w /usr/lib/xscreensaver/deco -window-id XSS_WINDOW &
|
|
||||||
|
|
||||||
Launch a program called "screenlock" when you're idle:
|
|
||||||
|
|
||||||
$ xss screenlock &
|
|
||||||
|
|
||||||
An simple "screenlock" script:
|
|
||||||
|
|
||||||
#! /bin/sh
|
|
||||||
|
|
||||||
xsswin magic XSS_WINDOW & pid=$!
|
|
||||||
xkeygrab | (while read l; do [ "$l" != "secret" ] && break; done)
|
|
||||||
kill $pid
|
|
||||||
|
|
||||||
A more complex "screenlock" script which locks the screen awaiting a
|
|
||||||
pass phrase with the right md5 checksum. After 4 seconds of being
|
|
||||||
locked, it pauses mpd (iff it was playing). When the screen is
|
|
||||||
unlocked, mpd is resumed (iff it was playing beforehand). The script
|
|
||||||
won't lock if the cursor's at the top of the screen.
|
|
||||||
|
|
||||||
#! /bin/sh
|
|
||||||
|
|
||||||
xcursorpos | (read x y; [ $y -lt 20 ]) && exit 0
|
|
||||||
mpc | fgrep -q '[playing]' && playing=1
|
|
||||||
xsswin magic XSS_WINDOW 2>/dev/null & xsswin=$!
|
|
||||||
(sleep 4; [ $playing ] && kill -0 $xsswin 2>/dev/null && mpc --no-status pause) &
|
|
||||||
xkeygrab | (
|
|
||||||
while read l; do
|
|
||||||
md5s=$(echo -n $l | md5sum | cut -d\ -f1)
|
|
||||||
if [ $md5s = 'a37c87558d98e9fe0484e09070268be1' ]; then
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
xbell
|
|
||||||
done
|
|
||||||
)
|
|
||||||
kill $xsswin
|
|
||||||
[ $playing ] && mpc --no-status play
|
|
||||||
|
|
||||||
|
|
||||||
Download
|
|
||||||
--------
|
|
||||||
|
|
||||||
You can [browse the source](http://woozle.org/neale/g.cgi/x11/xss),
|
|
||||||
download a [tarball of the latest
|
|
||||||
commit](http://woozle.org/neale/g.cgi/x11/xss/snapshot/xss-master.tar.gz), or clone the
|
|
||||||
git repository:
|
|
||||||
|
|
||||||
git clone http://woozle.org/~neale/projects/x11/xss
|
|
||||||
|
|
||||||
|
|
||||||
History
|
|
||||||
-------
|
|
||||||
|
|
||||||
AIX apparently had something also called `xss` which did almost exactly
|
|
||||||
what mine does, but with command-line options. `magic` is similar to
|
|
||||||
the `qix` hack from xscreensaver and xlock. I'm not aware of anything
|
|
||||||
else like the rest of the programs, which is why I wrote them.
|
|
||||||
|
|
||||||
I lifted some code from `beforelight` from the X11 distribution, and
|
|
||||||
from `slock` from [suckless.org](http://suckless.org/). Both have a
|
|
||||||
BSD/X11-like license.
|
|
112
trigger.cgi.go
|
@ -1,112 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"github.com/coduno/netrc"
|
|
||||||
"github.com/jsgoecke/tesla"
|
|
||||||
"log"
|
|
||||||
"net/http"
|
|
||||||
"net/http/cgi"
|
|
||||||
"net/smtp"
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
// These are not actually secrets, and get posted around various forums
|
|
||||||
const clientId = "81527cff06843c8634fdc09e8ac0abefb46ac849f38fe1e431c2ef2106796384"
|
|
||||||
const clientSec = "c7257eb71a564034f9419ee651c7d0e5f7aa6bfbd18bafb5c5c033b093bb2fa3"
|
|
||||||
|
|
||||||
func Kersplode(section string, error string, w http.ResponseWriter) {
|
|
||||||
errtxt := fmt.Sprintf("%s: %s", section, error)
|
|
||||||
|
|
||||||
http.Error(w, errtxt, 500)
|
|
||||||
|
|
||||||
// Send an email
|
|
||||||
c, _ := smtp.Dial("localhost:25")
|
|
||||||
defer c.Close()
|
|
||||||
c.Mail("neale@woozle.org")
|
|
||||||
c.Rcpt("dartcatcher@gmail.com")
|
|
||||||
wc, _ := c.Data()
|
|
||||||
defer wc.Close()
|
|
||||||
fmt.Fprintln(wc, "From: IFTTT Trigger <neale@woozle.org>")
|
|
||||||
fmt.Fprintln(wc, "To: Neale Pickett <dartcatcher@gmail.com>")
|
|
||||||
fmt.Fprintln(wc, "Subject: IFTTT trigger error")
|
|
||||||
fmt.Fprintln(wc, "")
|
|
||||||
fmt.Fprintln(wc, "Hi, this is the IFTTT trigger at woozle.org.")
|
|
||||||
fmt.Fprintln(wc, "I'm sorry to say that something went wrong with a recent request.")
|
|
||||||
fmt.Fprintln(wc, "Here is the text of the error:")
|
|
||||||
fmt.Fprintln(wc, "")
|
|
||||||
fmt.Fprintln(wc, errtxt)
|
|
||||||
}
|
|
||||||
|
|
||||||
type Handler struct {
|
|
||||||
cgi.Handler
|
|
||||||
}
|
|
||||||
|
|
||||||
func getSecret(host string) netrc.Entry {
|
|
||||||
n, _ := netrc.Parse()
|
|
||||||
return n[host]
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h Handler) TriggerHvac(w http.ResponseWriter, r *http.Request) {
|
|
||||||
secret := getSecret("teslamotors.com")
|
|
||||||
auth := tesla.Auth{
|
|
||||||
ClientID: clientId,
|
|
||||||
ClientSecret: clientSec,
|
|
||||||
Email: secret.Login,
|
|
||||||
Password: secret.Password,
|
|
||||||
}
|
|
||||||
cli, err := tesla.NewClient(&auth)
|
|
||||||
if err != nil {
|
|
||||||
Kersplode("tesla.NewClient", err.Error(), w);
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
vehicles, err := cli.Vehicles()
|
|
||||||
if err != nil {
|
|
||||||
Kersplode("cli.Vehicles", err.Error(), w);
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
vehicle := vehicles[0]
|
|
||||||
if _, err := vehicle.Wakeup(); err != nil {
|
|
||||||
Kersplode("vehicle.Wakeup", err.Error(), w);
|
|
||||||
return
|
|
||||||
}
|
|
||||||
for i := 0; i < 5; i += 1 {
|
|
||||||
err := vehicle.StartAirConditioning()
|
|
||||||
if err == nil {
|
|
||||||
break
|
|
||||||
} else if (i == 5) {
|
|
||||||
Kersplode("vehicle.StartAirConditioning", err.Error(), w);
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
http.Error(w, "OK", 200)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|
||||||
secret := getSecret("host:trigger.cgi")
|
|
||||||
if r.FormValue("auth") != secret.Password {
|
|
||||||
http.Error(w, "Invalid authtok", 401)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
switch trigger := r.FormValue("trigger"); trigger {
|
|
||||||
case "hvac":
|
|
||||||
h.TriggerHvac(w, r)
|
|
||||||
default:
|
|
||||||
http.Error(w, "Undefined trigger", 422)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
log.SetOutput(os.Stdout)
|
|
||||||
log.SetFlags(0)
|
|
||||||
log.SetPrefix("Status: 500 CGI Go Boom\nContent-type: text/plain\n\nERROR: ")
|
|
||||||
os.Setenv("HOME", "/home/neale") // required by netrc library
|
|
||||||
h := Handler{}
|
|
||||||
if err := cgi.Serve(h); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|