File: shscripts.pl

package info (click to toggle)
gmoo 0.5.6-11
  • links: PTS
  • area: main
  • in suites: etch, etch-m68k
  • size: 2,412 kB
  • ctags: 2,213
  • sloc: ansic: 18,320; sh: 5,396; makefile: 385; perl: 205; sed: 93; tcl: 30
file content (250 lines) | stat: -rw-r--r-- 7,626 bytes parent folder | download | duplicates (2)
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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
# Gmoo Perl subroutines/macros, version 0.9.1
# 
# Used for shell extenstions for gmoo.
# by Paul van Tilburg <paul@luon.net>
#
# $Id: shscripts.pl,v 1.4 2002/04/16 20:15:35 paul-cs Exp $

use strict;
use vars qw($VERSION);

$VERSION = '0.9.1';

# COMMANDS:
CLIENT::register_macro("sh",         "sh_cb",       "Run shell command, output to user.");
CLIENT::register_macro("run",        "run_cb",      "Run shell command, output through emote.");
CLIENT::register_macro("crun",       "crun_cb",     "Run shell command, output to channel.");
CLIENT::register_macro("pstrun",     "pstrun_cb",   "Run shell command, output through \@paste.");
CLIENT::register_macro("ppstrun",    "ppstrun_cb",  "Run shell command, output through \@paste <someone>.");
CLIENT::register_macro("prefrun",    "prefrun_cb",  "Run shell command, use prefix for output.");

# CONFIGURING:
CLIENT::register_macro("shsetopt",   "setopt_cb",   "Set an shscripts plugin option and save.");
CLIENT::register_macro("shlistopts", "listopts_cb", "List all available options and their values.");

# HELP:
CLIENT::register_macro("shhelp",     "help_cb",      "Show list of all available commands.");

# run(COMMAND) => OUTPUTREF
# Runs command and generates output array with cerain features (line
# numbering, limited execution time) and returns reference to that array.
sub run {
  my $Cmd = shift;
  my ($Outputref, $config, $i);

  eval { $config = get_conf(); };
  chomp $@;
  return "[$@]" if $@;

  eval {
    local $SIG{'ALRM'} = sub { die "Timed out\n" };
    alarm $config->{'timeout'};

    push @$Outputref, "Command: $Cmd" if $config->{'showcommand'};
    open CMD, $config->{'showstderr'} ? "$Cmd 2>&1|" : "$Cmd|" or die "$!\n";
    while (<CMD>) { 
      if ($i == $config->{'maxlines'}) {
	push @$Outputref, "Command aborted, output exceeded limit of " .
	                  "$config->{maxlines} lines.";
	last;
      }
      $i++;
      if ($config->{'showlinenum'}) {
        push @$Outputref, 
	     sprintf("%" . length($config->{'maxlines'}) . "d: %s", $i, $_); 
      }
      else {
        push @$Outputref, $_; 
      }
    }
    close CMD;

    push @$Outputref, "=> " . ($? >> 8) if $config->{'showretval'}
  };
  alarm 0;
     
  chomp $@;
  if ($@ =~ /Timed out/) {
    push @$Outputref,
         "Command execution terminated: " .
         "timed out after $config->{timeout} seconds!" if $@;
  }
  elsif ($@) {
    push @$Outputref, "Command execution failed: $@!";
  }

  return $Outputref;
}

# get_conf() => CONFIGREF
# Reads configuration in ~/.gmoo/shscripts.conf (if exists), parses
# key/values and returns hash reference.
sub get_conf {
  my ($key, $value);
  my $cfile = "$ENV{HOME}/.gmoo/shscripts.conf";

  # Default configuration:
  my $config = { timeout     => 8,
                 showcommand => 0,
		 showlinenum => 0,
		 showretval  => 1,
		 showstderr  => 0,
		 maxlines    => 50 };
  
  if (-r $cfile) {
    open CONFIG, "<$cfile" or die "Can't open configfile '$cfile': $!\n";
    
    while (<CONFIG>) {
      chomp; s/#.*//;
      if (($key, $value) = /^\s*(\S+)\s*=\s*(\S.*)/) { $config->{$key} = $value; }
    }
    
    close CONFIG;
  }

  return $config;
}

# put_conf(CONFIGREF)
# Writes configuration as 'key = value' pairs to ~/.gmoo/shscripts.conf
sub put_conf {
  my $config = shift;
  my $cfile = "$ENV{HOME}/.gmoo/shscripts.conf";

  open CONFIG, ">$cfile" or die "Can't write to configfile '$cfile': $!\n";
  print CONFIG "# This file is auto generated by the shscrips plugin.\n",
               "# Do NOT attempt to edit this file, use /shlistopts, /shsetopt instead!\n\n";
  
  foreach (sort keys %$config) {
     print CONFIG "$_ = $config->{$_}\n";
  }

  close CONFIG;
}

# Syntax: /sh <command>
sub sh_cb { 
  my ($World, $Cmd) = @_;
  my $Ref;

  $Ref = &run($Cmd);
  foreach (@$Ref) { chomp; WORLD::msg($World, $_); }
}

# Syntax: /run <command>
sub run_cb {
  my ($World, $Cmd) = @_;
  my $Ref = &run($Cmd);
  WORLD::writeln($World, ":LINUXes: `$Cmd`");
  foreach (@$Ref) { chomp; WORLD::writeln($World, "emote | $_"); }
}

# Syntax: /crun <chan_alias> <command>
# Depends on the existance of channelaliases in the MOO/MUD.
sub crun_cb {
  my $World = shift;
  my ($Channel, @Command) = split(/ /, shift);
  my $Cmd = join(" ", @Command);
  my $Ref = &run($Cmd);
  
  WORLD::writeln($World, "$Channel :LINUXes: `$Cmd`");
  foreach (@$Ref) { chomp; WORLD::writeln($World, "$Channel emote | $_"); }
}

# Syntax: /pstrun <command>
# Depends on the exitsance of the command '@paste'.
sub pstrun_cb {
  my ($World, $Cmd) = @_;
  my $Ref = &run($Cmd);

  WORLD::writeln($World, "\@paste\n\$ $Cmd");
  foreach (@$Ref) { chomp, WORLD::writeln($World, $_); }
  WORLD::writeln($World, ".");
}

# Syntax: /ppstrun <someone> <command>
# Depends on the existance of the command '@paste' and the possibility
# to paste private with: @paste <someone>.
sub ppstrun_cb {
  my $World = shift;
  my ($Target, @Command) = split(/ /, shift);
  my $Ref = &run(join(" ", @Command));
  
  WORLD::writeln($World, "\@paste $Target\n\$ @Command");
  foreach (@$Ref) { chomp, WORLD::writeln($World, $_); }
  WORLD::writeln($World, ".");
}

# Syntax: /prefrun <prefix> <command>
# Send output to world with everyline prefixed by <prefix><space>.
sub prefrun_cb {
  my $World = shift;
  my ($Prefix, @Command) = split(/ /, shift);
  my $Ref = &run(@Command);
  
  foreach (@$Ref) { chomp; WORLD::writeln($World, "$Prefix $_"); }
}

# Syntax: /listopts
# List all configuration options used by this plugin.
sub listopts_cb {
  my $World = shift;
  my $config;

  eval { $config = get_conf(); };
  chomp $@;
  return WORLD::msg($World, $@) if $@;

  WORLD::msg($World, "SHSCRIPTS plugin options:");
  foreach (sort keys %$config) {
    WORLD::msg($World, "$_ = $config->{$_}");
  }
}

# Syntax: /setopt <key> <value>
# Sets an option to given value if option exists, and saves changed
# parameter to disk for next Gmoo sessions.
sub setopt_cb {
  my ($World, $keyval) = @_;
  my ($key, $value) = split(/ /, $keyval);
  my $config;
  my $prev;

  eval { $config = get_conf(); };
  chomp $@;
  return WORLD::msg($World, $@) if $@;

  if (defined($prev = $config->{$key})) {
    $config->{$key} = $value;
    
    eval { put_conf($config); };
    chomp $@;
    return WORLD::msg($World, $@) if $@;

    WORLD::msg($World, 
               "SHSCRIPTS plugin option '$key' changed from $prev to $value.");
  }
  else {  
    WORLD::msg($World, "Unknonwn option: $key, use /shlistsopts.")
  }
}

# Syntax: /shhelp
# Shows available commands with syntax of this plugin.
sub help_cb {
  my $World = shift;

  WORLD::msg($World, "SHSCRIPTS plugin $VERSION help. This plugin has the following macros (with syntax):");
  WORLD::msg($World, "");
  WORLD::msg($World, "/sh <cmd>\t\t\tRun shell command, output to user.");
  WORLD::msg($World, "/run <cmd>\t\t\tRun shell command, output through emote.");
  WORLD::msg($World, "/crun <chan> <cmd>\t\tRun shell command, output to channel.");
  WORLD::msg($World, "/pstrun <cmd> \t\tRun shell command, output through \@paste.");
  WORLD::msg($World, "/ppstrun <person> <cmd>\tRun shell command, output through \@paste <person>.");
  WORLD::msg($World, "/prefun <prefix> <cmd> \tRun shell command, use prefix <prefix> before each line of output.");
  WORLD::msg($World, "");
  WORLD::msg($World, "/shsetopt <opt> <value>\tSet an shscripts plugin option and save it for other sessions.");
  WORLD::msg($World, "/shlistopts\t\t\tList all available options and their values.");
  WORLD::msg($World, "");
  WORLD::msg($World, "/shhelp\t\t\tShow this list of all available macros and syntax.");
}