#!/usr/bin/perl # # use Net::PSYC; sub debug() { 1 } use Getopt::Std; getopt('pime'); # pick the name of an ego from the environment # FIXME: assuming nickname has no whitespace my $nick = $opt_e || $ENV{'PSYCNICK'} || $ENV{'NICK'} # this one should work with any chat system || $ENV{'IRCNICK'} || $ENV{'USER'} || 'user'; my $peerid = $opt_i || $ENV{'GNUNET_PEERID'} # peerid of the gnunet node runnning on cheet || 'TVV54YYR29KRDKM30ZC3014JXHDGPVT7KFQGA44CEV2YQSEVFDAG'; my $place = $opt_p || $ENV{'PSYCPLACE'} # pubkey of a place created on cheet || 'RG3RY7FTTT6128V1HGZQCQ89Q5APTHSP2JD9WKGH4T2N7KQZFVQG'; my $method = $opt_m || '_notice_testing_psycit'; # first, let's check if we are being run by the correct user my $cf = "$ENV{HOME}/.config/gnunet.conf"; die "This user has no $cf that I can read" unless open(C, $cf); my $ok = 0; while() { # i'll check for [arm] some other day... FIXME $ok++ if /^\s*USER_ONLY\s*=\s*YES\s*$/i; } close C; die "Your $cf is not configured to run user services" unless $ok; # now, let's see if the services are up my $cmd = 'gnunet-arm --info |'; die "$cmd failed: $!" unless open(C, $cmd); $ok = 0; while() { $ok++ if /^(gns|social|identity) /; } close C; die "Not all of GNS, social and identity services are running" if $ok != 3; unless ($ego = fetchEgo($nick)) { die "Could not create ego for $nick: $!" unless sys('gnunet-identity', '--create', $nick); die "Could not fetch ego for $nick after creation: $!" unless $ego = fetchEgo($nick); die "Could not assign $nick's ego as default for social: $!" # FIXME: --set instead of --service doesnt look intuitive unless sys('gnunet-identity', '--ego', $nick, '-s', 'social'); } if ($opt_C) { # FIXME: gnunet-social should not need different commands here, # checking for presence of -p parameter should be enough. &sys( "gnunet-social -e $ego --follow ".( $opt_p? "--host-reconnect -p $opt_p" : "--host-enter --welcome" )); } elsif ($opt_S) { # FIXME: why do we have differing API calls for entering and # reconnecting a place? &sys( "gnunet-social --guest-enter --follow -e $ego -p $place -i $peerid" ); } elsif ($opt_P) { my $d = ''; if ($#ARGV > 0) { $d = join(' ', @ARGV); } else { $d .= $_ while ; } $d =~ tr/[\r\n]/ /; chomp $d; # FIXME: API must be able to know by itself if a place is local or remote # therefore the distinction of guest-talk and host-announce must go &sys( "gnunet-social --guest-talk -m $method -d '$d' -e $ego -p $place -i $peerid" ); } else { print < [-c] [-p ] [-i ] [-m ] [-e ] [ ] Commands are: -C create or reconnect to a locally hosted pubsub channel (will not terminate as messages are expected) -S enter or reconnect to a remotely hosted pubsub channel (will not terminate as messages are expected) -P publish to a channel -h show this help Parameters are: -p use this place where necessary -i use this GNUnet PeerID where necessary -e use this ego where necessary for publishing, can also be passed via stdin. Options are: -c continue in case of errors -m use a different method when publishing X # -L leave a channel # -s show some status } exit; sub sys { print "=> ", join(' ', @_), "\n" if debug; if (system(@_)) { if ($? == -1) { print "failed to execute: $!\n"; } elsif ($? & 127) { printf "child died with signal %d, %s coredump\n", ($? & 127), ($? & 128) ? 'with' : 'without'; } else { printf "child exited with value %d\n", $? >> 8; } exit $? unless $opt_c; return 0; } return 1; } sub fetchEgo { my $n = shift; # FIXME: there should be some UX consistency between gnunet tools # regarding --list, --info or --display # FIXME: gnunet-identity should offer a way to resolve exactly one # ego nickname my $e = undef, $cmd = 'gnunet-identity --display |'; local(*C); die "$cmd failed: $!" unless open(C, $cmd); while() { # print; $e = $1 if /^$n - (\w+)$/i; # may i ignore case? } close C; return $e; }