Pulled all of src

This commit is contained in:
Neale Pickett 2017-07-09 21:10:18 +00:00
parent d746005b1f
commit 36b2855d3e
88 changed files with 0 additions and 5422 deletions

View File

Before

Width:  |  Height:  |  Size: 306 KiB

After

Width:  |  Height:  |  Size: 306 KiB

View File

Before

Width:  |  Height:  |  Size: 120 KiB

After

Width:  |  Height:  |  Size: 120 KiB

View File

Before

Width:  |  Height:  |  Size: 1.2 MiB

After

Width:  |  Height:  |  Size: 1.2 MiB

View File

Before

Width:  |  Height:  |  Size: 400 KiB

After

Width:  |  Height:  |  Size: 400 KiB

View File

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 38 KiB

View File

Before

Width:  |  Height:  |  Size: 729 KiB

After

Width:  |  Height:  |  Size: 729 KiB

View File

Before

Width:  |  Height:  |  Size: 1.1 MiB

After

Width:  |  Height:  |  Size: 1.1 MiB

View File

Before

Width:  |  Height:  |  Size: 452 KiB

After

Width:  |  Height:  |  Size: 452 KiB

View File

Before

Width:  |  Height:  |  Size: 95 KiB

After

Width:  |  Height:  |  Size: 95 KiB

View File

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 44 KiB

View File

Before

Width:  |  Height:  |  Size: 97 KiB

After

Width:  |  Height:  |  Size: 97 KiB

View File

Before

Width:  |  Height:  |  Size: 61 KiB

After

Width:  |  Height:  |  Size: 61 KiB

View File

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 31 KiB

View File

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

View File

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB

View File

Before

Width:  |  Height:  |  Size: 52 KiB

After

Width:  |  Height:  |  Size: 52 KiB

View File

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

Before

Width:  |  Height:  |  Size: 980 KiB

After

Width:  |  Height:  |  Size: 980 KiB

View File

Before

Width:  |  Height:  |  Size: 87 KiB

After

Width:  |  Height:  |  Size: 87 KiB

View File

Before

Width:  |  Height:  |  Size: 8.3 KiB

After

Width:  |  Height:  |  Size: 8.3 KiB

View File

Before

Width:  |  Height:  |  Size: 158 KiB

After

Width:  |  Height:  |  Size: 158 KiB

View File

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

108
g.cgi.go
View File

@ -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()
}
}

View File

@ -1 +0,0 @@
COPY += src/9wm/9wm.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 75 KiB

View File

@ -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).

View File

@ -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 $< $@

View File

@ -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.

View File

@ -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))))

View File

@ -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>&lt;?scm scheme-code ?&gt;</dt>
<dd>Evaluates scheme-code, discarding value of the last expression</dd>
<dt>&lt;?scm:d scheme-code ?&gt;</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.

View File

@ -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/)

View File

@ -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>&lt;?scm scheme-code ?&gt;</dt>
<dd>Evaluates scheme-code, discarding value of the last expression</dd>
<dt>&lt;?scm:d scheme-code ?&gt;</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

View File

@ -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** &lt;= **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>

View File

@ -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)

View File

@ -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)

Binary file not shown.

Binary file not shown.

View File

@ -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)

View File

@ -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

View File

@ -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 },
};

View File

@ -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 ->
()

View 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

View File

@ -1,2 +0,0 @@
Title: Miscellaneous hacks

Binary file not shown.

View File

@ -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()

View File

@ -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)

Binary file not shown.

Binary file not shown.

View File

@ -1,4 +0,0 @@
index.html: - 12dab84c3ad5b0dba380c051471c14d6 - -
index.ptml: 1042003175 - 39a0ed00cb554392574b5955dbdc0af9 -
links.html: - 962d7fd4c69ea67cfeb1d0cc88e892a6 - -
links.ptml: 1041913579 - bd8a21beca5f285bf5e8ba50e86f340f -

View File

@ -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

View File

@ -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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

View File

@ -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:

View File

@ -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

View File

@ -1,5 +0,0 @@
Title: PostScript Hacks
One morning I woke up wondering, "how difficult could PostScript really be?"
Answer: Not very.

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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>.

View File

@ -1 +0,0 @@
../pysieved.mdwn

View File

@ -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>'

View File

@ -1,3 +0,0 @@
Title: Python hacks
Here's some junk I did in Python.

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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.'

View File

@ -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('"', '&quot;')
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()

View File

@ -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()

View File

@ -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()

View File

@ -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()

View File

@ -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)

View File

@ -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.

View File

@ -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)
}
}