1.   #!/usr/bin/perl
2.   ######################################
3.   ## Coded by Douglas[at]WeakNetLabs[dot]com
4.   ## Coded by Chartreuse[at]WeakNetLabs[dot]com
5.   #####################################
6.   #  TODO List:  (Add to when new features are wanted with priorities 0-9 where 0 is urgent)
7.   #   + -7- Create configuration file code and store the environment there to be loaded
8.   #   + -6- Create a Help File/Help Page to display for command help
9.   #   + -3- Create more commands and populate them out
10.  #   + -9- Trap Arrow keys and implement functions to do scrollback
11.  #   + -5- Remove system call's in favor of modules -- system calls reduce portability
12.  #
13.  #
14.  #
15.  #
16.  #
17.  #####################################
18.  #  Change Log:
19.  # [18/05/10 Chartreuse] Recoded Trevelyn's original code and added my own
20.  # [19/05/10 Chartreuse] Added in Trevelyn's new code for mysql and such
21.  #                       Made Help function print list of valid commands
22.  #                       Moved parsing user input to it's own function
23.  #                       Added support for command alias's
24.  #
25.  # [19/05/10 Trevelyn] Added Support for Negative Backreferencing in MySQL()
26.  # function.  Fixed token error for parsing /select/,
27.  # /from/, /REGEXP/.  Added quit(); Removed some 
28.  # print.  
29.  ##
30.  use strict;
31.  use warnings;
32. 
33.  #####################################
34.  # Load up Modules
35.  ##
36.  use Cwd;
37.  use Term::ANSIColor;
38.  use File::Spec;
39.  use POSIX;
40.  use Term::Cap;
41. 
42. 
43.  #####################################
44.  # Pre-set Environment variables
45.  ##  TODO: Move to configuration file (.celeritasrc) and load on startup
46.  my $hostname = "celeritas";
47.  my $PS1 = colored (getlogin() . "\@$hostname", "bold green") . colored (" " . getWorkingDirectory() . "%", "bold blue") . " ";
48.  my $version = "0.1.2ALPHA";
49.  my @split_regexp;
50. 
51.  ####################################
52.  # Global Variables  --  Avoid Creating these
53.  ##  TODO: Find other solutions rather than these
54.  my $term;                          # Needed for term::cap
55.  my $termios = new POSIX::Termios;  # Needed for term::cap
56.  my $iAmAlive = 1; # Clean exit flag
57. 
58.  my $db = "";
59.  my $usr = "";
60.  my $col = 0;
61.  my $pass = "";
62. 
63.  my @validCommands = qw /exit echo sys help clear mysql set use show quit/; # List of valid commands that can be symbolically called
64.  my %commandAlias = (   # Hash of alias's, key = alias name, value = command name
65.  "usedb" => "use"
66.         );
67. 
68.  ####################################
69.  ##### ENTRY POINT - Begin Here #####
70.  ####################################
71.  initialSetup();
72.  mainLoop();
73.  cleanUpAndQuit();
74.  ###################################
75.  ######### END ENTRY POINT #########
76.  ###################################
77. 
78. 
79.  ###################################
80.  # Subroutines Here
81.  ##
82.  ### initialSetup() - Preconfigure everything before entering mainLoop()
83.  # TODO: Unknown
84.  sub initialSetup
85.  {
86.  ## Stuff needed for Term::Cap
87. 
88.  # General terminal line I/O
89.  $termios->getattr;
90.  # Extract the entry of the terminal type
91.  $term = Term::Cap->Tgetent( { TERM => undef, OSPEED => $termios->getospeed } );
92. 
93.  return;
94.  }
95.  ### mainLoop() - Program Flow and Logic Here ###
96.  # TODO: Unknown
97.  sub mainLoop
98.  {
99.  my $returnValue=0;
100. while($iAmAlive) ## Logic Loop while we have not been told to exit nicely
101. {
102. printPrompt(); # Show us a prompt
103. parseUserInput();
104.
105. }
106.
107. return;
108. }
109. sub parseUserInput
110. {
111. chomp( my $userCommand = <STDIN> ); # Set $userCommand with user input and clean off any trailing newlines
112. $userCommand =~ /^(\S+)\s?(.*)/; # Return all characters up till first space and everything after first space
113.
114. my $commandName = $1;
115. my $commandArguments = $2;
116.
117. if(!( grep {$_ eq lc($1)} @validCommands))
118. {
119. if( exists $commandAlias{$1} ) # Check if we are dealing with a command alias
120. {
121. no strict 'refs';  # Should we even be doing the symbolic-references in the first place?
122.
123. return &{lc($commandAlias{$1} . "_cmd")}($2);  # Does the postfix protection make this safe enough?
124. }
125. else
126. {
127. print colored("Celeritas:", "bold red") . colored(" $1","bold") . " command not understood\n";
128. return 0;
129. }
130. }
131. else
132. {
133. no strict 'refs';  # Should we even be doing the symbolic-references in the first place?
134. $commandName .= "_cmd";  # Append postfix to entered command and call it
135. return &{lc($commandName)}($2);           # Does the postfix protection make this safe enough?
136. }
137. return 0;
138. }
139. ### printPrompt() - Prints the prompt ($PS1) to STDIN
140. # TODO: Unknown
141. sub printPrompt
142. {
143. print $PS1; # Just print out the prompt string for now
144. return;
145. }
146.
147. ### getWorkingDirectory() - Returns the current working directory without the full path
148. # TODO: Unknown
149. sub getWorkingDirectory
150. {
151. my @dirs = File::Spec->splitdir( Cwd::cwd() ); # Split the Current working path
152. return $dirs[$#dirs];  # Return the last element, (The current directory)
153. }
154.
155. ### cleanUpAndQuit() - Clean up all we've done, prepare to quit, and quit
156. # TODO: Unknown
157. sub cleanUpAndQuit
158. {
159. print "\n";  # Give shell some breathing room before leaving
160. exit(0);
161. }
162.
163. ####################################
164. # Celeritas Commands Below
165. ##  TODO: Populate Commands
166.
167. ### exit_cmd - Command to nicely exit back to the shell
168. # TODO: Unknown
169. sub exit_cmd
170. {
171. print "Now Exiting... See you later :)\n";
172. $iAmAlive = 0;
173.
174. return;
175. }
176. sub quit_cmd
177. {
178. exit_cmd();
179. }
180. ### echo_cmd - Command to echo arguments out to STDOUT
181. # TODO: Possible Input Protection? Required?
182. sub echo_cmd
183. {
184. my ($input) = @_;
185. print "$input\n";
186.
187. return;
188. }
189. ### sys_cmd - Run command through the host shell
190. # TODO: Reimplement Trevelyn's Backref the REGEX code into a subroutine
191. sub sys_cmd
192. {
193. # Trevelyn's Backreference the REGEX Code  
194. my ($input) = @_;
195. my @split;
196. if ($input =~ /\\-[0-9]/) {
197. @split = split(/\)/, $input);
198. foreach (@split) {
199. $_ =~ s/.*\(//g;
200. }
201. }
202. my $n = 0;
203. foreach (@split) {
204. $n++;
205. $input =~ s/\\-$n/\($_\)/g;
206. }
207.
208. system($input); # Run the command
209. return;
210. }
211. ### help_cmd - Display help pages to user
212. # TODO: Create Help Menu
213. sub help_cmd
214. {
215. print "Help\n";
216. print "-----------------\n";
217. print "Valid Commands: \n";
218. print join(" ", @validCommands) . "\n\n";
219.
220. return;
221. }
222. ### clear_cmd - Clears the screen
223. # TODO: Unknown
224. sub clear_cmd
225. {
226. print $term->Tputs('cl');
227. return;
228. }
229. ### mysql_cmd - Run mysql
230. # TODO: Use Modules instead of system command?
231. sub mysql_cmd {
232. my @split_cmd = split(" ", shift);
233. if (@split_cmd)
234. {
235. my ($what,$table,$regexp);
236. my $n = 0;
237. foreach (@split_cmd)
238. { 
239. if ($_ =~ /select/i) { $what = $split_cmd[($n + 1)]; }
240. if ($_ =~ /from/i) { $table = $split_cmd[($n + 1)]; }
241. if ($_ =~ /REGEXP/) { $regexp = $split_cmd[($n + 1)]; }
242. $n++;
243. }
244. ### Addition For "neg backreferencing" function in MySQL!
245. # This is good, because the '\-[0-9]' will be allowed ANYWHERE else in the command!
246. # by simply changing ONLY the regexp text:
247. # TODO: 
248. if ($regexp =~ /\\-[0-9]/) { 
249. @split_regexp = split(/\)/, $regexp);
250. }
251. foreach (@split_regexp) {
252. $_ =~ s/.*\(//g;
253. }
254. $n = 0;
255. foreach (@split_regexp) {
256. $n++;
257. if ($_ !~ /\\-[0-9]/) {
258. $regexp =~ s/\\-$n/\($_\)/g;
259. }
260. }
261. # slurp all results line x line into array @lines:
262. ## SYSTEM COMMAND, perhaps use the MySQL module? ##
263. my @lines = `mysql -t -e \'select $what from $table\' $db --password=$pass --user=$usr`;
264. # get column of target for "where $something regexp..."
265.
266. my $g = 0;
267. print $lines[0] . $lines[1] . $lines[2];
268.
269. foreach( $lines[1] ) 
270. {
271. if ($_ =~ /where/i) 
272. { 
273. $col = ($g + 1); 
274. last();
275. } $g++;
276. }
277.
278. my $t = $#lines;
279. foreach(@lines[3..$t])
280. {
281. my @split_lines = split(/" "/, $_);
282. # Here it is, if it's here, it gets printed:
283. if ($split_lines[$col] =~ /$regexp/) 
284. {
285. chomp $_;
286. print "$_\n";
287. print $lines[0];
288. }
289. }
290. #print "The command was: select " . $what . " from " . " $table " . " where column " . $something . " had a regexp match of " . $regexp . "\n";
291. }
292. return;
293. }
294. ### set_cmd - Set variables for built in commands
295. # TODO: Add more?   Maybe make these like environment variables
296. #                   and use a symbolic reference to store them as
297. #                   varname_env and make them accessable in commands
298. #                   and regex
299. sub set_cmd {
300. my @split_cmd = split(" ", shift);
301. if (@split_cmd)
302. {
303. if ($split_cmd[0] eq 'db' or $split_cmd[0] eq 'database') { 
304. print "Database: ";
305. $db = <STDIN>;
306. chomp $db;
307. return;
308. }
309. if ($split_cmd[0] eq 'pass' or $split_cmd[0] eq 'passwd') { 
310. print "Password: ";
311. system "stty -echo";  ## Use Term::Cap module to remove the need for system call?
312. $pass = <STDIN>;
313. chomp $pass;
314. system "stty echo"; ## Use Term::Cap module to remove the need for system call?
315. print "\n";
316. return;
317. }
318. if ($split_cmd[0] eq 'usr' or $split_cmd[0] eq 'user') { 
319. print "Username: ";
320. $usr = <STDIN>;
321. chomp $usr;
322. return;
323. }else {
324. print "Error: set: " . $split_cmd[0] . " Not yet implemented.\n";
325. return;
326. }
327. }
328. return;
329. }
330. ### use_cmd - Set which database we are using
331. # Alias's: usedb
332. # TODO: Unknown
333. sub use_cmd {
334. my @split_cmd = split(" ", shift);
335. if (@split_cmd)
336. {
337. if ($split_cmd[0] eq '') { 
338. print "Invalid name for database.\n";
339. return 0;
340. }
341. else {
342. $db = $split_cmd[0];
343. print "Database successfully changed to " . $db . "\n";
344. return;
345. }
346. }
347. }
348. ### show_cmd - Show all variables for built in commands
349. # TODO: Same as set_cmd, possibly use an env variables type setup
350. sub show_cmd {
351. my @split_cmd = split(" ", shift);
352. if (@split_cmd)
353. {
354. if ($split_cmd[0] eq 'db' or $split_cmd[0] eq 'database' or $split_cmd[0] eq 'dbase') {
355. print $db . "\n";
356. return;
357. }
358. if ($split_cmd[0] eq 'user' or $split_cmd[0] eq 'usr' or $split_cmd[0] eq 'who') {
359. print $usr . "\n";
360. return;
361. }
362. if ($split_cmd[0] eq 'version' or $split_cmd[0] eq 'v' or $split_cmd[0] eq 'V') { 
363. print $version . "\n";
364. return;
365. }
366. if ($split_cmd[0] eq 'help') { 
367. help();
368. }
369. else { 
370. print "Error: " . $split_cmd[0] . " not yet implemented for command: \"show\"\n";
371. return;
372. }
373. }
374. }
375.

Download the File By Clicking HERE

Coded in PHP