mirror of
git://git.psyced.org/git/psyced
synced 2024-08-15 03:25:10 +00:00
let the past begone in cvs land. welcome to igit igit!
This commit is contained in:
commit
4e601cf1c7
509 changed files with 77963 additions and 0 deletions
361
utility/INI.pm
Normal file
361
utility/INI.pm
Normal file
|
|
@ -0,0 +1,361 @@
|
|||
# $Id: INI.pm,v 1.34 2006/06/14 16:27:23 lynx Exp $
|
||||
package INI;
|
||||
require Tie::Hash;
|
||||
@ISA = (Tie::ExtraHash);
|
||||
|
||||
use strict;
|
||||
|
||||
# lynx: you propably really want that _all_ tied INI hashes in a Perl ...
|
||||
# "session" share the verbosity-setting, but would you mind if i did that some
|
||||
# more OO, on a per hash basis?
|
||||
my $verbose = 0;
|
||||
# saga: i don't need this to be any better but if your heart aches, go ahead
|
||||
|
||||
sub HASH { 0 }
|
||||
sub FNAME { 1 }
|
||||
sub CHANGED { 2 }
|
||||
sub MAX { 3 }
|
||||
sub JANITOR { 4 }
|
||||
|
||||
sub import {
|
||||
$_ = join ' ', @_;
|
||||
$verbose = /\bverbose\b/i;
|
||||
}
|
||||
|
||||
sub iniSane {
|
||||
my $self = shift;
|
||||
my $key = shift;
|
||||
my $value = shift;
|
||||
|
||||
if (defined $value && $key !~ /^.+?_.+/) {
|
||||
die "'$key' is not a valid key";
|
||||
}
|
||||
|
||||
if ($key =~ /[\r\n\s]/) {
|
||||
die "invalid characters in key '$key'";
|
||||
}
|
||||
|
||||
if (defined $value && $value =~ /[\r\n]/) {
|
||||
die "invalid characters in value for '$key'";
|
||||
}
|
||||
}
|
||||
|
||||
# TODO:: make janitor a more swanky datastructure.
|
||||
# like $janitor->{'_foo'}->[CHILDREN]->{'_bar'}->[COUNT]
|
||||
# instead of $janitor->{'_foo_bar'}.
|
||||
# on the other hand, we'd probably need entries for levels with a count of 0,
|
||||
# if they got child levels. hm.
|
||||
# it'd eat more memory (ok, we don't have to care for that), and.. i'm not even
|
||||
# sure if it would be faster. probably not. same operations, splitting on "_",
|
||||
# and we'd have to walk through the structure beginning from the leftmost level
|
||||
# of a value to the right every time while we might find our levels earlier
|
||||
# if coming from the right (.. trying _foo_bar_some before _foo_bar before
|
||||
# _foo) in the average case. we'll at least in some cases, while we always need
|
||||
# to walk through from the leftmost level if doing that tree specified above.
|
||||
# hm. i'll have to think that over.
|
||||
sub iniJanDel {
|
||||
my $self = shift;
|
||||
my $key = shift;
|
||||
my $janitor = $self->[JANITOR];
|
||||
my $max = $self->[MAX];
|
||||
|
||||
while ($key =~ s/(.+)_.*/$1/) {
|
||||
if ($janitor->{$key}-- == $max) {
|
||||
for (my $i = 1; $i < $max; $i++) {
|
||||
$self->iniJanAdd($key);
|
||||
}
|
||||
last;
|
||||
}
|
||||
last if $janitor->{$key} >= $max;
|
||||
delete $janitor->{$key} unless $janitor->{$key};
|
||||
}
|
||||
}
|
||||
|
||||
sub iniJanAdd {
|
||||
my $self = shift;
|
||||
my $key = shift;
|
||||
my $janitor = $self->[JANITOR];
|
||||
my $max = $self->[MAX];
|
||||
|
||||
while ($key =~ s/(.+)_.*/$1/) {
|
||||
if (++$janitor->{$key} == $max) {
|
||||
for (my $i = 1; $i < $max; $i++) {
|
||||
$self->iniJanDel($key);
|
||||
}
|
||||
last;
|
||||
}
|
||||
last if $janitor->{$key} > $max;
|
||||
}
|
||||
}
|
||||
|
||||
sub iniParse {
|
||||
my $self = shift;
|
||||
my $fname = $self->[FNAME];
|
||||
my $max = $self->[MAX];
|
||||
my $hash = $self->[HASH];
|
||||
my $janitor = $self->[JANITOR];
|
||||
my $section;
|
||||
|
||||
open(FILE, '<', $fname) || die $!;
|
||||
while (<FILE>) {
|
||||
chomp;
|
||||
|
||||
next if /^\s*(?:$|;)/;
|
||||
|
||||
if (/^\[(.+?)\]\s*(?:;.*)?$/) {
|
||||
$self->iniSane($1);
|
||||
$section = $1;
|
||||
print STDERR "$section " if $verbose;
|
||||
next;
|
||||
}
|
||||
|
||||
if ($section && /^(.+?)\s*=\s*((?>(?:(?<=(?<!\\)\\)(?:\\\\)*["\s;\\]|[^"\s\\;]|\s(?!\s*(?:;|$))|\\(?!$))*)|"(?:(?<=(?<!\\)\\)(?:\\\\)*["\s]|[^"])*?(?:(?<!\\)(?:\\\\)+|(?<!\\))")\s*(?:;.*)?$/) {
|
||||
my $t = join('', $section, $1);
|
||||
my $t2 = $2;
|
||||
if (substr($t2, 0, 1) eq '"') {
|
||||
$t2 = substr($t2, 1, length($t2)-2);
|
||||
}
|
||||
$t2 =~ s/\\(.)/$1/g;
|
||||
$self->iniSane($t, $t2);
|
||||
$hash->{$t} = $t2;
|
||||
# print STDERR "$t is $t2\n";
|
||||
$self->iniJanAdd($t) if $max;
|
||||
next;
|
||||
}
|
||||
|
||||
die "failed in parsing from '$fname':\n$_\n(line $.)" if ($_);
|
||||
}
|
||||
close(FILE);
|
||||
}
|
||||
|
||||
sub iniSerialize {
|
||||
my $self = shift;
|
||||
my $hash = $self->[HASH];
|
||||
my $janitor = $self->[JANITOR];
|
||||
my $max = $self->[MAX];
|
||||
my %shash = ();
|
||||
my $nottop;
|
||||
my $res = ";this is an automatically generated file, you may change it as "
|
||||
. "you like, but\n"
|
||||
. ";keep in mind that your comments will be destroyed if a "
|
||||
. "config tool makes some\n"
|
||||
. ";changes.\n\n";
|
||||
|
||||
foreach (keys %$hash) {
|
||||
my $sec = $_;
|
||||
my $key = "";
|
||||
my ($section, $buf);
|
||||
|
||||
while ($max && $sec =~ s/(.+)(_.*)/$1/) {
|
||||
$key = $2 . $key;
|
||||
if ($janitor->{$sec} >= $max) {
|
||||
$section = $sec;
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
unless ($section) {
|
||||
/(.+?)(_.*)/;
|
||||
$section = $1;
|
||||
$key = $2;
|
||||
}
|
||||
|
||||
$shash{$section} = {} unless exists $shash{$section};
|
||||
|
||||
$buf = $hash->{$_};
|
||||
$buf =~ s/\\/\\\\/g;
|
||||
$buf =~ s/"/\\"/g;
|
||||
if ($buf =~ /(?:^\s|\s$|;)/) {
|
||||
$buf = join('', '"', $buf, '"');
|
||||
}
|
||||
|
||||
$shash{$section}->{$key} = $buf;
|
||||
}
|
||||
|
||||
foreach my $base (sort keys %shash) {
|
||||
if ($nottop) {
|
||||
$res .= "\n";
|
||||
} else {
|
||||
$nottop = 1;
|
||||
}
|
||||
|
||||
$res .= join('', '[', $base, ']', "\n");
|
||||
|
||||
foreach my $child (keys %{$shash{$base}}) {
|
||||
$res .= join(' ', $child, '=', $shash{$base}->{$child});
|
||||
$res .= "\n";
|
||||
}
|
||||
}
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
sub TIEHASH {
|
||||
my $pkg = shift;
|
||||
my $fname = shift || die 'NO FILENAME PROVIDED';
|
||||
my $max = shift;
|
||||
my $self = [{}, $fname, 0, $max, {}];
|
||||
|
||||
bless $self, $pkg;
|
||||
|
||||
if (-r $fname) {
|
||||
print STDERR "Loading from $fname:\n" if $verbose;
|
||||
$self->iniParse();
|
||||
print STDERR "\nConfiguration loaded.\n\n" if $verbose;
|
||||
} else {
|
||||
print STDERR "$fname does not exist.\n" if $verbose;
|
||||
}
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub STORE {
|
||||
my $self = shift;
|
||||
my $key = shift;
|
||||
my $value = shift;
|
||||
|
||||
|
||||
#TODO: needs more restrictive checks, (key, value) are valid if they can be
|
||||
#added to the hash.
|
||||
#alternatively keep this somewhat abstract and overload it for psyced config
|
||||
#sanity checks.
|
||||
#oh, i like that.
|
||||
|
||||
$self->iniSane($key, $value);
|
||||
|
||||
$self->[CHANGED] = 1;
|
||||
|
||||
if ($self->[MAX] && !exists $self->[HASH]->{$key}) {
|
||||
$self->iniJanAdd($key);
|
||||
}
|
||||
|
||||
return $self->SUPER::STORE($key, $value);
|
||||
}
|
||||
|
||||
sub DELETE {
|
||||
my $self = shift;
|
||||
my $key = shift;
|
||||
|
||||
if ($self->[MAX] && exists $self->[HASH]->{$key}) {
|
||||
$self->iniJanDel($key);
|
||||
}
|
||||
|
||||
return $self->SUPER::DELETE($key);
|
||||
}
|
||||
|
||||
sub CLEAR {
|
||||
my $self = shift;
|
||||
|
||||
$self->[CHANGED] = 1;
|
||||
$self->[JANITOR] = {};
|
||||
|
||||
return $self->SUPER::CLEAR();
|
||||
}
|
||||
|
||||
sub SCALAR {
|
||||
my $self = shift;
|
||||
|
||||
return $self->iniSerialize();
|
||||
}
|
||||
|
||||
sub UNTIE {
|
||||
my $self = shift;
|
||||
|
||||
return unless $self->[CHANGED];
|
||||
|
||||
open(FILE, '>', $self->[FNAME]) || die $!;
|
||||
print FILE $self->iniSerialize();
|
||||
close(FILE);
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
INI - class definitions for tying .ini-like configuration files as hashes
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
require INI;
|
||||
|
||||
tie(%hash, INI, 'conf.ini', 5);
|
||||
|
||||
if ($hash{'_some_system_setting'} =~ /^y(?:es)$/) {
|
||||
# do something
|
||||
}
|
||||
|
||||
$hash{'_some_system_setting2'} = 12;
|
||||
|
||||
untie %hash;
|
||||
|
||||
=head1 FORMAT DESCRIPTION
|
||||
|
||||
[section] ; comment
|
||||
key = value ; comment
|
||||
key = "value" ; comment
|
||||
; comment
|
||||
(all whitespaces up to here are optional).
|
||||
|
||||
key = \"
|
||||
(value of key will be a quote sign)
|
||||
|
||||
key = \; ; and
|
||||
key = ";"
|
||||
(value of key will will be a semicolon)
|
||||
|
||||
Section- and keynames should start with underscores.
|
||||
|
||||
The section names are just prepended to the key names, so
|
||||
|
||||
[_foo]
|
||||
_bar_snafu = kibo
|
||||
and
|
||||
[_foo_bar]
|
||||
_snafu = kibo
|
||||
define the same (key, value)-tuple.
|
||||
|
||||
=head1 API
|
||||
|
||||
=over
|
||||
|
||||
=item tie(B<HASH>, B<FILE>, B<MAX>)
|
||||
|
||||
Tie B<FILE> to B<HASH>, B<FILE> will be parsed upon tie and fill the hash,
|
||||
contents of B<HASH> will be serialized to B<FILE> on untie.
|
||||
|
||||
B<MAX> is optional and defines when a level counts as full, thus if B<MAX>
|
||||
is set to 3, and you have 3 settings named _foo_bar_something1,
|
||||
_foo_bar_something2 and _foo_bar_something3, they'll be serialized into a
|
||||
|
||||
section [_foo_bar] as _something<digit> = value.
|
||||
|
||||
=item untie(B<HASH>)
|
||||
|
||||
Untie B<HASH>, will be serialized into B<FILE> given in the tie statement if
|
||||
changed.
|
||||
|
||||
Will use B<MAX> (from the tie statement) to find out which levels deserve their
|
||||
own section.
|
||||
|
||||
=item scalar(B<HASH>)
|
||||
|
||||
Returns a string containing B<HASH> serialized into the INI format.
|
||||
You'll most probably never need that for anything but debugging purposes, as
|
||||
B<INI> does serializing into files for you on untie.
|
||||
|
||||
=back
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
L<http://about.psyc.eu/psyced>
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Tobias Josefowitz, <tobij@goodadvice.pages.de>
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
Copyright (c) 2005 Tobias Josefowitz.
|
||||
All rights reserved.
|
||||
|
||||
This program is free software under the GPL.
|
||||
=cut
|
||||
438
utility/Installer.pl
Normal file
438
utility/Installer.pl
Normal file
|
|
@ -0,0 +1,438 @@
|
|||
#!/usr/bin/perl
|
||||
#
|
||||
# new installer in the making
|
||||
# see also http://about.psyc.eu/psyced
|
||||
|
||||
use strict;
|
||||
|
||||
# all of the full screen editing stuff could move into
|
||||
# its appropriate own .pm file ...? there even seems
|
||||
# to be overlap with PSYCion.. nevermind.. :)
|
||||
#
|
||||
use Prompt;
|
||||
|
||||
use Term::Cap;
|
||||
use Term::ANSIColor qw(colored :constants);
|
||||
|
||||
use Data::Dumper;
|
||||
use Storable;
|
||||
use Getopt::Std;
|
||||
|
||||
my $term;
|
||||
my $prompt;
|
||||
my $t; #misc stuff
|
||||
|
||||
my %v;
|
||||
my %opts;
|
||||
|
||||
if (-f '.ser.data') {
|
||||
%v = %{retrieve('.ser.data')};
|
||||
}
|
||||
|
||||
getopt('w', \%opts);
|
||||
|
||||
my %key2name;
|
||||
my %name2key = (
|
||||
'left' => "\e[D",
|
||||
'right' => "\e[C",
|
||||
'down' => "\e[B",
|
||||
'up' => "\e[A",
|
||||
'a-left' => "\e\e[D",
|
||||
'a-right' => "\e\e[C",
|
||||
'a-down' => "\e\e[B",
|
||||
'a-up' => "\e\e[A",
|
||||
'ret' => "\x0d", 'C-m' => "\x0d",
|
||||
'esc' => "\x1b",
|
||||
'c-c' => "\x03",
|
||||
'tab' => "\x09",
|
||||
'bs' => "\x7f",
|
||||
'pu' => "\e[5~",
|
||||
'pd' => "\e[6~",
|
||||
'home' => ["\e[H", "\eO", "\e[1~"],
|
||||
'end' => ["\eOw","\eOe", "\e[4~"],
|
||||
'ins' => "\e[2~",
|
||||
'del' => "\e[3~",
|
||||
'f1' => "\e[11~",
|
||||
'f2' => "\e[12~",
|
||||
'f3' => "\e[13~",
|
||||
'f4' => "\e[14~",
|
||||
'f5' => "\e[15~",
|
||||
'f6' => "\e[17~",
|
||||
'f7' => "\e[18~",
|
||||
'f8' => "\e[19~",
|
||||
'f9' => "\e[20~",
|
||||
'f10' => "\e[21~",
|
||||
'f11' => "\e[23~",
|
||||
'f12' => "\e[24~",
|
||||
'c-a' => "\x01",
|
||||
'c-b' => "\x02",
|
||||
#'c-c' => "\x03",
|
||||
'c-d' => "\x04",
|
||||
'c-e' => "\x05",
|
||||
'c-f' => "\x06",
|
||||
'c-g' => "\x07",
|
||||
'c-h' => "\x08",
|
||||
'c-i' => "\x09",
|
||||
'c-j' => "\x0a",
|
||||
'c-k' => "\x0b",
|
||||
'c-l' => "\x0c",
|
||||
'c-m' => "\x0d",
|
||||
'c-n' => "\x0e",
|
||||
'c-o' => "\x0f",
|
||||
'c-p' => "\x10",
|
||||
'c-q' => "\x11",
|
||||
'c-r' => "\x12",
|
||||
'c-s' => "\x13",
|
||||
'c-t' => "\x14",
|
||||
'c-u' => "\x15",
|
||||
'c-v' => "\x16",
|
||||
'c-w' => "\x17",
|
||||
'c-x' => "\x18",
|
||||
'c-y' => "\x19",
|
||||
'c-z' => "\x1a",
|
||||
'a-1' => "\e1",
|
||||
'a-2' => "\e2",
|
||||
'a-3' => "\e3",
|
||||
'a-4' => "\e4",
|
||||
'a-5' => "\e5",
|
||||
'a-6' => "\e6",
|
||||
'a-7' => "\e7",
|
||||
'a-8' => "\e8",
|
||||
'a-9' => "\e9",
|
||||
'a-0' => "\e0",
|
||||
);
|
||||
|
||||
sub YESNO { +{ 'y' => 1, 'n' => 1 } }
|
||||
|
||||
sub NUMFT {
|
||||
my $from = shift;
|
||||
my $to = shift;
|
||||
|
||||
die unless (defined $from && defined $to);
|
||||
my $href = {};
|
||||
|
||||
foreach ($from..$to) {
|
||||
$href->{$_} = 1;
|
||||
}
|
||||
|
||||
return $href;
|
||||
}
|
||||
|
||||
sub bind {
|
||||
my $key = shift;
|
||||
my $cmd = shift;
|
||||
|
||||
$key2name{$name2key{$key}} = $cmd;
|
||||
#print "$key, $cmd, " . unpack("H*", $name2key{$key}) . "\r\n";
|
||||
}
|
||||
|
||||
$name2key{'pos1'} = $name2key{'home'};
|
||||
$name2key{'alt-left'} = $name2key{'a-left'};
|
||||
$name2key{'alt-right'} = $name2key{'a-right'};
|
||||
|
||||
my %action = (
|
||||
'exit' => sub { print "\r\n"; exit; }
|
||||
);
|
||||
|
||||
sub del_line { "\r".$term->Tputs('dl', 1) }
|
||||
|
||||
sub init {
|
||||
select(STDIN); $| = 1;
|
||||
select(STDOUT); $| = 1;
|
||||
system "stty raw -echo";
|
||||
$term = Tgetent Term::Cap { TERM => undef, OSPEED => 9600 };
|
||||
*Prompt::del_line = \&del_line;
|
||||
if ($opts{'w'} && int($opts{'w'}) == $opts{'w'}) {
|
||||
print "true!\r\n";
|
||||
$prompt = new Prompt({ 'width' => $opts{'w'} });
|
||||
} else {
|
||||
$prompt = new Prompt;
|
||||
}
|
||||
$Term::ANSIColor::AUTORESET = 1;
|
||||
|
||||
main::bind('left', 'backward-char');
|
||||
main::bind('right', 'forward-char');
|
||||
main::bind('c-c', 'exit');
|
||||
main::bind('bs', 'backward-delete-char');
|
||||
main::bind('home', 'beginning-of-line');
|
||||
main::bind('c-a', 'beginning-of-line');
|
||||
main::bind('end', 'end-of-line');
|
||||
main::bind('c-e', 'end-of-line');
|
||||
main::bind('c-u', 'kill-whole-line');
|
||||
main::bind('c-k', 'kill-line');
|
||||
}
|
||||
|
||||
sub type {
|
||||
my $stdin = shift;
|
||||
my $raw;
|
||||
|
||||
sysread(*$stdin, $raw, 5);
|
||||
|
||||
if ($raw =~ /^[\r\n]$/) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (exists $key2name{$raw}) {
|
||||
if (exists($action{$key2name{$raw}})) {
|
||||
return $action{$key2name{$raw}}->();
|
||||
}
|
||||
|
||||
print $prompt->type($key2name{$raw}, $raw);
|
||||
return;
|
||||
}
|
||||
$prompt->put($raw);
|
||||
|
||||
print del_line() . $prompt->prompt();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
sub get {
|
||||
my $p = shift;
|
||||
my $default = shift;
|
||||
my $enforce = shift;
|
||||
|
||||
do {
|
||||
$prompt->Ret();
|
||||
$prompt->setPrompt($p);
|
||||
$prompt->data($default) if $default;
|
||||
|
||||
$prompt->type('end-of-line');
|
||||
|
||||
print del_line() . $prompt->prompt();
|
||||
while (!type(\*STDIN)) { }
|
||||
|
||||
print "\r\n";
|
||||
} while ($enforce && (!$prompt->data()
|
||||
|| ref $enforce
|
||||
&& !$enforce->{$prompt->data()})
|
||||
&& print "Invalid input. Try again!\r\n");
|
||||
|
||||
|
||||
return $prompt->data();
|
||||
}
|
||||
|
||||
sub find_driver {
|
||||
opendir(DIR, ".");
|
||||
my @driver = grep { /^(psyclpc|ldmud)-.+\.tar\.(gz|bz2)$/ } readdir(DIR);
|
||||
closedir(DIR);
|
||||
|
||||
if (scalar(@driver) != 1) {
|
||||
return \@driver;
|
||||
}
|
||||
|
||||
return $driver[0];
|
||||
}
|
||||
|
||||
sub investigate_protocol {
|
||||
my $setting = shift || die;
|
||||
my $what = shift || die;
|
||||
my $duse = shift || die;
|
||||
my $dport = shift || die;
|
||||
my $prange = shift;
|
||||
my $psome = shift;
|
||||
my $pport = shift;
|
||||
|
||||
$v{'use_' . $setting} = get('Enable ' . $what . ': ', $v{'use_' . $setting} || $duse, YESNO);
|
||||
if ($v{'use_' . $setting} eq 'y') {
|
||||
my $trange;
|
||||
my $enf;
|
||||
|
||||
if ($prange) {
|
||||
$trange = " between $prange->[0] and $prange->[1]";
|
||||
$enf = NUMFT(@$prange);
|
||||
} elsif ($psome) {
|
||||
$trange = " (";
|
||||
$enf = {};
|
||||
|
||||
for (my $i = 0; $i < scalar(@$psome); $i++) {
|
||||
$trange .= ' or ' if $i;
|
||||
$trange .= $psome->[$i];
|
||||
$enf->{$psome->[$i]} = 1;
|
||||
}
|
||||
|
||||
$trange .= ')';
|
||||
} else {
|
||||
$enf = 1;
|
||||
}
|
||||
|
||||
$v{'port_' . $setting} = get('Port number' . $trange . ': ',
|
||||
$dport, $enf);
|
||||
if ($pport) {
|
||||
print '[official port for ' . uc($setting) . " is $pport]\r\n\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
init();
|
||||
|
||||
#print Dumper(\%key2name);
|
||||
|
||||
print BOLD "psyced.ini configuration generator wizard\r\n\n";
|
||||
|
||||
## let's leave ldmud installation in install.sh for those who still want or
|
||||
## need to do it manually. the majority should use distribution packages!
|
||||
##
|
||||
#unless (!ref($t = find_driver())) {
|
||||
# print BOLD "ATTENTION: ";
|
||||
# print "You have ";
|
||||
#
|
||||
# if (scalar(@$t) == 0) {
|
||||
# print "no psyclpc-*.tar.gz in this directory\r\n";
|
||||
# print "Please obtain one from http://lpc.psyc.eu\r\n";
|
||||
# } else {
|
||||
# print "several driver tars in this directory\r\n";
|
||||
# print "Please delete some of them until you have only one left.\r\n";
|
||||
# print "If you continue now, this script won't compile a driver for you. \r\n\n";
|
||||
# }
|
||||
#
|
||||
# unless (get("Continue? ", "n", YESNO) eq 'y') { exit; }
|
||||
# print "\r\n";
|
||||
#} else {
|
||||
# print "I can see you have a driver tar here. That's good.\r\n\n";
|
||||
#}
|
||||
|
||||
print BOLD "INSTALLATION SPECIFIC QUESTIONS\r\n\n";
|
||||
|
||||
if ($>) {
|
||||
print "Since you started this installation not as root, you will see non-root defaults.\r\n\n";
|
||||
}
|
||||
|
||||
$v{'prefix'} = get("Install psyced to: ", $v{'prefix'} || $ENV{'HOME'} .
|
||||
"/psyced", 1);
|
||||
|
||||
$v{'prefix_sbin'} = get("Install binaries to: ", $v{'prefix_sbin'} || $v{'prefix'}.'/sbin');
|
||||
|
||||
$v{'hostname'} = get("Server host name: ", $v{'hostname'} || $ENV{'HOSTNAME'});
|
||||
|
||||
print "\r\n";
|
||||
print BOLD "HINT:";
|
||||
print " Your domain name. If your server is funny.bunny.com, that'll be bunny.com\r\n";
|
||||
$v{'domainname'} = get("Domain name: ", $v{'domainname'});
|
||||
|
||||
print "\r\nIf you have a static IP, please tell me. Otherwise leave this field blank.\r\n";
|
||||
$v{'ip'} = get("Server IP address: ", $v{'ip'});
|
||||
|
||||
print "\r\n";
|
||||
|
||||
unless ($>) {
|
||||
$v{'user'} = get("Install and run psyced as user: ", $v{'user'} || $ENV{'USER'});
|
||||
v{'group'} = get("Install and run psyced as group: ", $v{'group'} || $ENV{'GROUP'});
|
||||
|
||||
print "\r\n";
|
||||
}
|
||||
|
||||
print "Where do you want psyced runtime output? For manually started development\r\n";
|
||||
print "servers choose 'console', for background daemon service use 'files'.\r\n";
|
||||
|
||||
$v{'log'} = get("Send server runtime output to: ", $v{'log'} || 'console',
|
||||
{ 'files' => 1, 'console' => 1 });
|
||||
|
||||
$v{'debug'} = get("Debug level (0..4): ", '1',
|
||||
NUMFT(0, 4));
|
||||
|
||||
unless ($>) {
|
||||
$v{'init'} = get("Install a System V style init script? ", "n", YESNO);
|
||||
}
|
||||
|
||||
print BOLD "\r\nPSYC SPECIFIC OPTIONS\r\n\n";
|
||||
|
||||
print<<X;
|
||||
Set the PSYC identification for your server. e.g. funny.bunny.com.\r
|
||||
If you are using dial-up internet, you can try out a few things, but\r
|
||||
if you want this software to serve a serious purpose you need to have\r
|
||||
a dynamic DNS address for this machine installed and provide it here.\r
|
||||
\r
|
||||
X
|
||||
|
||||
$v{'psyc_hostname'} = get('PSYC hostname: ', $v{'psyc_hostname'} || $v{'hostname'} . ($v{'domainname'} ? '.' . $v{'domainname'} : ''), 1);
|
||||
|
||||
print<<X;
|
||||
\r
|
||||
Now comes the best part. You get to decide which of the many\r
|
||||
protocols and services that psyced provides you want to\r
|
||||
activate. Since psyclpc doesn't have the the ability to run safely\r
|
||||
as root all protocols use non-privilege port numbers.\r
|
||||
We also mention the official privileged port numbers in case\r
|
||||
you want to set up a firewall based port mapping.\r
|
||||
\r
|
||||
X
|
||||
|
||||
$v{'use_psyc'} = get('Enable PSYC (better say yes here)? ', $v{'yesno'} || 'y', YESNO);
|
||||
|
||||
$v{'port_psyc'} = get("Port number between 4400 and 4409: ", $v{'psyc_port'} || '4404', NUMFT(4400, 4409)) if $v{'use_psyc'} eq 'y';
|
||||
|
||||
print BOLD "\r\npsyced REGULAR PROTOCOL SERVICES\r\n\n";
|
||||
|
||||
my @prots = ( [ 'jabber_interserver',
|
||||
'XMPP communication with other JABBER servers',
|
||||
'y',
|
||||
'5269'
|
||||
],
|
||||
[ 'irc',
|
||||
'access for IRC clients',
|
||||
'y',
|
||||
'6667',
|
||||
[ 6600, 6699 ]
|
||||
],
|
||||
[ 'jabber_clients',
|
||||
'access for JABBER clients (experimental)',
|
||||
'n',
|
||||
'5222',
|
||||
undef,
|
||||
[ 5222, 55222 ]
|
||||
],
|
||||
[ 'smtp',
|
||||
'SMTP reception server (experimental)',
|
||||
'n',
|
||||
'2525',
|
||||
[ 2500, 2599 ],
|
||||
undef,
|
||||
25
|
||||
],
|
||||
[ 'pop3',
|
||||
'POP3 server (experimental)',
|
||||
'n',
|
||||
'1100'
|
||||
],
|
||||
[ 'nntp',
|
||||
'access for NNTP readers (experimental)',
|
||||
'n',
|
||||
'1199',
|
||||
[ 1190, 1199 ],
|
||||
undef,
|
||||
'119'
|
||||
],
|
||||
[ 'telnet',
|
||||
'telnet access',
|
||||
'y',
|
||||
'2323',
|
||||
[ 2300, 2399 ],
|
||||
undef,
|
||||
23
|
||||
],
|
||||
[ 'http',
|
||||
'builtin HTTP daemon',
|
||||
'y',
|
||||
'44444',
|
||||
undef,
|
||||
undef,
|
||||
80
|
||||
],
|
||||
[ 'applet',
|
||||
'applet access',
|
||||
'y',
|
||||
'2008',
|
||||
[ 2006, 2009 ]
|
||||
]
|
||||
);
|
||||
|
||||
foreach (@prots) {
|
||||
investigate_protocol(@$_);
|
||||
}
|
||||
|
||||
store \%v, '.ser.data';
|
||||
|
||||
# now generate the psyced.ini ... TODO
|
||||
|
||||
1;
|
||||
27
utility/Makefile
Normal file
27
utility/Makefile
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
TARGET=ergebnis
|
||||
LDFLAGS=-s
|
||||
|
||||
start:
|
||||
-@rm $(TARGET) >&/dev/null
|
||||
ifndef ZAHL
|
||||
@echo USAGE:
|
||||
@echo 'make ZAHL=<toCalc>'
|
||||
@false
|
||||
endif
|
||||
- make ZAHL=$(ZAHL) recurseBin
|
||||
@echo
|
||||
cat $(TARGET)
|
||||
@echo
|
||||
-@rm $(TARGET) >&/dev/null
|
||||
|
||||
recurseBin:
|
||||
- perl -e 'if ($(ZAHL) < 2) { exit 1; }' && make ZAHL=`perl -e 'if ($(ZAHL) >= 1) { print $(ZAHL) / 2} else { exit 1; }'` recurseBin
|
||||
perl -e 'print $(ZAHL) % 2' >> $(TARGET)
|
||||
perl -e 'if ($(ZAHL) < 2) { exit 1; }'
|
||||
|
||||
mailtest:
|
||||
make psycmail
|
||||
cp psycmail /usr/depot/mbin/psycmail
|
||||
rm psycmail
|
||||
echo "$@"|elm lynx -s "$@"
|
||||
|
||||
114
utility/cvsdont.pike
Normal file
114
utility/cvsdont.pike
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
#!/bin/env pike
|
||||
|
||||
// well, i'm using it. makes cdifs a lot nicer.
|
||||
// saga.
|
||||
//
|
||||
// oh interesting. how does it work? does it have
|
||||
// a usage: message? -lynX
|
||||
|
||||
#define unless(x) if(!(x))
|
||||
|
||||
int main() {
|
||||
int flag, i = -1, j, haveCuts;
|
||||
Stdio.File conf = Stdio.File();
|
||||
array(string) data;
|
||||
array(int) cuts = ({});
|
||||
mapping donts = ([]);
|
||||
|
||||
unless (getenv("HOME")) {
|
||||
werror("well, set $HOME, svp.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
unless (conf->open(getenv("HOME") + "/.cvsdont", "r")) {
|
||||
werror("well, could not open " + getenv("HOME") + "/.cvsdont\n");
|
||||
return 2;
|
||||
}
|
||||
|
||||
foreach (conf->read() / "\n", string line) {
|
||||
donts[line] = 1;
|
||||
}
|
||||
|
||||
data = Stdio.stdin->read() / "\n";
|
||||
|
||||
if (data[-1] == "") {
|
||||
data = data[0..sizeof(data) - 2];
|
||||
}
|
||||
|
||||
foreach (data, string line) {
|
||||
i++;
|
||||
unless (flag) {
|
||||
if (sizeof(line) > 10 && line[0..9] == "RCS file: " && donts[line[10..sizeof(line) - 1]]) {
|
||||
flag = !flag;
|
||||
cuts += ({ i - 2 });
|
||||
}
|
||||
} else {
|
||||
if (line[0] == '=') {
|
||||
flag = !flag;
|
||||
cuts += ({ i - 1 });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
i = -1;
|
||||
flag = 0;
|
||||
|
||||
haveCuts = sizeof(cuts);
|
||||
|
||||
#ifdef DEBUG
|
||||
werror("%O\n", cuts);
|
||||
#endif
|
||||
|
||||
if (haveCuts & 1) {
|
||||
cuts += ({ sizeof(data) });
|
||||
haveCuts++;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
werror("%O\n", cuts);
|
||||
#endif
|
||||
|
||||
foreach (data, string line) {
|
||||
i++;
|
||||
|
||||
#ifdef DEBUG
|
||||
if (haveCuts > j) {
|
||||
werror("} %d %d (%d)\n", i, cuts[j], (haveCuts - 1) > j);
|
||||
} else {
|
||||
werror("}} %d %d\n", i, j);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (haveCuts > j && cuts[j] == i) {
|
||||
#ifdef DEBUG
|
||||
if ((haveCuts - 1) > j) {
|
||||
werror("1] %d %d\n", j, cuts[j]);
|
||||
werror("2] %d\n", cuts[j+1]);
|
||||
} else {
|
||||
werror("] %d %d(%d)\n", j, haveCuts, sizeof(cuts));
|
||||
}
|
||||
#endif
|
||||
|
||||
unless ((haveCuts - 1) > j && i == cuts[j + 1]) {
|
||||
#ifdef DEBUG
|
||||
werror(">> %d\n", i);
|
||||
werror(") %d %d %d %d\n", i, j, cuts[j], flag);
|
||||
#endif
|
||||
flag = !flag;
|
||||
} else {
|
||||
#ifdef DEBUG
|
||||
werror("> %d %d\n", i, ((haveCuts - 1) > j) ? cuts[j+1] : 0);
|
||||
#endif
|
||||
j++;
|
||||
}
|
||||
j++;
|
||||
}
|
||||
|
||||
unless (flag || line[0] == '?') {
|
||||
write("%s\n", line);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
68
utility/erq/Makefile.in
Normal file
68
utility/erq/Makefile.in
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
|
||||
# These lines are needed on some machines.
|
||||
MAKE=make
|
||||
SHELL=@CONFIG_SHELL@
|
||||
INSTALL=@INSTALL@
|
||||
mkinstalldirs=$(SHELL) @top_srcdir@/mkinstalldirs
|
||||
#
|
||||
CC=@CC@
|
||||
|
||||
prefix=@prefix@
|
||||
exec_prefix=@exec_prefix@
|
||||
|
||||
SUBDIRS = indent make_docs xerq
|
||||
SED = sed
|
||||
|
||||
BINDIR=@bindir@
|
||||
MUD_LIB=@libdir@
|
||||
ERQ_DIR=@libexecdir@
|
||||
|
||||
#PROFIL= -DOPCPROF -DVERBOSE_OPCPROF
|
||||
#PROFIL=-p -DMARK
|
||||
#PROFIL=-pg
|
||||
PROFIL=
|
||||
#Enable warnings from the compiler, if wanted.
|
||||
WARN= # no warning options - will work with all compilers :-)
|
||||
#WARN= -Wall -Wshadow -Dlint
|
||||
#WARN= -Wall -Wshadow -Wno-parentheses # gcc settings
|
||||
#
|
||||
# Optimization and source level debugging options.
|
||||
# adding a -fomit-frame-pointer on the NeXT (gcc version 1.93 (68k, MIT syntax))
|
||||
# will corrupt the driver.
|
||||
HIGH_OPTIMIZE = @OCFLAGS@ # high optimization
|
||||
MED_OPTIMIZE= @MCFLAGS@ # medium optimization
|
||||
LOW_OPTIMIZE = @LCFLAGS@ # minimal optimization
|
||||
NO_OPTIMIZE= @DCFLAGS@ # no optimization; for frequent recompilations.
|
||||
|
||||
OPTIMIZE= $(@val_optimize@_OPTIMIZE)
|
||||
|
||||
# The main debugging level is define in config.h
|
||||
# Add additional options here.
|
||||
DEBUG=
|
||||
#
|
||||
MPATH=-DMUD_LIB='"$(MUD_LIB)"' -DBINDIR='"$(BINDIR)"' -DERQ_DIR='"$(ERQ_DIR)"'
|
||||
#
|
||||
TOPINC=-I@top_srcdir@
|
||||
#
|
||||
CFLAGS= @EXTRA_CFLAGS@ $(OPTIMIZE) $(DEBUG) $(WARN) $(MPATH) $(PROFIL) $(TOPINC)
|
||||
#
|
||||
LIBS=@ERQ_LIBS@ -lresolv
|
||||
#
|
||||
LDFLAGS=@LDFLAGS@
|
||||
|
||||
|
||||
|
||||
all: erq@EXEEXT@
|
||||
|
||||
FORCE: install
|
||||
|
||||
erq@EXEEXT@: erq.c
|
||||
# $(CC) erq.c -lresolv -o erq@EXEEXT@
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) erq.c -o erq@EXEEXT@ $(LIBS)
|
||||
|
||||
install: erq@EXEEXT@
|
||||
$(mkinstalldirs) $(BINDIR)
|
||||
$(INSTALL) erq@EXEEXT@ $(BINDIR)/erq@EXEEXT@
|
||||
|
||||
clean:
|
||||
-rm -f *.o erq@EXEEXT@ *~
|
||||
100
utility/erq/erq-srv.patch
Normal file
100
utility/erq/erq-srv.patch
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
Index: erq.c
|
||||
===================================================================
|
||||
--- erq.c (revision 2308)
|
||||
+++ erq.c (working copy)
|
||||
@@ -108,6 +108,7 @@
|
||||
#endif
|
||||
|
||||
#include "erq.h"
|
||||
+#include "srv.c"
|
||||
|
||||
#define randomize_tickets(n) srandom(n)
|
||||
#define get_ticket() random()
|
||||
@@ -1172,7 +1173,75 @@
|
||||
break;
|
||||
}
|
||||
#endif /* ERQ_RLOOKUPV6 */
|
||||
+#ifdef ERQ_LOOKUP_SRV
|
||||
+ case ERQ_LOOKUP_SRV:
|
||||
+ {
|
||||
+ /* lookup list of srv records */
|
||||
+ struct srvhost * r;
|
||||
+ struct srvhost * s;
|
||||
+ char service[50], proto[20], hostname[200];
|
||||
+ int counter;
|
||||
+ char srvbuf[MAX_REPLY];
|
||||
+
|
||||
+ header[8] = CHILD_FREE;
|
||||
+ counter = 0;
|
||||
+ srvbuf[0] = '\0';
|
||||
+ // TODO: sscanf this from req string
|
||||
+ // format: <service>.<proto>.<hostname>
|
||||
+ // example: _psyc._tcp.ve.symlynX.com
|
||||
+ // getsrv(hostname, service, proto)
|
||||
+ memcpy(header + 9, buf, msglen);
|
||||
+ buf[msglen] = '\0';
|
||||
+ sscanf(buf, "%49[^.].%19[^.].%199s", service, proto, hostname);
|
||||
+#if ERQ_DEBUG > 0
|
||||
+ fprintf(stderr, "%s: ERQ_LOOKUP_SRV '%s', %s,%s,%s\n", time_stamp(), buf, service, proto, hostname);
|
||||
+#endif
|
||||
+ r = getsrv(hostname, service, proto);
|
||||
+ if (!r) {
|
||||
+ /* lookup failed, send empty message*/
|
||||
+ write_32(header, 8);
|
||||
+ write1(header, 9);
|
||||
+#if ERQ_DEBUG > 0
|
||||
+ fprintf(stderr, "%s: ERQ_LOOKUP_SRV could not srv_resolve '%s'\n", time_stamp(), buf);
|
||||
+#endif
|
||||
+ break;
|
||||
+ } else {
|
||||
+ s = r;
|
||||
+ while (s) {
|
||||
+ /* walk list of structures */
|
||||
+ /* important members: name, port, pref, weight */
|
||||
+ if (strlen(srvbuf) < MAX_REPLY - 1) {
|
||||
+ strncat(srvbuf, s -> name, MAX_REPLY - strlen(srvbuf));
|
||||
+ strncat(srvbuf, "\n", MAX_REPLY - strlen(srvbuf));
|
||||
+
|
||||
+
|
||||
+ if (strlen(srvbuf) < MAX_REPLY - 1) {
|
||||
+ snprintf(hostname, MAX_REPLY - 1, "%d%c", s -> port, '\n');
|
||||
+ strncat(srvbuf, hostname, MAX_REPLY - strlen(srvbuf));
|
||||
+
|
||||
+ if (strlen(srvbuf) < MAX_REPLY - 1) {
|
||||
+ snprintf(hostname, MAX_REPLY - 1, "%d%c", s -> pref, '\n');
|
||||
+ strncat(srvbuf, hostname, MAX_REPLY - strlen(srvbuf));
|
||||
+ if (strlen(srvbuf) < MAX_REPLY - 1) {
|
||||
+ snprintf(hostname, MAX_REPLY - 1, "%d%c", s -> weight, '\n');
|
||||
+ strncat(srvbuf, hostname, MAX_REPLY - strlen(srvbuf));
|
||||
+ } else s = NULL;
|
||||
+ } else s = NULL;
|
||||
+ } else s = NULL;
|
||||
+ } else s = NULL;
|
||||
+
|
||||
+ s = s -> next;
|
||||
+ counter++;
|
||||
+ }
|
||||
+ freesrvhost(r);
|
||||
+ }
|
||||
+ write_32(header, strlen(srvbuf) + 9);
|
||||
+ write1(header, 9);
|
||||
+ write1(srvbuf, strlen(srvbuf) + 1);
|
||||
|
||||
+ break;
|
||||
+ }
|
||||
+#endif /* ERQ_LOOKUP_SRV */
|
||||
case ERQ_EXECUTE:
|
||||
{
|
||||
/* Execute a program, wait for its termination and
|
||||
Index: erq.h
|
||||
===================================================================
|
||||
--- erq.h (revision 2308)
|
||||
+++ erq.h (working copy)
|
||||
@@ -21,6 +21,7 @@
|
||||
#ifdef __IPV6__
|
||||
#define ERQ_RLOOKUPV6 12 /* Lookup name/ip6 */
|
||||
#endif
|
||||
+#define ERQ_LOOKUP_SRV 13
|
||||
|
||||
/* Additional service request type flags evaluated by efun send_erq().
|
||||
* The ERQ itself won't get to see it.
|
||||
2616
utility/erq/erq.c
Normal file
2616
utility/erq/erq.c
Normal file
File diff suppressed because it is too large
Load diff
60
utility/erq/erq.h
Normal file
60
utility/erq/erq.h
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
/* external request demon interface definitions */
|
||||
|
||||
#ifndef ERQ_H__
|
||||
#define ERQ_H__ 1
|
||||
|
||||
/* servive request types */
|
||||
|
||||
#define ERQ_RLOOKUP 0 /* Lookup ip -> name */
|
||||
#define ERQ_EXECUTE 1 /* Execute a program */
|
||||
#define ERQ_FORK 2 /* Fork a program */
|
||||
#define ERQ_AUTH 3 /* Connect to a remote authd */
|
||||
#define ERQ_SPAWN 4 /* Spawn a program */
|
||||
#define ERQ_SEND 5 /* Send data to a program or connection */
|
||||
#define ERQ_KILL 6 /* Kill a program or connection */
|
||||
#define ERQ_OPEN_UDP 7 /* Open a UDP socket */
|
||||
#define ERQ_OPEN_TCP 8 /* Open a TCP connection */
|
||||
#define ERQ_LISTEN 9 /* Open a TCP accept-socket */
|
||||
#define ERQ_ACCEPT 10 /* Accept a connection from a accept-socket */
|
||||
#define ERQ_LOOKUP 11 /* Lookup name -> ip */
|
||||
|
||||
#ifdef __IPV6__
|
||||
#define ERQ_RLOOKUPV6 12 /* Lookup name/ip6 */
|
||||
#endif
|
||||
#define ERQ_LOOKUP_SRV 13
|
||||
|
||||
/* Additional service request type flags evaluated by efun send_erq().
|
||||
* The ERQ itself won't get to see it.
|
||||
*/
|
||||
|
||||
#define ERQ_CB_STRING (1 << 31) /* Callback closure takes a string arg */
|
||||
|
||||
|
||||
/* answers from ERQ_EXECUTE / ERQ_FORK */
|
||||
|
||||
#define ERQ_OK 0
|
||||
#define ERQ_SIGNALED 1
|
||||
#define ERQ_E_NOTFOUND 2 /* process not found by wait */
|
||||
#define ERQ_E_UNKNOWN 3 /* unknown exit condition from wait() */
|
||||
#define ERQ_E_ARGLENGTH 4
|
||||
#define ERQ_E_ARGFORMAT 5
|
||||
#define ERQ_E_ARGNUMBER 6
|
||||
#define ERQ_E_ILLEGAL 7
|
||||
#define ERQ_E_PATHLEN 8
|
||||
#define ERQ_E_FORKFAIL 9
|
||||
#define ERQ_E_TICKET 11
|
||||
#define ERQ_E_INCOMPLETE 12
|
||||
#define ERQ_E_WOULDBLOCK 13
|
||||
#define ERQ_E_PIPE 14
|
||||
#define ERQ_STDOUT 15 /* Normal data received */
|
||||
#define ERQ_STDERR 16
|
||||
#define ERQ_EXITED 17 /* Connection closed on EOF */
|
||||
#define ERQ_E_NSLOTS 18
|
||||
|
||||
/* reserved handles */
|
||||
|
||||
#define ERQ_HANDLE_RLOOKUP (-1)
|
||||
#define ERQ_HANDLE_KEEP_HANDLE (-2)
|
||||
#define ERQ_HANDLE_RLOOKUPV6 (-3)
|
||||
|
||||
#endif /* ERQ_H__ */
|
||||
226
utility/erq/srv.c
Normal file
226
utility/erq/srv.c
Normal file
|
|
@ -0,0 +1,226 @@
|
|||
/* SRV implementation by the PSYC developers at psyced.org
|
||||
*
|
||||
* REMINDER: when modifying anything about these files, remember
|
||||
* that not only the psyced installer needs to be updated, you
|
||||
* also have to manually update the gentoo tar.
|
||||
*/
|
||||
|
||||
#include "srv.h"
|
||||
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <strings.h>
|
||||
#include <arpa/inet.h> // For solaris
|
||||
#include <arpa/nameser.h>
|
||||
#include <resolv.h>
|
||||
|
||||
#if !defined(__FreeBSD__) && !defined(__NetBSD__) && !defined(__OpenBSD__)
|
||||
# include <malloc.h>
|
||||
#else
|
||||
# include <stdlib.h>
|
||||
#endif
|
||||
|
||||
/* the biggest packet we'll send and receive */
|
||||
#if PACKETSZ > 1024
|
||||
#define MAXPACKET PACKETSZ
|
||||
#else
|
||||
#define MAXPACKET 1024
|
||||
#endif
|
||||
|
||||
/* and what we send and receive */
|
||||
typedef union {
|
||||
HEADER hdr;
|
||||
u_char buf[MAXPACKET];
|
||||
} querybuf;
|
||||
|
||||
#ifndef T_SRV
|
||||
#define T_SRV 33
|
||||
#endif
|
||||
|
||||
|
||||
void freesrvhost ( struct srvhost * s )
|
||||
{
|
||||
struct srvhost * n;
|
||||
while( s ) {
|
||||
n = s->next;
|
||||
/* hack to make double-free visible by causing null dereference */
|
||||
s->next = NULL;
|
||||
free( (void *)s );
|
||||
s = n;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int compare( const void * a, const void * b )
|
||||
{
|
||||
struct srvhost * aa, * bb;
|
||||
|
||||
if ( !a )
|
||||
return 1;
|
||||
if ( !b )
|
||||
return -1;
|
||||
|
||||
aa = (struct srvhost *) *(int*)a;
|
||||
bb = (struct srvhost *) *(int*)b;
|
||||
|
||||
if ( aa->pref > bb->pref )
|
||||
return 1;
|
||||
if ( aa->pref < bb->pref )
|
||||
return -1;
|
||||
|
||||
if ( aa->rweight > bb->rweight )
|
||||
return -1;
|
||||
if ( aa->rweight < bb->rweight )
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
struct srvhost * getsrv( const char * domain,
|
||||
const char * service, const char * protocol ) {
|
||||
querybuf answer; /* answer buffer from nameserver */
|
||||
int n;
|
||||
char * zone;
|
||||
int ancount, qdcount; /* answer count and query count */
|
||||
HEADER *hp; /* answer buffer header */
|
||||
struct srvhost **replyarray;
|
||||
struct srvhost * firsthost;
|
||||
int answerno;
|
||||
u_char hostbuf[256];
|
||||
u_char *msg, *eom, *cp; /* answer buffer positions */
|
||||
int dlen, type, pref, weight, port;
|
||||
|
||||
if ( !domain || !*domain ||
|
||||
!service || !*service ||
|
||||
!protocol || !*protocol )
|
||||
return NULL;
|
||||
|
||||
zone = (char *)malloc( strlen( domain ) +
|
||||
strlen( service ) +
|
||||
strlen( protocol ) + 20 );
|
||||
if (zone == NULL)
|
||||
return NULL;
|
||||
|
||||
*zone = '\0';
|
||||
|
||||
if (*service != '_') // If service and protocol do not start with a
|
||||
strcat(zone, "_"); // _, prepend the _ to them...
|
||||
|
||||
strcat(zone, service);
|
||||
strcat(zone, ".");
|
||||
|
||||
if (*protocol != '_')
|
||||
strcat(zone, "_");
|
||||
|
||||
strcat(zone, protocol);
|
||||
strcat(zone, ".");
|
||||
|
||||
strcat(zone, domain);
|
||||
|
||||
n = res_query( zone, C_IN, T_SRV, (u_char *)&answer, sizeof( answer ) );
|
||||
|
||||
(void) free( zone );
|
||||
zone = NULL;
|
||||
|
||||
if ( n < (int)sizeof(HEADER) )
|
||||
return NULL;
|
||||
|
||||
/* valid answer received. skip the query record. */
|
||||
|
||||
hp = (HEADER *)&answer;
|
||||
qdcount = ntohs(hp->qdcount);
|
||||
ancount = ntohs(hp->ancount);
|
||||
|
||||
msg = (u_char *)&answer;
|
||||
eom = (u_char *)&answer + n;
|
||||
cp = (u_char *)&answer + sizeof(HEADER);
|
||||
|
||||
while ( qdcount-- > 0 && cp < eom ) {
|
||||
n = dn_expand( msg, eom, cp, (char *)hostbuf, 256 );
|
||||
if (n < 0)
|
||||
return NULL;
|
||||
cp += n + QFIXEDSZ;
|
||||
}
|
||||
|
||||
/* make a big-enough (probably too big) reply array */
|
||||
|
||||
replyarray
|
||||
= (struct srvhost **) malloc( ancount * sizeof(struct srvhost *) );
|
||||
for( n = 0; n < ancount; n++ )
|
||||
replyarray[n] = NULL;
|
||||
answerno = 0;
|
||||
|
||||
/* loop through the answer buffer and extract SRV records */
|
||||
while ( ancount-- > 0 && cp < eom ) {
|
||||
n = dn_expand( msg, eom, cp, (char *)hostbuf, 256 );
|
||||
if ( n < 0 ) {
|
||||
for( n = 0; n < answerno; n++ )
|
||||
(void) free( replyarray[n] );
|
||||
(void)free( replyarray );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cp += n;
|
||||
|
||||
type = _getshort(cp);
|
||||
cp += sizeof(u_short);
|
||||
|
||||
/* class = _getshort(cp); */
|
||||
cp += sizeof(u_short);
|
||||
|
||||
/* ttl = _getlong(cp); */
|
||||
cp += sizeof(u_long);
|
||||
|
||||
dlen = _getshort(cp);
|
||||
cp += sizeof(u_short);
|
||||
|
||||
if ( type != T_SRV ) {
|
||||
cp += dlen;
|
||||
continue;
|
||||
}
|
||||
|
||||
pref = _getshort(cp);
|
||||
cp += sizeof(u_short);
|
||||
|
||||
weight = _getshort(cp);
|
||||
cp += sizeof(u_short);
|
||||
|
||||
port = _getshort(cp);
|
||||
cp += sizeof(u_short);
|
||||
|
||||
n = dn_expand( msg, eom, cp, (char *)hostbuf, 256 );
|
||||
if (n < 0)
|
||||
break;
|
||||
cp += n;
|
||||
|
||||
replyarray[answerno]
|
||||
= (struct srvhost *)malloc( sizeof( struct srvhost ) +
|
||||
strlen( (char *)hostbuf ) );
|
||||
replyarray[answerno]->pref = pref;
|
||||
replyarray[answerno]->weight = weight;
|
||||
if ( weight )
|
||||
replyarray[answerno]->rweight = 1+random()%( 10000 * weight );
|
||||
else
|
||||
replyarray[answerno]->rweight = 0;
|
||||
replyarray[answerno]->port = port;
|
||||
replyarray[answerno]->next = NULL;
|
||||
strcpy( replyarray[answerno]->name, (char *)hostbuf );
|
||||
|
||||
answerno++;
|
||||
}
|
||||
if (answerno == 0) return NULL;
|
||||
qsort( replyarray, answerno, sizeof( struct srvhost * ),
|
||||
compare );
|
||||
|
||||
// Recreate a linked list from the sorted array...
|
||||
for( n = 0; n < answerno; n++ )
|
||||
replyarray[n]->next = replyarray[n+1];
|
||||
replyarray[answerno-1]->next = NULL;
|
||||
|
||||
firsthost = replyarray[0];
|
||||
(void) free( replyarray );
|
||||
return firsthost;
|
||||
}
|
||||
|
||||
32
utility/erq/srv.h
Normal file
32
utility/erq/srv.h
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
/****************************************************************************
|
||||
** $Id: srv.h,v 1.1 2006/05/22 11:18:10 lynx Exp $
|
||||
**
|
||||
** Definition of something or other
|
||||
**
|
||||
** Created : 979899
|
||||
**
|
||||
** Copyright (C) 1997 by Troll Tech AS. All rights reserved.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef SRV_H
|
||||
#define SRV_H
|
||||
|
||||
struct srvhost {
|
||||
unsigned int pref;
|
||||
struct srvhost * next;
|
||||
unsigned int port;
|
||||
unsigned int weight;
|
||||
unsigned int rweight;
|
||||
char name[1];
|
||||
};
|
||||
|
||||
|
||||
extern void freesrvhost ( struct srvhost * );
|
||||
|
||||
extern struct srvhost * getsrv( const char * domain,
|
||||
const char * service,
|
||||
const char * protocol );
|
||||
|
||||
#endif
|
||||
|
||||
61
utility/iso2utf8.pike
Normal file
61
utility/iso2utf8.pike
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
// converts files given as argument into utf8 if they contain
|
||||
// non iso-8859-15 characters. used to migrate '.o' files from
|
||||
// the old SYSTEM_CHARSET to the newer one.
|
||||
//
|
||||
// written by el, debugged and styled by lynX
|
||||
|
||||
int main(int argc, array(string) args) {
|
||||
int rc = 0;
|
||||
//write("args: %O\n", args);
|
||||
object decoder = Locale.Charset.decoder("iso-8859-15");
|
||||
|
||||
if (sizeof(args) > 1) foreach (args[1..];;string filename) {
|
||||
if (Stdio.is_file(filename)) {
|
||||
Stdio.File in;
|
||||
string ret;
|
||||
|
||||
if (mixed err = catch {
|
||||
in = Stdio.File(filename, "r");
|
||||
ret = in->read();
|
||||
in->close();
|
||||
}) {
|
||||
|
||||
write("failed reading %s: %O\n", filename, err);
|
||||
rc++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (mixed err = catch {
|
||||
ret = utf8_to_string(ret);
|
||||
}) {
|
||||
if (mixed err = catch {
|
||||
decoder->clear();
|
||||
decoder->feed(ret);
|
||||
ret = decoder->drain();
|
||||
}) {
|
||||
write("%s neither UTF-8 nor iso-8859-15!?\n", filename);
|
||||
} else {
|
||||
if (mixed err = catch {
|
||||
in = Stdio.File(filename, "w");
|
||||
in->write(string_to_utf8(ret));
|
||||
in->close();
|
||||
}) {
|
||||
write("writing to %O failed: %O\n", filename, err);
|
||||
rc++;
|
||||
} else {
|
||||
//write("wrote utf8 data to file.\n");
|
||||
write("%s\n", filename);
|
||||
}
|
||||
}
|
||||
} else { // is utf8 alread!!
|
||||
write(" ");
|
||||
}
|
||||
} else {
|
||||
//write("ignoring non-file: %O.\n", filename);
|
||||
}
|
||||
} else {
|
||||
write("no files. finishing.\n");
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
92
utility/multipatcher
Normal file
92
utility/multipatcher
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
#!/usr/bin/perl
|
||||
# recursive cvs root fixer. reusable for all sorts of patch operations. -lynX
|
||||
|
||||
require 'find.pl';
|
||||
$File::Find::dont_use_nlink = 'DONT!';
|
||||
|
||||
my $op = "s#^:pserver:anonymous\@cvs\.psyced\.org:/CVS/anonCVS#:pserver:$ENV{USER}\@cvs\.psyced\.org:/CVS/muveCVS#m";
|
||||
|
||||
$grep = shift or die <<X;
|
||||
|
||||
usage: $0 <filematch> [<operation> [<directories>]]
|
||||
|
||||
<filematch> would typically be "Root"
|
||||
|
||||
<operation> by default is to transform anonymous access to the psyced
|
||||
repository into your personal login access. in detail:
|
||||
|
||||
$op
|
||||
|
||||
without <directories> the directory tree starting from the current directory
|
||||
is recursively checked.
|
||||
|
||||
you can obviously use a completely different regular expression on completely
|
||||
different sets of files. for example here is a command that will remove the
|
||||
/lastlog store from all of psyced's .o save files it encounters.
|
||||
|
||||
multipatcher '.o' 's:^_log .*\\n\$::m'
|
||||
|
||||
you can even embed any of \$name, \$dir or \$base, like this:
|
||||
|
||||
multipatcher .o 's#softnews#id":"psyc://psyced.org/~$base","softnews#'
|
||||
|
||||
this one inserts an entry 'id' in front of an existing entry called 'softnews'
|
||||
X
|
||||
|
||||
$_ = shift;
|
||||
$op = $_ if $_;
|
||||
|
||||
$|=1;
|
||||
my @list;
|
||||
&find($#ARGV >= 0 ? @ARGV : '.');
|
||||
exit;
|
||||
|
||||
sub wanted {
|
||||
($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime)
|
||||
= lstat;
|
||||
return unless /$grep/o;
|
||||
|
||||
my $f = $_;
|
||||
if (open(I, $f)) {
|
||||
$_ = &slurp(I);
|
||||
close I;
|
||||
} else {
|
||||
print STDERR "cannot access $name\n";
|
||||
return;
|
||||
}
|
||||
my $base = $f =~ m!^(\w+)\b! ? $1 : $f;
|
||||
|
||||
my $was = $_;
|
||||
eval $op;
|
||||
# print "** $op ** in $_ **\n";
|
||||
|
||||
if ($was eq $_) {
|
||||
print "no:\t$name\n";
|
||||
return;
|
||||
}
|
||||
print "yes:\t$name\n";
|
||||
|
||||
if (open(O, ">Nu$f")) {
|
||||
print O $_;
|
||||
close O;
|
||||
} else {
|
||||
print STDERR "cannot create Nu$f in $dir\n";
|
||||
return;
|
||||
}
|
||||
unless (unlink $f) {
|
||||
print STDERR "cannot delete $f\n";
|
||||
return;
|
||||
}
|
||||
rename ("Nu$f", $f) or die "the world is not logical";
|
||||
}
|
||||
|
||||
# reads a file from a stream into a variable all at once
|
||||
#
|
||||
sub slurp {
|
||||
local(*IN) = @_;
|
||||
local($save) = $/;
|
||||
undef $/;
|
||||
local($data) = <IN>;
|
||||
$/ = $save;
|
||||
return $data;
|
||||
}
|
||||
131
utility/performance-test.c
Normal file
131
utility/performance-test.c
Normal file
|
|
@ -0,0 +1,131 @@
|
|||
// Usage in Pike: time pike -D_test_new_objects performance-test.c
|
||||
// Usage in LPC: cp performance-test.c ../world/test.c
|
||||
// time psyclpc -E 0 -f "test main" -D_test_new_objects
|
||||
//
|
||||
// Measurements aren't too accurate as they include compilation time.
|
||||
|
||||
/*
|
||||
* This file was written to find out which data container types perform
|
||||
* best: arrays, mappings or objects. Then I decided to also look at
|
||||
* pike's behaviour on this topic.
|
||||
*
|
||||
* Results:
|
||||
|
||||
LPC: even with psyclpc's new streamlined object code, using
|
||||
objects takes double as much computation time than using mappings
|
||||
or arrays. this presumes you will be using objects where each
|
||||
attribute has its own variable - but it is in fact more likely
|
||||
that you will be using mappings with an object class wrapper, so
|
||||
the factor rises to 3. doing traditional OO programming is a bit
|
||||
expensive in LPC, it seems. but probably it's not different in
|
||||
other languages, it's just a tradeoff which is generally accepted
|
||||
for the benefit of having OO with encapsulation and everything.
|
||||
|
||||
PIKE: as expected the optimizations generally make pike double
|
||||
as fast as LPC, however there is an interesting detail with
|
||||
arrays being 3 times as fast as objects. so even in pike it is
|
||||
recommendable to use OO only where it is really worth it. note
|
||||
also the result for _test_new_objects must be wrong, how can
|
||||
cloning 300000 MyTests come out cheaper than just using one (as
|
||||
shown in _test_using_objects?). I presume some compile-time
|
||||
optimization killed the intended purpose of the test, so we have
|
||||
no usable estimate on object cloning. :(
|
||||
|
||||
*
|
||||
* This is hybrid pike/LPC code:
|
||||
*/
|
||||
|
||||
int loops = 300000;
|
||||
|
||||
#ifdef LPC3
|
||||
# include <net.h>
|
||||
# include <sys/debug_message.h>
|
||||
#endif
|
||||
|
||||
#ifdef __PIKE__
|
||||
class MyTest {
|
||||
#endif
|
||||
// TEST OBJECT CODE START
|
||||
mixed p;
|
||||
|
||||
mixed attri(mixed put) {
|
||||
if (put) p = put;
|
||||
return p;
|
||||
}
|
||||
|
||||
int one() {
|
||||
return 1;
|
||||
}
|
||||
// TEST OBJECT CODE STOP
|
||||
#ifdef __PIKE__
|
||||
}
|
||||
// minor advantage for pike.. we are not cloning main()
|
||||
#endif
|
||||
|
||||
mixed main(mixed x, mixed y) {
|
||||
int i, sum = 0;
|
||||
mixed t;
|
||||
array(int) a = ({ 1, 2 });
|
||||
mapping m = ([ "one": 1, "two": 2 ]);
|
||||
object o;
|
||||
|
||||
//PP(("\nx=%O y=%O\n\n", x, y));
|
||||
//
|
||||
#ifdef LPC3
|
||||
// apparently stderr gets flushed anyway, so i can make nice
|
||||
// nice incremental outputs there.. ;)
|
||||
debug_message("Running tests ..", DMSG_STDERR);
|
||||
// printf("... %c ...", "ufo"[-1]); // LPC requires <1 here
|
||||
o = clone_object(ME);
|
||||
#else
|
||||
write("Running tests ..");
|
||||
o = MyTest();
|
||||
#endif
|
||||
// results using loops = 300000
|
||||
for (i=loops; i; i--) {
|
||||
#ifdef _test_new_objects // LPC: 1.900u 0.040s 0:01.94 100.0%
|
||||
# ifdef __PIKE__ //pike: 0.468u 0.004s 0:00.46 100.0%
|
||||
o = MyTest(); // pike result must be wrong :(
|
||||
# else
|
||||
/* also has significantly higher eval_cost */
|
||||
o = clone_object(ME);
|
||||
# endif
|
||||
sum += o->one();
|
||||
destruct(o);
|
||||
#endif
|
||||
#ifdef _test_new_mappings // LPC: 0.704u 0.016s 0:00.72 98.6%
|
||||
m = ([ ]); //pike: 0.336u 0.024s 0:00.35 100.0%
|
||||
m["one"] = 1;
|
||||
sum += m["one"];
|
||||
#endif
|
||||
#ifdef _test_new_arrays // LPC: 0.572u 0.012s 0:00.59 98.3%
|
||||
a = ({ }); //pike: 0.292u 0.000s 0:00.29 100.0%
|
||||
a += ({ 1 });
|
||||
sum += a[0];
|
||||
#endif
|
||||
#ifdef _test_using_objects // LPC: 1.164u 0.008s 0:01.17 99.1%
|
||||
o->attri(4404); //pike: 0.488u 0.004s 0:00.49 97.9%
|
||||
t = o->attri();
|
||||
sum += o->one();
|
||||
#endif
|
||||
#ifdef _test_using_mappings // LPC: 0.588u 0.032s 0:00.62 98.3%
|
||||
m["4404"] = 4404; //pike: 0.292u 0.004s 0:00.29 100.0%
|
||||
t = m["4404"];
|
||||
sum += m["one"];
|
||||
#endif
|
||||
#ifdef _test_using_arrays // LPC: 0.508u 0.012s 0:00.52 98.0%
|
||||
a[1] = 4404; //pike: 0.188u 0.004s 0:00.19 94.7%
|
||||
t = a[1];
|
||||
sum += a[0];
|
||||
#endif
|
||||
}
|
||||
t = "Result is "+ ( sum == loops? "correct": "wrong" ) +".\n";
|
||||
#ifdef LPC3
|
||||
debug_message(". done!\n"+ t, DMSG_STDERR);
|
||||
return "sum: "+ sum;
|
||||
#else
|
||||
write(". done!\n"+ t);
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
203
utility/pkggen.c
Normal file
203
utility/pkggen.c
Normal file
|
|
@ -0,0 +1,203 @@
|
|||
/* Why do we use C for shell scripts?
|
||||
* Well.. why not?
|
||||
* Because people like me need to add something and end up spending half
|
||||
* an hour for a 30 second change.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <time.h>
|
||||
|
||||
#define unless(x) if (!(x))
|
||||
|
||||
void cvscp(char *filename) {
|
||||
char cmdline[1000];
|
||||
printf(">>> %s\n", filename);
|
||||
|
||||
snprintf(cmdline, (sizeof cmdline) - 1, "cp %s ../skel", filename);
|
||||
|
||||
if (system(cmdline)) {
|
||||
printf(">> Could not update %s. Exiting.\n", filename);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void webcp(char *filename) {
|
||||
char cmdline[1000];
|
||||
printf(">>> %s\n", filename);
|
||||
|
||||
snprintf(cmdline, (sizeof cmdline) - 1, "lynx -dump http://www.psyced.org/%s.html > %s.txt", filename, filename);
|
||||
|
||||
if (system(cmdline)) {
|
||||
printf(">> Could not update %s. Exiting.\n", filename);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
time_t t;
|
||||
struct tm *lt;
|
||||
char ft[200], s[1000];
|
||||
int l, hadskel;
|
||||
|
||||
time(&t);
|
||||
lt = localtime(&t);
|
||||
/* new format without dashes to accomodate gentoo versioning style */
|
||||
strftime(ft, 199, "%Y%m%d", lt);
|
||||
/* strftime(ft, 199, "%F", lt); */
|
||||
|
||||
if (chdir("skel")) {
|
||||
hadskel = 0;
|
||||
|
||||
printf(">> Welcome. Today is %s. I will create a skel and data directory here.\n", ft);
|
||||
if (argc != 2) {
|
||||
printf(">> Usage: %s psyced-<date>.tar.bz2\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
l = strlen(argv[1]);
|
||||
if (l < 10 || l > 30) {
|
||||
puts(">> This doesn't look like a psyced-<date>.tar.bz2.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
puts(">> Let me unpack this.");
|
||||
|
||||
snprintf(s, (sizeof s) - 1, "tar xvfj %s", argv[1]);
|
||||
if (system(s)) {
|
||||
printf(">> Could not untar %s. Exiting.\n", argv[1]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
argv[1][l - sizeof("tar.bz2")] = 0;
|
||||
if (rename(argv[1], "skel")) {
|
||||
printf(">> Could not rename %s. Exiting.\n", argv[1]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (chdir("skel")) {
|
||||
puts(">> Could not enter skel/. Exiting.");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
hadskel = 1;
|
||||
puts(">> You already have a skel, good. Skipping unpack operation.");
|
||||
}
|
||||
|
||||
if (!unlink(".config")) {
|
||||
puts(">> Deleted a .config that someone left lying around.");
|
||||
}
|
||||
|
||||
if (mkdir("../data", S_IRWXU)) {
|
||||
puts(">> Could not create data/. Already there?");
|
||||
/* return 1; */
|
||||
} else {
|
||||
puts(">> Extracting data");
|
||||
|
||||
if (system("tar xf data.tar -C../data")) {
|
||||
puts(">> Error in extracting data.tar. Exiting.");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (chdir("../data")) {
|
||||
puts(">> Could not enter data/. Exiting.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* we don't want to update CHANGESTODO. we put a fake file
|
||||
there so it doesn't download the real thing, later we delete it
|
||||
system("cp BANNER CHANGESTODO");
|
||||
hmm, doesn't really work like that
|
||||
*/
|
||||
|
||||
puts(">> Now is your chance to inspect a cvs diff. Suspend now.");
|
||||
sleep(4);
|
||||
|
||||
puts(">> Doing a CVS update");
|
||||
if (system("cvs -q update -dP")) {
|
||||
puts(">> Error during CVS update. Exiting.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* because we want to keep it out of the snapshots anyway */
|
||||
unlink("CHANGESTODO");
|
||||
/* system("rm .#CHANGESTODO*") */
|
||||
|
||||
puts(">> Now is your chance to make manual changes. Suspend now.");
|
||||
sleep(4);
|
||||
|
||||
puts(">> Creating new data.tar");
|
||||
|
||||
if (system("tar cf ../skel/data.tar --owner=root --group=root .")) {
|
||||
puts(">> Error during archiving. Exiting.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
puts(">> Updating files from CVS");
|
||||
|
||||
cvscp("install.sh");
|
||||
|
||||
puts(">> Cleaning up data/");
|
||||
chdir("..");
|
||||
if (system("rm -rf data")) {
|
||||
puts(">> Could not remove data/. Exiting.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (chdir("skel")) {
|
||||
puts(">> Could not enter skel/. Exiting.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
puts(">> Updating files from Webserver");
|
||||
|
||||
webcp("README");
|
||||
webcp("INSTALL");
|
||||
webcp("FIRSTSTEPS");
|
||||
|
||||
puts(">> Creating archive");
|
||||
|
||||
snprintf(s, (sizeof s) - 1, "../psyced-%s", ft);
|
||||
if (mkdir(s, S_IRWXU)) {
|
||||
printf(">> Could not create %s/. Exiting.\n", s);
|
||||
return 1;
|
||||
}
|
||||
|
||||
snprintf(s, (sizeof s) - 1, "tar cf - . | tar xf - -C../psyced-%s", ft);
|
||||
if (system(s)) {
|
||||
puts(">> Could not copy data for tarring. Exiting.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
chdir("..");
|
||||
|
||||
snprintf(s, (sizeof s) - 1, "tar cfj psyced-%s.tar.bz2 --owner=root --group=root psyced-%s", ft, ft);
|
||||
|
||||
if (system(s)) {
|
||||
printf(">> Could not create psyced-%s.tar.bz2. Exiting.\n", ft);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf(">> psyced-%s.tar.bz2 has been created. Cleaning up.\n", ft);
|
||||
|
||||
snprintf(s, (sizeof s) - 1, "rm -rf psyced-%s", ft);
|
||||
if (system(s)) {
|
||||
printf(">> Could not remove psyced-%s. Exiting.\n", ft);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!hadskel) {
|
||||
if (system("rm -r skel")) {
|
||||
puts(">> I'm done, but I could not remove the skel directory.");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
puts(">> Done.");
|
||||
|
||||
return 0;
|
||||
}
|
||||
22
utility/powwow.patch
Normal file
22
utility/powwow.patch
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
there is a sample configuration for using powwow as a telnet-based
|
||||
client application for psyc in the config directory. unfortunately
|
||||
the default powwow configuration comes with a very stupid setting
|
||||
for command continuation, the ';' -- which makes it very hard to
|
||||
wink in a conversation, unless you #quote on which means all of
|
||||
your #alias'es will no longer work. the solution is to apply this
|
||||
little patch before you compile or emerge powwow. maybe one day
|
||||
someone will make it a setting, then this patch will become useless
|
||||
but in the year 2005 this is still not the case. -lynX
|
||||
|
||||
|
||||
--- defines.h~ 2005-08-14 19:34:58.000000000 +0200
|
||||
+++ defines.h 2005-08-14 19:35:02.000000000 +0200
|
||||
@@ -117,7 +117,7 @@
|
||||
#define STRESC "\\"
|
||||
#define ESC2 '`' /* other special escape char */
|
||||
#define STRESC2 "`"
|
||||
-#define CMDSEP ';' /* command separator character */
|
||||
+#define CMDSEP '§' /* command separator character */
|
||||
#define SPECIAL_CHARS "{}();\"=" /* specials chars needing escape */
|
||||
#define MPI "~$#E" /* MUME protocol introducer */
|
||||
#define MPILEN 4 /* strlen(MPI) */
|
||||
174
utility/procmail.patch
Normal file
174
utility/procmail.patch
Normal file
|
|
@ -0,0 +1,174 @@
|
|||
=== src/mailfold.h
|
||||
==================================================================
|
||||
--- src/mailfold.h (revision 1073)
|
||||
+++ src/mailfold.h (local)
|
||||
@@ -7,7 +7,7 @@
|
||||
const int ignwerr,const int dolock)),
|
||||
readmail P((int rhead,const long tobesent));
|
||||
void
|
||||
- logabstract P((const char*const lstfolder)),
|
||||
+ logabstract P((const char*const lstfolder,const char*psycnotify)),
|
||||
concon P((const int ch));
|
||||
|
||||
extern int logopened,rawnonl;
|
||||
=== src/procmail.c
|
||||
==================================================================
|
||||
--- src/procmail.c (revision 1073)
|
||||
+++ src/procmail.c (local)
|
||||
@@ -766,6 +766,10 @@
|
||||
}
|
||||
if(readparse(chp+1,getb,0,skiprc))
|
||||
goto fail;
|
||||
+ if (strchr(chp+1, ':') > 0) { /* notify a non-email scheme */
|
||||
+ logabstract(tgetenv(lastfolder), chp+1);
|
||||
+ goto setlsucc;
|
||||
+ }
|
||||
if(i)
|
||||
{ if(startchar==themail.p)
|
||||
{ startchar[filled]='\0'; /* just in case */
|
||||
@@ -953,7 +957,7 @@
|
||||
return rcs_DELIVERED;
|
||||
}
|
||||
logsetlsucc: if(succeed&&flags[CONTINUE]&&lgabstract==2)
|
||||
- logabstract(tgetenv(lastfolder));
|
||||
+ logabstract(tgetenv(lastfolder), 0);
|
||||
setlsucc: rawnonl=0;lastsucc=succeed;lasttell= -1; /* for comsat */
|
||||
resettmout(); /* clear any pending timer */
|
||||
}
|
||||
=== src/misc.c
|
||||
==================================================================
|
||||
--- src/misc.c (revision 1073)
|
||||
+++ src/misc.c (local)
|
||||
@@ -287,7 +287,7 @@
|
||||
{ lstfolder=tgetenv(lastfolder);
|
||||
sendcomsat(0);
|
||||
}
|
||||
- logabstract(lstfolder);
|
||||
+ logabstract(lstfolder, 0);
|
||||
if(!nextexit) /* these are unsafe from sighandlers */
|
||||
{ shutdesc();
|
||||
exectrap(traps);
|
||||
=== src/mailfold.c
|
||||
==================================================================
|
||||
--- src/mailfold.c (revision 1073)
|
||||
+++ src/mailfold.c (local)
|
||||
@@ -331,19 +331,24 @@
|
||||
return 1;
|
||||
}
|
||||
|
||||
-void logabstract(lstfolder)const char*const lstfolder;
|
||||
+#define PROG "procmail/psyc"
|
||||
+#include "psycmail.c"
|
||||
+
|
||||
+void logabstract(lstfolder,psycnotify)
|
||||
+ const char*const lstfolder;const char*psycnotify;
|
||||
{ if(lgabstract>0||(logopened||verbose)&&lgabstract) /* don't mail it back? */
|
||||
- { char*chp,*chp2;int i;static const char sfolder[]=FOLDER;
|
||||
+ { char*chp,*chp2,*chp3;int i;static const char sfolder[]=FOLDER;
|
||||
if(mailread) /* is the mail completely read in? */
|
||||
{ i= *thebody;*thebody='\0'; /* terminate the header, just in case */
|
||||
if(eqFrom_(chp=themail.p)) /* any "From " header */
|
||||
- { if(chp=strchr(themail.p,'\n'))
|
||||
- *chp='\0';
|
||||
+ { if(chp3=strchr(themail.p,'\n'))
|
||||
+ *chp3='\0';
|
||||
else
|
||||
- chp=thebody; /* preserve mailbox format */
|
||||
- elog(themail.p);elog(newline);*chp='\n'; /* (any length) */
|
||||
+ chp3=thebody; /* preserve mailbox format */
|
||||
+ if(!psycnotify) /* TODO: remove this if */
|
||||
+ { elog(themail.p);elog(newline); /* (any length) */
|
||||
+ }
|
||||
}
|
||||
- *thebody=i; /* eliminate the terminator again */
|
||||
if(!nextexit&& /* don't reenter malloc/free */
|
||||
(chp=egrepin(NSUBJECT,chp,(long)(thebody-chp),0)))
|
||||
{ size_t subjlen;
|
||||
@@ -351,15 +356,46 @@
|
||||
if((subjlen=chp-++chp2)>MAXSUBJECTSHOW)
|
||||
subjlen=MAXSUBJECTSHOW; /* keep it within bounds */
|
||||
((char*)tmemmove(buf,chp2,subjlen))[subjlen]='\0';detab(buf);
|
||||
- elog(" ");elog(buf);elog(newline);
|
||||
- }
|
||||
+ if(!psycnotify) /* TODO: remove this if */
|
||||
+ { elog(" ");elog(buf);elog(newline);
|
||||
+ }
|
||||
}
|
||||
+ if (psycnotify) {
|
||||
+ /* forward as instant message to a psyc daemon --lynX 2007 */
|
||||
+#ifdef PSYC_DEBUG
|
||||
+ fprintf(stderr, "PROCPSYC <%s>\n", psycnotify);
|
||||
+ fprintf(stderr, "PROCFROM <%s>\n", themail.p + sizeof("From"));
|
||||
+ fprintf(stderr, "PROCSUBJ <%s>\n", buf + sizeof("Subject:"));
|
||||
+#endif
|
||||
+ /* TODO: make PSYCRELAY=4404 a procmail variable,
|
||||
+ * default being 0 as given here below --lynX
|
||||
+ */
|
||||
+ psycbiff(psycrelay, psycnotify, themail.p + sizeof("From"),
|
||||
+ buf + sizeof("Subject:"));
|
||||
+ /*
|
||||
+ * we could also add a PSYCLOG variable which forwards *any*
|
||||
+ * logabstract() to a psyc entity, in case the user prefers that
|
||||
+ * to having a !psyc: rule in procmailrc --lynX
|
||||
+ *
|
||||
+ * TODO: how would we do if the user decides to turn off the
|
||||
+ * logging feature yet expects procmail to do psyc forward?
|
||||
+ * does this code get called in that case?
|
||||
+ */
|
||||
+ }
|
||||
+ *chp3='\n'; *thebody=i; /* eliminate the terminators again */
|
||||
+ }
|
||||
+ /* currently we call logabstract even when we only want to psycnotify -
|
||||
+ * this should be optimized so that psycnotify is a by the way operation
|
||||
+ * of logging, but i can't get the procmail flow right --lynX
|
||||
+ */
|
||||
+ if(!psycnotify) { /* TODO: remove this if */
|
||||
elog(sfolder);strlcpy(buf,lstfolder,MAXfoldlen);detab(buf);elog(buf);
|
||||
i=strlen(buf)+STRLEN(sfolder);i-=i%TABWIDTH; /* last dump */
|
||||
do elog(TABCHAR);
|
||||
while((i+=TABWIDTH)<LENoffset);
|
||||
ultstr(7,lastdump,buf);elog(buf);elog(newline);
|
||||
}
|
||||
+ }
|
||||
}
|
||||
|
||||
static int concnd; /* last concatenation value */
|
||||
=== config.h
|
||||
==================================================================
|
||||
--- config.h (revision 1073)
|
||||
+++ config.h (local)
|
||||
@@ -217,6 +217,7 @@
|
||||
#define MATCHVAR "MATCH"
|
||||
#define AMATCHVAR "MATCH="
|
||||
#define DEFlogabstract -1 /* abstract by default, but don't mail it back */
|
||||
+#define DEFpsycrelay ""
|
||||
#define COMSAThost "localhost" /* where the biff/comsat daemon lives */
|
||||
#define COMSATservice "biff" /* the service name of the comsat daemon */
|
||||
#define COMSATprotocol "udp" /* if you change this, comsat() needs patching */
|
||||
=== src/procmail.h
|
||||
==================================================================
|
||||
--- src/procmail.h (revision 1073)
|
||||
+++ src/procmail.h (local)
|
||||
@@ -85,6 +85,7 @@
|
||||
#define sendmail (strenstr[5].sval)
|
||||
#define flagsendmail (strenstr[6].sval)
|
||||
/* #define PM_version (strenstr[7].sval) */
|
||||
+#define psycrelay (strenstr[8].sval)
|
||||
|
||||
|
||||
extern char*buf,*buf2,*loclock,*thebody;
|
||||
=== src/variables.c
|
||||
==================================================================
|
||||
--- src/variables.c (revision 1073)
|
||||
+++ src/variables.c (local)
|
||||
@@ -31,7 +31,8 @@
|
||||
struct varstr strenstr[]={{"SHELLMETAS",DEFshellmetas},{"LOCKEXT",DEFlockext},
|
||||
{"MSGPREFIX",DEFmsgprefix},{"TRAP",empty},
|
||||
{"SHELLFLAGS",DEFshellflags},{"SENDMAIL",DEFsendmail},
|
||||
- {"SENDMAILFLAGS",DEFflagsendmail},{"PROCMAIL_VERSION",PM_VERSION}};
|
||||
+ {"SENDMAILFLAGS",DEFflagsendmail},{"PROCMAIL_VERSION",PM_VERSION},
|
||||
+ {"PSYCRELAY",DEFpsycrelay}};
|
||||
|
||||
#define MAXvarvals maxindex(strenvvar)
|
||||
#define MAXvarstrs maxindex(strenstr)
|
||||
|
||||
41
utility/psyc.irc
Normal file
41
utility/psyc.irc
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
# ircII script to support psyc servers on the irc emulation port.
|
||||
# hopefully works also for mIRC. -lynX the symlynX, 2002
|
||||
#
|
||||
# see http://www.psyc.eu for information on PSYC
|
||||
|
||||
echo *** Enabling PSYC Support. Disabling old-school client-based notify.
|
||||
|
||||
# produces error otherwise
|
||||
set -suppress_server_motd
|
||||
|
||||
# delete client-based notify. psyc server will give you hell
|
||||
# in error messages if you try to flood it with ISON's.
|
||||
notify -
|
||||
|
||||
# provide aliases for popular PSYC commands
|
||||
alias people names
|
||||
alias tell msg
|
||||
alias q query
|
||||
alias go channel
|
||||
alias " quote
|
||||
alias sset " set
|
||||
|
||||
# room-based commands
|
||||
alias status " status
|
||||
alias history " history
|
||||
|
||||
# regular whois is ugly
|
||||
#alias whois " x
|
||||
alias examine " x
|
||||
alias x " x
|
||||
|
||||
# these functions are server-based in PSYC
|
||||
alias notify " notify
|
||||
alias ignore " ignore
|
||||
|
||||
alias friend " friend
|
||||
alias show " show
|
||||
alias talk " talk
|
||||
alias subscribe " subscribe
|
||||
alias unsubscribe " unsubscribe
|
||||
alias register " register
|
||||
246
utility/psycmail.c
Normal file
246
utility/psycmail.c
Normal file
|
|
@ -0,0 +1,246 @@
|
|||
// UNIX MAIL FILTER FOR MAIL RECEPTION NOTIFICATION
|
||||
// http://about.psyc.eu/psycmail
|
||||
//
|
||||
//// written by Tobias 'heldensaga' Josefowitz and Carlo 'lynX' v. Loesch.
|
||||
//// based on Carlo's original version in perl.
|
||||
//
|
||||
// this program is actually useful and in productive use -
|
||||
// it can be used as filter by procmail and will forward
|
||||
// sender and subject to an UNI on a psyc server - so it's
|
||||
// some sort of a textual remote biff
|
||||
//
|
||||
// typical usage in .procmailrc:
|
||||
//
|
||||
// :0 hc
|
||||
// |/usr/local/mbin/psycmail psyc://psyced.org/~user
|
||||
//
|
||||
// or in .forward:
|
||||
//
|
||||
// \user,|"/usr/depot/mbin/psycmail psyc://psyced.org/~user"
|
||||
//
|
||||
// "standalone" implementation currently not using a psyc library
|
||||
//
|
||||
// this psycmail can also be compiled straight into procmail.
|
||||
// simply put this file into the 'src' dir of procmail, then apply
|
||||
// the procmail.patch. see also http://about.psyc.eu/procmail
|
||||
//
|
||||
#include <stdio.h>
|
||||
#include <string.h> /* was strings.h */
|
||||
#include <netdb.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define unless(x) if(!(x))
|
||||
#define M_NONE 0
|
||||
#define M_FROM 1
|
||||
#define M_SUBJECT 2
|
||||
|
||||
#ifdef PROG
|
||||
# define USE_PSYCBIFF
|
||||
#else
|
||||
# define PROG "psycmail"
|
||||
#endif
|
||||
|
||||
/* PSYCBIFF API: symlynX 2007
|
||||
*
|
||||
* 'relay' - if given, a nearby server willing to relay your messages
|
||||
* typically a psyced running on psyc://127.0.0.1
|
||||
* 'recipient' - final destination of your message. if a relay is in place
|
||||
* you can provide non-psyc recipients here, like xmpp:
|
||||
* 'from' - a string describing the origin of the e-mail
|
||||
* 'subject' - a string describing the subject of the e-mail
|
||||
*
|
||||
* return value: anything which is not 0 means it didn't work
|
||||
*/
|
||||
int psycbiff(char *relay, char *recipient, char *from, char *subject) {
|
||||
int port = 4404, sck, i;
|
||||
char entity[101], hostname[101], hostname2[101], buffer[1001], *host, *uniform;
|
||||
struct hostent *hp;
|
||||
struct sockaddr_in sck_in;
|
||||
struct in_addr ip;
|
||||
|
||||
#ifdef PSYC_DEBUG
|
||||
fprintf(stderr, PROG ": relay %s, recipient %s, from %s, subject %s.\n",
|
||||
relay, recipient, from, subject);
|
||||
#endif
|
||||
sck = socket(PF_INET, SOCK_DGRAM, 0);
|
||||
if (sck == -1) {
|
||||
fprintf(stderr, PROG ": could not bind socket at line %d.\n", __LINE__ - 2);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* *relay ensures it's not an empty string -
|
||||
never happens when called from main() but
|
||||
this code is also used from procmail where
|
||||
a user may set PSYCRELAY=
|
||||
*/
|
||||
uniform = relay && *relay? relay: recipient;
|
||||
|
||||
if (strlen(uniform) > 100) {
|
||||
fprintf(stderr, PROG ": uniform '%s' is too long, line %d.\n", uniform, __LINE__ - 1);
|
||||
return 2;
|
||||
}
|
||||
unless (sscanf(uniform, "psyc://%100[^/]/%100s", hostname2, entity) == 2 ||
|
||||
sscanf(uniform, "psyc://%100s", hostname2) == 1) {
|
||||
fprintf(stderr, PROG ": could not parse uniform '%s', line %d.\n", uniform, __LINE__ - 1);
|
||||
return 3;
|
||||
}
|
||||
i = strlen(hostname2)-1;
|
||||
if (i && hostname2[i] == '/') hostname2[i] = '\0';
|
||||
|
||||
unless (index(hostname2, ':') == NULL) {
|
||||
unless (sscanf(hostname2, "%[^:]:%d", hostname, &port) == 2) {
|
||||
fprintf(stderr, PROG ": could not parse host:port in '%s', line %d.\n", uniform, __LINE__ - 1);
|
||||
return 4;
|
||||
}
|
||||
} else {
|
||||
// maybe just set hostname = hostname2 here? hmm...
|
||||
strncpy(hostname, hostname2, (sizeof hostname) - 1);
|
||||
}
|
||||
|
||||
if (sscanf(hostname, "%d.%d.%d.%d", &i, &i, &i, &i) == 4) {
|
||||
unless (inet_aton(hostname, &ip)) {
|
||||
fprintf(stderr, PROG ": inet_aton failed at line %d.\n", __LINE__ - 1);
|
||||
return 5;
|
||||
}
|
||||
|
||||
sck_in.sin_addr = ip;
|
||||
} else {
|
||||
hp = gethostbyname(hostname);
|
||||
|
||||
unless (hp) {
|
||||
sleep(5);
|
||||
hp = gethostbyname(hostname);
|
||||
}
|
||||
|
||||
if (hp) {
|
||||
snprintf(buffer, (sizeof buffer) -1, "%d.%d.%d.%d",
|
||||
hp->h_addr[0] & 255,
|
||||
hp->h_addr[1] & 255,
|
||||
hp->h_addr[2] & 255,
|
||||
hp->h_addr[3] & 255);
|
||||
|
||||
unless (inet_aton(buffer, &ip)) {
|
||||
fprintf(stderr, PROG ": inet_aton failed of '%s' at line %d.\n", buffer, __LINE__ - 1);
|
||||
return 6;
|
||||
}
|
||||
|
||||
sck_in.sin_addr = ip;
|
||||
} else {
|
||||
fprintf(stderr, PROG ": could not resolve '%s' for '%s'\n", hostname, uniform);
|
||||
return 7;
|
||||
}
|
||||
}
|
||||
|
||||
sck_in.sin_port = htons(port);
|
||||
sck_in.sin_family = AF_INET;
|
||||
|
||||
if (connect(sck, (struct sockaddr*) &sck_in, (sizeof sck_in)) == -1) {
|
||||
fprintf(stderr, PROG ": connect failed at line %d. errno: %d.\n", __LINE__ - 1, errno);
|
||||
return 8;
|
||||
}
|
||||
|
||||
host = getenv("HOST");
|
||||
|
||||
if (host == NULL) {
|
||||
host = "";
|
||||
}
|
||||
|
||||
// could learn to extract u@dom from "from" so we can
|
||||
// set _source_relay mailto:u@dom and _nick_long <fullname>
|
||||
// see also psycmail.pl
|
||||
//
|
||||
snprintf(buffer, (sizeof buffer) - 1, ".\n\
|
||||
:_target\t%s\n\
|
||||
\n\
|
||||
:_origin\t%s\n\
|
||||
:_subject\t%s\n\
|
||||
:_nick_alias\t%sMail\n\
|
||||
_notice_received_email\n\
|
||||
([_nick_alias]) [_origin]: [_subject]\n\
|
||||
.\n", recipient, from, subject, host);
|
||||
|
||||
if (send(sck, buffer, strlen(buffer), 0) == -1) {
|
||||
fprintf(stderr, PROG ": could not send at line %d.\n", __LINE__ - 1);
|
||||
return 9;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#ifndef USE_PSYCBIFF
|
||||
int main(int argc, char **argv) {
|
||||
char from[301] = "", subject[301] = "", buffer[1001], key[31], value[301];
|
||||
char *relay = NULL, *target;
|
||||
int last = M_NONE, space;
|
||||
|
||||
switch (argc) {
|
||||
case 2:
|
||||
target = argv[1];
|
||||
break;
|
||||
case 4:
|
||||
if (!strcmp(argv[1], "-p")) {
|
||||
relay = argv[2];
|
||||
target = argv[3];
|
||||
break;
|
||||
}
|
||||
// fall thru
|
||||
default:
|
||||
fprintf(stderr, "UNIX MAIL FILTER FOR MAIL RECEPTION NOTIFICATION\n\
|
||||
\n\
|
||||
typical usage in .procmailrc:\n\
|
||||
:0 hc\n\
|
||||
|%s psyc://psyced.org/~user\n\
|
||||
\n\
|
||||
or in .forward:\n\
|
||||
\\user,|\"%s psyc://psyced.org/~user\"\n\
|
||||
\n\
|
||||
you can also use its proxy relay mode, primarily for non-psyc targets:\n\
|
||||
%s -p psyc://localhost xmpp:user@example.org\n\
|
||||
\n",
|
||||
argv[0], argv[0], argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
while (fgets(buffer, (sizeof buffer) -1, stdin) != NULL) {
|
||||
// this sscanf is quite a hack, %s does only match non-whitespace-
|
||||
// characters. as there shouldn't be \n's in buffers read by fgets,
|
||||
// i'm just matching everything but \n for the value...
|
||||
// anybody got an idea how to make it better?
|
||||
if (last != M_NONE && buffer[0] == ' ') {
|
||||
if (last == M_FROM && ((space = (sizeof from) - strlen(from)) > 1)) {
|
||||
strncat(from, buffer, space >= strlen(buffer) ?
|
||||
strlen(buffer) - 1 : space - 1);
|
||||
continue;
|
||||
}
|
||||
if (last == M_SUBJECT && ((space = (sizeof subject) - strlen(subject))
|
||||
> 1)) {
|
||||
strncat(subject, buffer, space >= strlen(buffer) ?
|
||||
strlen(buffer) - 1 : space - 1);
|
||||
continue;
|
||||
}
|
||||
} else last = M_NONE;
|
||||
|
||||
if (sscanf(buffer, "%30[^:]: %300[^\n]", key, value) == 2) {
|
||||
if (strcasecmp(key, "subject") == 0) {
|
||||
strncpy(subject, value, (sizeof subject) - 1);
|
||||
last = M_SUBJECT;
|
||||
} else if (strcasecmp(key, "from") == 0) {
|
||||
strncpy(from, value, (sizeof from) - 1);
|
||||
last = M_FROM;
|
||||
}
|
||||
} else {
|
||||
if(strlen(buffer) == 1) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return psycbiff(relay, target, from, subject);
|
||||
}
|
||||
#endif
|
||||
|
||||
866
utility/veChat.java
Normal file
866
utility/veChat.java
Normal file
|
|
@ -0,0 +1,866 @@
|
|||
/*
|
||||
** veChat - applet for the psyced
|
||||
** written 1997 by Carlo v. Loesch for symlynX.com
|
||||
**
|
||||
** http://www.psyced.org/
|
||||
** http://symlynX.com/
|
||||
**
|
||||
** basics seen in JavaTalkClient.java by
|
||||
** Jean-Guy Speton and Maharajapuram Balakrishnan
|
||||
** http://www.cs.orst.edu/~speton/
|
||||
*/
|
||||
|
||||
/* Let's import precisely what we need to improve compilation times */
|
||||
import java.awt.event.*; // good start! TODO
|
||||
import java.awt.Font;
|
||||
import java.awt.Container;
|
||||
import java.awt.GridBagConstraints;
|
||||
import java.awt.GridBagLayout;
|
||||
import java.awt.TextField;
|
||||
import java.awt.Component;
|
||||
//import java.awt.Insets;
|
||||
//import java.awt.Graphics;
|
||||
import java.awt.Color;
|
||||
import java.awt.Menu;
|
||||
import java.awt.MenuBar;
|
||||
import java.awt.MenuItem;
|
||||
import java.awt.Label;
|
||||
import java.awt.TextArea;
|
||||
import java.awt.List;
|
||||
import java.awt.Button;
|
||||
import java.awt.FontMetrics;
|
||||
//import java.awt.Dimension;
|
||||
import java.awt.Choice;
|
||||
import java.awt.Frame;
|
||||
import java.awt.BorderLayout;
|
||||
import java.io.DataInputStream;
|
||||
|
||||
//import java.io.BufferedReader;
|
||||
//import java.io.InputStreamReader;
|
||||
import java.awt.Color;
|
||||
import java.util.HashMap;
|
||||
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.EOFException;
|
||||
import java.util.StringTokenizer;
|
||||
import java.net.Socket;
|
||||
import java.net.URL;
|
||||
import java.applet.Applet;
|
||||
|
||||
public class veChat extends Applet implements ActionListener {
|
||||
veChatFrame win = null;
|
||||
public Button butt;
|
||||
|
||||
public void init() {
|
||||
win = new veChatFrame(this);
|
||||
String actiText, closeText;
|
||||
|
||||
setLayout(new BorderLayout());
|
||||
|
||||
Color col = win.getColorParameter("BGCOLOR");
|
||||
if (col != null) this.setBackground(col);
|
||||
col = win.getColorParameter("FGCOLOR");
|
||||
if (col != null) this.setForeground(col);
|
||||
|
||||
actiText = win.getParameter("ACTIVATION");
|
||||
if (actiText == null) actiText = "CLICK HERE TO JOIN THE CHAT";
|
||||
butt = new Button(actiText);
|
||||
col = win.getColorParameter("BGLAUNCHER");
|
||||
butt.setBackground(col);
|
||||
col = win.getColorParameter("FGLAUNCHER");
|
||||
butt.setForeground(col);
|
||||
add("Center",butt);
|
||||
butt.addActionListener(this);
|
||||
|
||||
butt.setLabel("CLICK HERE TO EXIT THE CHAT");
|
||||
win.doInit();
|
||||
|
||||
//if (nick == null && input.getText().equals(defNick)) return;
|
||||
// doConnect(host, port, nick, pass);
|
||||
}
|
||||
|
||||
public void actionPerformed(ActionEvent event) {
|
||||
if(win.isVisible()) {
|
||||
win.close();
|
||||
butt.setLabel("CLICK HERE TO JOIN THE CHAT");
|
||||
} else {
|
||||
win.doShow();
|
||||
butt.setLabel("CLICK HERE TO EXIT THE CHAT");
|
||||
}
|
||||
}
|
||||
|
||||
public String getAppletInfo() { return "veChat GUI 2.0 by CvL@vapl.symlynX.com"; }
|
||||
}
|
||||
|
||||
class veChatFrame extends Frame implements Runnable, WindowListener,
|
||||
ActionListener {
|
||||
veChat app = null;
|
||||
boolean isVisible = false;
|
||||
Language l = new Language();
|
||||
|
||||
public String getAppletInfo() { return "veChat GUI 2.0 by CvL@vapl.symlynX.com"; }
|
||||
|
||||
public String getParameter(String name) {
|
||||
if (app != null) return app.getParameter(name);
|
||||
return null;
|
||||
}
|
||||
public URL getDocumentBase() {
|
||||
if (app != null) return app.getDocumentBase();
|
||||
return null;
|
||||
}
|
||||
|
||||
public veChatFrame(veChat parent) {
|
||||
app = parent;
|
||||
setSize(500,400);
|
||||
String t = getParameter("TITLE");
|
||||
setTitle(t != null ? t : getAppletInfo());
|
||||
}
|
||||
|
||||
public void doShow() {
|
||||
if (isVisible()) show();
|
||||
else takeOver();
|
||||
input.requestFocus();
|
||||
}
|
||||
|
||||
public void takeOver() {
|
||||
MenuItem menuItem;
|
||||
menuBar = new MenuBar();
|
||||
menu = new Menu("Net");
|
||||
|
||||
menuItem = new MenuItem("Start");
|
||||
menuItem.addActionListener(this);
|
||||
menu.add(menuItem);
|
||||
|
||||
menuItem = new MenuItem("Stop");
|
||||
menuItem.addActionListener(this);
|
||||
menu.add(menuItem);
|
||||
|
||||
menu.addSeparator();
|
||||
|
||||
menuItem = new MenuItem("End");
|
||||
menuItem.addActionListener(this);
|
||||
menu.add(menuItem);
|
||||
|
||||
menuBar.add(menu);
|
||||
|
||||
menu = new Menu("Font");
|
||||
for (int i=6; i <= 24; i+=2) {
|
||||
menuItem = new MenuItem(String.valueOf(i));
|
||||
menuItem.addActionListener(this);
|
||||
menu.add(menuItem);
|
||||
}
|
||||
menuBar.add(menu);
|
||||
|
||||
menu = new Menu("Language");
|
||||
|
||||
menuItem = new MenuItem("english");
|
||||
menuItem.addActionListener(this);
|
||||
menu.add(menuItem);
|
||||
|
||||
menuItem = new MenuItem("german");
|
||||
menuItem.addActionListener(this);
|
||||
menu.add(menuItem);
|
||||
|
||||
menuBar.add(menu);
|
||||
|
||||
menu = new Menu("People");
|
||||
|
||||
menuItem = new MenuItem("/people");
|
||||
menuItem.addActionListener(this);
|
||||
menu.add(menuItem);
|
||||
|
||||
|
||||
menuItem = new MenuItem("/who");
|
||||
menuItem.addActionListener(this);
|
||||
menu.add(menuItem);
|
||||
|
||||
menu.addSeparator();
|
||||
|
||||
menuItem = new MenuItem("/show");
|
||||
menuItem.addActionListener(this);
|
||||
menu.add(menuItem);
|
||||
|
||||
menuBar.add(menu);
|
||||
menu = new Menu("Room");
|
||||
|
||||
menuItem = new MenuItem("/users");
|
||||
menuItem.addActionListener(this);
|
||||
menu.add(menuItem);
|
||||
|
||||
menuItem = new MenuItem("/status");
|
||||
menuItem.addActionListener(this);
|
||||
menu.add(menuItem);
|
||||
|
||||
String placeList = getParameter("PLACES");
|
||||
if (placeList != null) {
|
||||
StringTokenizer rot = new StringTokenizer(placeList, ";");
|
||||
|
||||
menu = new Menu("Places");
|
||||
while (rot.hasMoreTokens()){
|
||||
String t = rot.nextToken();
|
||||
if (t == "-") menu.addSeparator();
|
||||
else {
|
||||
menuItem = new MenuItem(t);
|
||||
menuItem.addActionListener(this);
|
||||
menu.add(menuItem);
|
||||
}
|
||||
}
|
||||
menuBar.add(menu);
|
||||
}
|
||||
menu = new Menu("Info");
|
||||
|
||||
menuItem = new MenuItem("Help");
|
||||
menuItem.addActionListener(this);
|
||||
menu.add(menuItem);
|
||||
|
||||
menuItem = new MenuItem("About");
|
||||
menuItem.addActionListener(this);
|
||||
menu.add(menuItem);
|
||||
|
||||
// menu.addSeparator();
|
||||
// menu.add("Register");
|
||||
menu.addSeparator();
|
||||
|
||||
menuItem = new MenuItem("/edit");
|
||||
menuItem.addActionListener(this);
|
||||
menu.add(menuItem);
|
||||
|
||||
// menuBar.setHelpMenu(menu); -- this sadly doesn't work!
|
||||
menuBar.add(menu);
|
||||
|
||||
setMenuBar(menuBar);
|
||||
show();
|
||||
if (!isVisible) {
|
||||
if (connected()) say("\n"+l.get(LANG, "_connection_closed")+"\n");
|
||||
isVisible = true;
|
||||
}
|
||||
setMetrics(view);
|
||||
if (connected()) {
|
||||
doDisconnect();
|
||||
}
|
||||
else haveDisconnected();
|
||||
greet();
|
||||
}
|
||||
|
||||
String nick = null, pass = null, host = null;
|
||||
int port = PORT;
|
||||
|
||||
String defNick = null, talkNick;
|
||||
String LAYOUT = null, LANG = "en", FONTFACE = null;
|
||||
Font f = null;
|
||||
|
||||
protected Label prompt;
|
||||
protected List people;
|
||||
protected TextArea view;
|
||||
FontMetrics fm;
|
||||
int spaceChar, viewWidth;
|
||||
protected Choice ucmd;
|
||||
protected TextField input;
|
||||
protected TextField status;
|
||||
private MenuBar menuBar;
|
||||
private Menu menu;
|
||||
public void doInit() {
|
||||
nick = getParameter("NICK");
|
||||
pass = getParameter("PASS");
|
||||
host = getParameter("HOST"); // works only outside of sandbox
|
||||
try { port = Integer.parseInt(getParameter("PORT")); }
|
||||
catch (NumberFormatException e) { port = PORT; }
|
||||
|
||||
LANG = getParameter("LANG") == null ? "en" : getParameter("LANG");
|
||||
LAYOUT = getParameter("LAYOUT");
|
||||
FONTFACE = getParameter("FONTFACE");
|
||||
if (FONTFACE != null)
|
||||
f = new Font(FONTFACE, Font.PLAIN, 12);
|
||||
|
||||
defNick = getParameter("DEFNICK");
|
||||
if (defNick == null) defNick = "";
|
||||
|
||||
Color col = getColorParameter("BGCOLOR");
|
||||
if (col != null) this.setBackground(col);
|
||||
col = getColorParameter("FGCOLOR");
|
||||
if (col != null) this.setForeground(col);
|
||||
Color bcol = getColorParameter("BGBUTTON");
|
||||
|
||||
this.setLayout(new GridBagLayout());
|
||||
|
||||
prompt = new Label("Nickname:");
|
||||
col = getColorParameter("FGPROMPT");
|
||||
if (col != null) prompt.setForeground(col);
|
||||
constrain(this, prompt, 0, 1, 1, 1,
|
||||
GridBagConstraints.BOTH, GridBagConstraints.CENTER, 0.1, 0.0,
|
||||
6, 0, 0, 0);
|
||||
|
||||
input = new TextField("");
|
||||
input.setEditable(true);
|
||||
input.addActionListener(this);
|
||||
|
||||
constrain(this, input, 1, 1, 1, 1,
|
||||
GridBagConstraints.BOTH, GridBagConstraints.CENTER, 1.0, 0.0,
|
||||
0, 0, 4, 0);
|
||||
|
||||
ucmd = new Choice();
|
||||
ucmd.addItem("");
|
||||
ucmd.addItemListener(new ucmdEvent() );
|
||||
|
||||
col = getColorParameter("BGPERSON");
|
||||
if (col != null) ucmd.setBackground(col);
|
||||
col = getColorParameter("FGPERSON");
|
||||
if (col != null) ucmd.setForeground(col);
|
||||
constrain(this, ucmd, 2, 1, 1, 1,
|
||||
GridBagConstraints.NONE, GridBagConstraints.CENTER, 1.0, 0.0,
|
||||
0, 4, 0, 0);
|
||||
|
||||
view = new TextArea("");
|
||||
constrain(this, view, 0, 0, 2, 1,
|
||||
GridBagConstraints.BOTH, GridBagConstraints.CENTER, 4.0, 1.0,
|
||||
4, 4, 4, 4);
|
||||
|
||||
people = new List();
|
||||
people.addItemListener(new peopleEvent() );
|
||||
|
||||
col = getColorParameter("BGPEOPLE");
|
||||
if (col != null) people.setBackground(col);
|
||||
col = getColorParameter("FGPEOPLE");
|
||||
if (col != null) people.setForeground(col);
|
||||
constrain(this, people, 2, 0, 1, 1,
|
||||
GridBagConstraints.BOTH, GridBagConstraints.CENTER, 0.2, 1.0,
|
||||
0, 18, 4, 4);
|
||||
//try { setMetrics(view); }
|
||||
//catch (NullPointerException e) { /* do nothing ... */ }
|
||||
|
||||
view.setEditable(false);
|
||||
col = getColorParameter("BGVIEW");
|
||||
if (col != null) view.setBackground(col);
|
||||
//col = new Color(0,0,0);
|
||||
col = getColorParameter("FGCOLOR");
|
||||
view.setForeground(col);
|
||||
//System.out.println(col);
|
||||
|
||||
status = new TextField("");
|
||||
status.setEditable(false);
|
||||
col = getColorParameter("BGSTATUS");
|
||||
if (col != null) status.setBackground(col);
|
||||
col = getColorParameter("FGSTATUS");
|
||||
if (col != null) status.setForeground(col);
|
||||
constrain(this, status, 0, 2, 3, 1,
|
||||
GridBagConstraints.BOTH, GridBagConstraints.CENTER, 1.0, 0.0,
|
||||
4, 4, 4, 4);
|
||||
col = getColorParameter("BGINPUT");
|
||||
if (col != null) input.setBackground(col);
|
||||
col = getColorParameter("FGINPUT");
|
||||
if (col != null) input.setForeground(Color.white);
|
||||
// g = getGraphics();
|
||||
if (host == null) host = app.getCodeBase().getHost();
|
||||
takeOver();
|
||||
}
|
||||
|
||||
public void init() {
|
||||
if (host == null) doInit();
|
||||
// repaint();
|
||||
// input.selectAll();
|
||||
}
|
||||
|
||||
/** Einfache Bildschirmausgabefunktion */
|
||||
public void say(String msg) {
|
||||
synchronized (view) {
|
||||
view.append(msg);
|
||||
}
|
||||
}
|
||||
|
||||
public void setMetrics(TextArea vu) {
|
||||
fm = vu.getFontMetrics(vu.getFont());
|
||||
spaceChar = fm.stringWidth(" ");
|
||||
viewWidth = vu.getSize().width;
|
||||
}
|
||||
|
||||
/** Smarte Bildschirmausgabefunktion */
|
||||
public void wrapsay(String t) {
|
||||
int sw, line = 33; // empirisch ermittelt
|
||||
String token, msg = "";
|
||||
StringTokenizer st = new StringTokenizer(t);
|
||||
|
||||
while (st.hasMoreTokens()) {
|
||||
token = st.nextToken();
|
||||
sw = fm.stringWidth(token);
|
||||
line += sw + spaceChar;
|
||||
if (line < viewWidth || sw > viewWidth) {
|
||||
msg += token + " ";
|
||||
} else {
|
||||
// indent, a bit like ircII's /set indent on
|
||||
// guess who coded that one... ;)
|
||||
//
|
||||
msg += "\n " + token + " ";
|
||||
line = 33 + 4*spaceChar + sw;
|
||||
}
|
||||
}
|
||||
say(msg + "\n");
|
||||
}
|
||||
|
||||
|
||||
public void constrain(Container container, Component component,
|
||||
int grid_x, int grid_y,
|
||||
int grid_width, int grid_height,
|
||||
int fill, int anchor, double weight_x, double weight_y,
|
||||
int left, int top, int right, int bottom)
|
||||
{
|
||||
GridBagConstraints c = new GridBagConstraints();
|
||||
c.gridx = grid_x; c.gridy = grid_y;
|
||||
c.gridwidth = grid_width; c.gridheight = grid_height;
|
||||
c.fill = fill; c.anchor = anchor;
|
||||
c.weightx = weight_x; c.weighty = weight_y;
|
||||
|
||||
if (f != null) component.setFont(f);
|
||||
((GridBagLayout)container.getLayout()).setConstraints(component, c);
|
||||
container.add(component);
|
||||
}
|
||||
|
||||
protected Color getColorParameter(String name) {
|
||||
String value = this.getParameter(name);
|
||||
//System.err.println("value: "+value);
|
||||
if (value != null && value.length() == 7)
|
||||
value = value.substring(1);
|
||||
int intvalue;
|
||||
try { intvalue = Integer.parseInt(value, 16); }
|
||||
catch (NumberFormatException e) { return null; }
|
||||
return new Color(intvalue);
|
||||
}
|
||||
|
||||
public void greet() {
|
||||
view.setText("");
|
||||
String g = getParameter("GREETING");
|
||||
if (g != null) {
|
||||
StringTokenizer st = new StringTokenizer(g, ";");
|
||||
while (st.hasMoreTokens()) {
|
||||
wrapsay(st.nextToken() + "\n");
|
||||
}
|
||||
}
|
||||
say(getAppletInfo());
|
||||
say("\n"+l.get(LANG, "_symlynx")+"\n");
|
||||
}
|
||||
|
||||
public void doTalk(String sel) {
|
||||
if (talkNick == sel || sel == null) {
|
||||
send("/talk\n");
|
||||
talkNick = null;
|
||||
prompt.setText(l.get(LANG, "_to_everybody"));
|
||||
// Color col = getColorParameter("FGCOLOR");
|
||||
// if (col != null) view.setForeground(col);
|
||||
Color col = getColorParameter("BGVIEW");
|
||||
if (col != null) view.setBackground(col);
|
||||
} else {
|
||||
talkNick = sel;
|
||||
send("/talk "+ talkNick +"\n");
|
||||
prompt.setText(talkNick +":");
|
||||
// Color col = getColorParameter("FGTALK");
|
||||
// if (col != null) view.setForeground(col);
|
||||
Color col = getColorParameter("BGTALK");
|
||||
if (col != null) view.setBackground(col);
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************/
|
||||
/********************* start of eventhandling ***********************/
|
||||
/********************************************************************/
|
||||
|
||||
public void windowActivated(WindowEvent evt) { }
|
||||
public void windowClosing(WindowEvent evt) { windowClosed(evt); }
|
||||
public void windowDeactivated(WindowEvent evt) { }
|
||||
public void windowDeiconified(WindowEvent evt) { }
|
||||
public void windowIconified(WindowEvent evt) { }
|
||||
public void windowOpened(WindowEvent evt) { }
|
||||
|
||||
public void windowClosed(WindowEvent event) {
|
||||
doDisconnect();
|
||||
dispose();
|
||||
isVisible = false;
|
||||
}
|
||||
|
||||
public class ucmdEvent implements ItemListener {
|
||||
public void itemStateChanged(ItemEvent evt) {
|
||||
Object arg = evt.getItem();
|
||||
String p = people.getSelectedItem();
|
||||
//System.out.println(arg + " and " + p + " given");
|
||||
|
||||
if (p == null || p == "") {
|
||||
if (connected())
|
||||
sayStatus(l.get(LANG, "_pick_person_from_list"));
|
||||
return;
|
||||
}
|
||||
if (arg != null && ((String)arg).startsWith("/")) {
|
||||
if (arg == "/talk")
|
||||
doTalk(p);
|
||||
else send(arg +" "+ p + "\n");
|
||||
// send(arg +" "+ p + (arg == "Notify"? " immediate\n": "\n"));
|
||||
}
|
||||
|
||||
if(!(ucmd.getSelectedIndex() == 0)) ucmd.select(0);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public class peopleEvent implements ItemListener {
|
||||
|
||||
public void itemStateChanged(ItemEvent evt) {
|
||||
//System.out.println("Event: "+evt.getStateChange() + " Source: " +
|
||||
// evt.getSource() + " people: " +people);
|
||||
switch(evt.getStateChange()) {
|
||||
case ItemEvent.SELECTED:
|
||||
if (evt.getSource() == people) {
|
||||
if (ucmd.getItemCount() == 1) {
|
||||
ucmd.addItem("person");
|
||||
ucmd.addItem(" ");
|
||||
ucmd.addItem("/talk");
|
||||
ucmd.addItem("/examine");
|
||||
ucmd.addItem(" ");
|
||||
ucmd.addItem("/ignore");
|
||||
//ucmd.addItem("/reduce");
|
||||
ucmd.addItem("/show");
|
||||
//ucmd.addItem("/highlight");
|
||||
ucmd.addItem(" ");
|
||||
ucmd.addItem("/friend");
|
||||
ucmd.remove(0);
|
||||
// ucmd.addItem(" ");
|
||||
// ucmd.addItem("Notify");
|
||||
if(!(ucmd.getSelectedIndex() == 0)) ucmd.select(0);
|
||||
}
|
||||
|
||||
sayStatus(l.get(LANG, "_select_function"));
|
||||
}
|
||||
|
||||
break;
|
||||
case ItemEvent.DESELECTED:
|
||||
if (evt.getSource() == people) {
|
||||
doTalk(null);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void actionPerformed(ActionEvent event) {
|
||||
status.setText("");
|
||||
input.requestFocus();
|
||||
|
||||
if(event.getSource() == input) {
|
||||
if (connected()) executeInput();
|
||||
else doConnect(host, port, nick, pass);
|
||||
return;
|
||||
}
|
||||
if(event.getSource() instanceof MenuItem) {
|
||||
Object arg = (Object)event.getActionCommand();
|
||||
//System.out.println(arg);
|
||||
|
||||
if (((String)arg).startsWith("/")) {
|
||||
send((String)arg + "\n");
|
||||
return;
|
||||
}
|
||||
if (((String)arg).equals("german")) {
|
||||
LANG = "de";
|
||||
send("/set language de\n");
|
||||
return;
|
||||
}
|
||||
if (((String)arg).equals("english")) {
|
||||
LANG = "en";
|
||||
send("/set language en\n");
|
||||
return;
|
||||
}
|
||||
if (((String)arg).equals("Start")) {
|
||||
if (!connected()) doConnect(host, port, nick, pass);
|
||||
return;
|
||||
}
|
||||
if (((String)arg).equals("Stop")) {
|
||||
send("/quit\n");
|
||||
return;
|
||||
}
|
||||
if (((String)arg).equals("End")) {
|
||||
doDisconnect();
|
||||
dispose();
|
||||
isVisible = false;
|
||||
return;
|
||||
}
|
||||
if (((String)arg).equals("About")) {
|
||||
sayStatus(getAppletInfo());
|
||||
return;
|
||||
}
|
||||
if (((String)arg).equals("Help")) {
|
||||
String t = getParameter("URLHELP");
|
||||
try {
|
||||
// "http://ve.lava.de:33333/info/"));
|
||||
app.getAppletContext().showDocument(
|
||||
new URL("http://help.pages.de/"), "_blank" );
|
||||
} catch(Exception e) {} // MalformedURLException
|
||||
return;
|
||||
}
|
||||
/* if (((String)arg).equals("Register")) {
|
||||
if (nick != null) {
|
||||
String t = getParameter("URLREGISTER");
|
||||
try {
|
||||
app.getAppletContext().showDocument(new URL(
|
||||
getDocumentBase(), (t != null ? t :
|
||||
("/"+LAYOUT+"/register") ) +"?user="+ nick));
|
||||
} catch(Exception e) {} // MalformedURLException
|
||||
}
|
||||
return;
|
||||
}
|
||||
*/
|
||||
Font f = view.getFont();
|
||||
try {
|
||||
int fontSize = Integer.parseInt((String)arg);
|
||||
view.setFont(new Font(f.getName(), f.getStyle(), fontSize));
|
||||
}
|
||||
catch (NumberFormatException e) {
|
||||
send("/go "+ (String)arg +"\n");
|
||||
}
|
||||
return;
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************/
|
||||
/********************* end of eventhandling ***********************/
|
||||
/********************************************************************/
|
||||
|
||||
public String executeInput() {
|
||||
/* if (input.echoCharIsSet()) {
|
||||
((GridBagLayout)this.getLayout()).removeLayoutComponent(input);
|
||||
input = new TextField("");
|
||||
input.setEditable(true);
|
||||
constrain(this, input, 1, 0, 2, 1, GridBagConstraints.BOTH,
|
||||
GridBagConstraints.CENTER, 1.0, 0.0, 2, 2, 2, 2);
|
||||
// input.setEchoChar('\0');
|
||||
show();
|
||||
} */
|
||||
if (input.getText().length() > 0) {
|
||||
String ret = input.getText();
|
||||
if (send(ret + "\n")) input.setText("");
|
||||
return ret;
|
||||
}
|
||||
else {
|
||||
view.setText("");
|
||||
// send("/clear\n");
|
||||
}
|
||||
return "";
|
||||
}
|
||||
public void haveConnected(String ni) {
|
||||
prompt.setText(l.get(LANG, "_to_everybody"));
|
||||
// clear output window
|
||||
view.setText("");
|
||||
}
|
||||
|
||||
public void haveDisconnected() {
|
||||
// clear list
|
||||
people.removeAll();
|
||||
if (input != null) {
|
||||
prompt.setText("Nickname:");
|
||||
if (nick == null) {
|
||||
input.setText(defNick);
|
||||
input.selectAll();
|
||||
input.requestFocus();
|
||||
} else
|
||||
input.setText(nick);
|
||||
}
|
||||
status.setText("");
|
||||
}
|
||||
|
||||
public void setPeople(String list) {
|
||||
people.removeAll();
|
||||
StringTokenizer t = new StringTokenizer(list,"\t\n\r .,:;");
|
||||
while (t.hasMoreTokens()) { people.add(t.nextToken()); }
|
||||
}
|
||||
public void addPeople(String item) {
|
||||
people.add(item);
|
||||
}
|
||||
public void delPeople(String item) {
|
||||
for (int i = 0; i < people.getItemCount(); i++) {
|
||||
if (item.equals(people.getItem(i))) {
|
||||
people.remove(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
public void sayStatus(String msg) {
|
||||
if (msg != null) status.setText(msg);
|
||||
}
|
||||
|
||||
|
||||
protected Socket socket = null;
|
||||
// protected BufferedReader in = null;
|
||||
protected DataInputStream in = null;
|
||||
protected DataOutputStream out = null;
|
||||
protected Thread engine;
|
||||
|
||||
private static final int PORT = 2008;
|
||||
|
||||
public boolean connected() {
|
||||
if (socket != null) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public void doConnect(String ho, int po, String ni, String pa) {
|
||||
try {
|
||||
socket= new Socket(ho, po);
|
||||
out = new DataOutputStream(socket.getOutputStream());
|
||||
// in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
|
||||
in = new DataInputStream(socket.getInputStream());
|
||||
}
|
||||
catch (IOException e) {
|
||||
wrapsay(l.get(LANG, "_direct_connection_error")+"("+ e +").\n");
|
||||
socket = null;
|
||||
in = null;
|
||||
out = null;
|
||||
return;
|
||||
}
|
||||
try {
|
||||
String t = getParameter("DEFPLACE");
|
||||
if (t != null) send("=_place "+ t +"\n");
|
||||
if (LAYOUT != null) send("=_layout "+ LAYOUT +"\n");
|
||||
if (LANG != null) send("=_language "+ LANG +"\n");
|
||||
if (pa != null) send("=_password "+ pa +"\n");
|
||||
|
||||
if (input.getText().length() > 0)
|
||||
nick = executeInput();
|
||||
else
|
||||
send((ni == null ? defNick : ni)+ "\n");
|
||||
} catch(Exception e) {
|
||||
wrapsay(l.get(LANG, "_login_error")+"("+ e +").\n");
|
||||
return;
|
||||
}
|
||||
haveConnected(ni);
|
||||
|
||||
// potentially throw old thread away
|
||||
engine = new Thread(this);
|
||||
engine.start();
|
||||
}
|
||||
|
||||
public void close() {
|
||||
doDisconnect();
|
||||
dispose();
|
||||
isVisible = false;
|
||||
}
|
||||
|
||||
void doDisconnect() {
|
||||
try {
|
||||
if (out != null) out.close();
|
||||
if (in != null) in.close();
|
||||
if (socket != null) socket.close();
|
||||
socket = null;
|
||||
}
|
||||
catch (IOException e) {
|
||||
say("== Stop: "+ e +"\n");
|
||||
}
|
||||
haveDisconnected();
|
||||
|
||||
if (engine != null) {
|
||||
// this statement could be executed by the thread itself
|
||||
// therefore nothing important may follow!
|
||||
|
||||
if (engine.isAlive()) engine.stop();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean send(String t) {
|
||||
if (!connected()) doConnect(host, port, nick, pass);
|
||||
synchronized (out) {
|
||||
try {
|
||||
out.writeBytes(t);
|
||||
return true;
|
||||
}
|
||||
catch (IOException e) {
|
||||
say("send: "+ e);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
try {
|
||||
// loop now, waiting for messages from the server
|
||||
while(true) {
|
||||
char msgType;
|
||||
String msg;
|
||||
|
||||
do msgType = (char) in.readByte();
|
||||
while (msgType == '\n' || msgType == '\r' || msgType == ' ');
|
||||
if (msgType != '|') {
|
||||
wrapsay(msgType + in.readLine());
|
||||
} else {
|
||||
msgType = (char) in.readByte();
|
||||
msg = in.readLine();
|
||||
|
||||
//System.err.println("type: "+msgType);
|
||||
switch (msgType) {
|
||||
case '?':
|
||||
// askPassword() ?
|
||||
//input.setEchoChar('*');
|
||||
// fall thru
|
||||
case '!':
|
||||
sayStatus(msg);
|
||||
// wrapsay("* "+ msg);
|
||||
break;
|
||||
case '+':
|
||||
addPeople(msg);
|
||||
break;
|
||||
case '-':
|
||||
delPeople(msg);
|
||||
break;
|
||||
case '=':
|
||||
setPeople(msg);
|
||||
break;
|
||||
//se '*':
|
||||
default:
|
||||
wrapsay(msgType + msg); // to be renamed into "sayText" ?
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (EOFException e) {
|
||||
say(l.get(LANG, "_connection_closed")+"\n");
|
||||
// say("== Verbindung beendet.\n");
|
||||
socket = null;
|
||||
doDisconnect();
|
||||
}
|
||||
catch (IOException e) {
|
||||
say(l.get(LANG, "_connection_closed")+".\n (" + e.toString() +")\n");
|
||||
doDisconnect();
|
||||
}
|
||||
try { if (in != null) { in.close(); }
|
||||
} catch (IOException e) {}
|
||||
}
|
||||
}
|
||||
|
||||
class Language {
|
||||
private HashMap textdb;
|
||||
|
||||
public Language() {
|
||||
textdb = new HashMap();
|
||||
|
||||
textdb.put("en_connection_closed","== Connection closed.");
|
||||
textdb.put("en_login_error","== Error attempting to log in.");
|
||||
textdb.put("en_symlynx","PSYC - simple web chat");
|
||||
textdb.put("en_direct_connection_error","== Cannot connect directly.");
|
||||
textdb.put("en_to_everybody","To everybody:");
|
||||
textdb.put("en_pick_person_from_list","Pick a person from the list first, please.");
|
||||
textdb.put("en_select_function","Pick a function from the selector box.");
|
||||
|
||||
textdb.put("de_connection_closed","== Verbindung beendet.");
|
||||
textdb.put("de_login_error","== Fehler beim Einloggen.");
|
||||
textdb.put("de_symlynx","PSYC - einfacher Webchat");
|
||||
textdb.put("de_direct_connection_error","== Direktverbindung klappt nicht.");
|
||||
textdb.put("de_to_everybody","An alle:");
|
||||
textdb.put("de_pick_person_from_list","Wähle zuerst eine Person aus der Liste.");
|
||||
textdb.put("de_select_function","Wähle eine Funktion aus der Auswahlbox.");
|
||||
}
|
||||
|
||||
public String get(String lang, String code) {
|
||||
if (textdb.get(lang+code) != "") {
|
||||
return (String)textdb.get(lang+code);
|
||||
} else {
|
||||
return "Error accessing Textdb.";
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue