aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/scripts/astcli
blob: cf0ebdf15acbfabdc916eb89b0e7aca577c3ddc7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
#!/usr/bin/perl -w

use strict;
use IO::Socket;
use Getopt::Long;

# Created by: David Van Ginneken
# Bird's the Word Technologies
# davevg@btwtech.com
#
# And distributed under the terms of the GPL
#
my ($user, $pw, $host, $port, $interactive, $save) = (undef, undef, 'localhost', 5038, 0, 0);
my $EOL = "\r\n"; # Standard End of Line
process_credentials('/etc/astcli.conf');
process_credentials("$ENV{HOME}/.astcli") if defined $ENV{HOME};
GetOptions("username=s" => \$user, "secret=s" => \$pw, "host=s" => \$host, "port=s" => \$port, "readline" => \$interactive, "write" => \$save);

$|++; # Auto Flush Output
my $action = join(" ", @ARGV);

&usage if (!defined $user || !defined $pw);
my $tc = new IO::Socket::INET(
		PeerAddr => $host,
		PeerPort => $port,
		Timeout => 30,
		Proto => 'tcp'
) or die "Could not connect to Host: $host on port $port\n";
if (my $error = login()) {
	print STDERR $error;
	exit 1;
};

if ($save) {
	if (-d $ENV{HOME}) {
		open DEFAULT, ">$ENV{HOME}/.astcli";
		print DEFAULT "username=$user\n" if $user;
		print DEFAULT "password=$pw\n" if $pw;
		print DEFAULT "hostname=$host\n" if $host;
		print DEFAULT "portno=$port\n" if $port;
		close DEFAULT;
	}
}

# Send a single command to the manager connection handle (global $tc).
# Assumes things always work well :-)
sub send_command($) {
	my $command = shift;
	$tc->send('Action: Command' . $EOL);
	$tc->send("Command: $command" . $EOL);
	$tc->send($EOL);
	my $response = '';
	while (<$tc>) {
		last if $_ =~ /--END COMMAND--/;
		$response .= $_;
	}
	$response =~ s/Privilege: Command$EOL//;
	$response =~ s/Response: Follows$EOL//;
	print $response;
}

sub login {
	my ($response, $message);
	$tc->send("Action: Login" . $EOL);
	$tc->send("Username: $user" . $EOL);
	$tc->send("Secret: $pw" . $EOL);
	$tc->send("Events: off" . $EOL);
	$tc->send($EOL);
	while (<$tc>) {
		last if $_ eq $EOL;
		$_ =~ s/$EOL//g;
		($response) = $_ =~ /^Response: (.*?)$/ if $_ =~ /^Response:/;
		($message) = $_ =~ /^Message: (.*?)$/ if $_ =~ /^Message:/;
	}
	return 0 if $response eq 'Success';
	return $message;
}

sub logoff {
	my ($response, $message);
	$tc->send("Action: Logoff" . $EOL . $EOL);
	return 1;
}

# If the user asked to send commands from standard input:
if ($action eq '-' || !defined $action || $action eq '') {
	if ($interactive) {
		eval { require Term::ReadLine;};
		$interactive = scalar($@) ? 0 : 1;
		print STDERR "Falling back to standard mode, Unable to load Term::Readline for readline mode\n" unless $interactive;
	}
	if ($interactive) {
		my $term = new Term::ReadLine 'Command Line Interface';
		my $prompt = "$host*CLI> ";
		my $attribs = $term->Attribs;
		$attribs->{completion_function} = sub {
			my ($text, $line, $start) = @_;
			# Stub function for tab auto completion for those feeling adventurous
			return;
		};
		while (defined($_ = $term->readline($prompt))) {
			(logoff() and exit) if $_ =~ /exit|quit/; # Give them a way to exit the "terminal"
			send_command($_);
		}	
	} else {
		while (<>) {
			chomp;
			(logoff() and exit) if $_ =~ /exit|quit/; # If someone accidentally ends up here, let them exit
			send_command($_);
		}
	}
	exit 0;
}

# Otherwise just send the command:
send_command($action);

# parses a configuration file into the global $user and $pw.
sub process_credentials {
	# Process the credentials found..
	my $file = shift;
	# silently fail if we can't read the file:
	return unless (-r $file);
	open (my $fh, "<$file") or return;
	while (<$fh>) {
		chomp;
		(undef,$user) = split(/[,=]/, $_) if $_ =~ /user(name)?[,=]/i;
		(undef,$pw) = split(/[,=]/, $_) if $_ =~ /(secret|passw(or)?d|pwd?)[,=]/i;
		(undef,$host) = split(/[,=]/, $_) if $_ =~ /host(name)?[,=]/i;
		(undef,$port) = split(/[,=]/, $_) if $_ =~ /port(num|no)?[,=]/i;
	}
	close ($fh);
}

sub usage {
	print STDERR "astcli [<options>] [<cli-command>|-]\n";
	print STDERR "       -u <name> - Connect as username <name>\n";
	print STDERR "       -s <pw>   - Connect with secret <pw>\n";
	print STDERR "       -h <host> - Connect to host <host> [localhost]\n";
	print STDERR "       -p <port> - Connect on TCP port <port> [5038]\n";
	print STDERR "       -r        - Start a readline session for interactivity\n";
	print STDERR "       -w        - Save connection options in a configuration file\n";
	print STDERR "   You may specify the command as '-' to take commands from stdin.\n";
	exit;
}