Getting Parameters from the Command Line

lim it ed t o use in sit uat ions where youre t he only user on t he m achine or you t rust all ot her users. The rest of t his sect ion shows how t o process com m and- line argum ent s t o get connect ion param et ers, and how t o read param et ers from opt ion files.

2.11.4 Getting Parameters from the Command Line

The usual MySQL convent ion for com m and- line argum ent s t hat is, t he convent ion followed by st andard MySQL client s such as m ysql is t o allow param et ers t o be specified using eit her a short opt ion or a long opt ion. For exam ple, t he usernam e cbuser can be specified eit her as - u cbuser or - u cbuser or - - user =cbuser . I n addit ion, for t he opt ions t hat specify t he password -p or - - password , t he password value m ay be om it t ed aft er t he opt ion nam e t o indicat e t hat t he program should prom pt for t he password int eract ively. The next set of exam ple program s shows how t o process com m and argum ent s t o obt ain t he host nam e, usernam e, and password. The st andard flags for t hese are - h or - - host , - u or - - user, and - p or - - password. You can writ e your own code t o it erat e t hrough t he argum ent list , but in general, it s m uch easier t o use exist ing opt ion- processing m odules writ t en for t hat purpose. The program s present ed here are im plem ent ed using a getopt - st yle funct ion for each API , wit h t he except ion of PHP. I nsofar as possible, t he exam ples m im ic t he behavior of t he st andard MySQL client s. No exam ple program is provided for PHP, because few PHP script s are writ t en for use from t he com m and line. 2 .1 1 .4 .1 Pe r l Perl passes com m and- line argum ent s t o script s in t he ARGV array, which can be processed using t he GetOptions funct ion of t he Get opt : : Long m odule. The following program shows how t o parse t he com m and argum ent s for connect ion param et ers. I f a password opt ion is specified wit h no following argum ent , t he script prom pt s t he user for t he password value. usrbinperl -w cmdline.pl - demonstrate command-line option parsing in Perl use strict; use DBI; use Getopt::Long; Getopt::Long::ignorecase = 0; options are case sensitive Getopt::Long::bundling = 1; allow short options to be bundled connection parameters - all missing undef by default my host_name, password, user_name; GetOptions =s means a string argument is required after the option :s means a string argument is optional after the option host|h=s = \host_name, password|p:s = \password, user|u=s = \user_name or exit 1; no error message needed; GetOptions prints its own solicit password if option specified without option value if defined password password eq { turn off echoing but dont interfere with STDIN open TTY, devtty or die Cannot open terminal\n; system stty -echo devtty; print STDERR Enter password: ; chomp password = TTY; system stty echo devtty; close TTY; print STDERR \n; } construct data source name my dsn = DBI:mysql:database=cookbook; dsn .= ;host=host_name if defined host_name; connect to server my dbh = DBI-connect dsn, user_name, password, {PrintError = 0, RaiseError = 1}; print Connected\n; dbh-disconnect ; print Disconnected\n; exit 0; The argum ent s t o GetOptions are pairs of opt ion specifiers and references t o t he script variables int o which opt ion values should be placed. An opt ion specifier list s bot h t he long and short form s of t he opt ion wit hout leading dashes , followed by =s if t he opt ion requires a following argum ent or :s if it m ay be followed by an argum ent . For exam ple, host|h=s allows bot h - - host and - h and indicat es t hat a st ring argum ent is required following t he opt ion. You need not pass t he ARGV array because GetOptions uses it im plicit ly. When GetOptions ret urns, ARGV cont ains any rem aining argum ent s following t he last opt ion. The Get opt : : Long m odules bundling variable affect s t he int erpret at ion of argum ent s t hat begin wit h a single dash, such as - u. Norm ally, wed like t o accept bot h - u cbuser and - u cbuser as t he sam e t hing, because t hat s how t he st andard MySQL client s act . However, if bundling is zero t he default value , GetOptions int erpret s - u cbuser as a single opt ion nam ed ucbuser . By set t ing bundling t o nonzero, GetOptions underst ands bot h - u cbuser and -u cbuser t he sam e way. This happens because it int erpret s an opt ion beginning wit h a single dash charact er by charact er, on t he basis t hat several single- charact er opt ions m ay be bundled t oget her. For exam ple, when it sees - u cbuser , it looks at t he u, t hen checks whet her or not t he opt ion t akes a following argum ent . I f not , t he next charact er is int erpret ed as anot her opt ion let t er. Ot herwise, t he rest of t he st ring is t aken as t he opt ions value. For - u cbuser , u does t ake an argum ent , so GetOptions int erpret s cbuser as t he opt ion value. One problem w it h GetOptions is t hat it doesnt support -p wit hout a password t he sam e w ay as t he st andard MySQL client program s. I f -p is followed by anot her opt ion, GetOptions correct ly det erm ines t hat t here is no password value present . But if - p is followed by a non- opt ion argum ent , it m isint erpret s t hat argum ent as t he password. The result is t hat t hese t wo invocat ions of cm dline.pl are not quit e equivalent : cmdline.pl -h localhost -p -u cbuser xyz Enter password: cmdline.pl -h localhost -u cbuser -p xyz DBI-connectdatabase=cookbook;host=localhost failed: Access denied for user: cbuserlocalhost Using password: YES at .cmdline.pl line 40 For t he first com m and, GetOptions det erm ines t hat no password is present and t he script prom pt s for one. I n t he second com m and, GetOptions has t aken xyz as t he password value. A second problem wit h cm dline.pl is t hat t he password- prom pt ing code is Unix specific and doesnt work under Windows. You could t ry using Term : : ReadKey, which is a st andard Perl m odule, but it doesnt w ork under Windows, eit her. I f you have a good password prom pt er for Windows, you m ight consider sending it t o m e for inclusion in t he recipes dist ribut ion. 2 .1 1 .4 .2 PH P PHP provides lit t le support for opt ion processing from t he com m and line because it is used predom inant ly in a web environm ent where com m and- line argum ent s are not widely used. Hence, I m providing no getopt - st yle exam ple for PHP. I f you w ant t o go ahead and w rit e your own argum ent processing rout ine, use t he argv array cont aining t he argum ent s and t he argc variable indicat ing t he num ber of argum ent s. argv[0] is t he program nam e, and argv[1] t o argv[argc-1] are t he following argum ent s. The following code illust rat es how t o access t hese variables: print Number of arguments: argc\n; print Program name: argv[0]\n; print Arguments following program name:\n; if argc == 1 print None\n; else { for i = 1; i argc; i++ print i: argv[i]\n; } 2 .1 1 .4 .3 Pyt h on Pyt hon passes com m and argum ent s t o script s as a list in t he sys.argv variable. You can access t his variable by im port ing t he sys m odule, t hen process it s cont ent s wit h getopt if you also im port t he getopt m odule. The following program illust rat es how t o get param et ers from t he com m and argum ent s and use t hem for est ablishing a connect ion t o t he server: usrbinpython cmdline.py - demonstrate command-line option parsing in Python import sys import getopt import MySQLdb try: opts, args = getopt.getopt sys.argv[1:], h:p:u:, [ host=, password=, user= ] except getopt.error, e: print program name and text of error message print s: s sys.argv[0], e sys.exit 1 default connection parameter values host_name = password = user_name = iterate through options, extracting whatever values are present for opt, arg in opts: if opt in -h, --host: host_name = arg elif opt in -p, --password: password = arg elif opt in -u, --user: user_name = arg try: conn = MySQLdb.connect db = cookbook, host = host_name, user = user_name, passwd = password print Connected except MySQLdb.Error, e: print Cannot connect to server print Error:, e.args[1] print Code:, e.args[0] sys.exit 1 conn.close print Disconnected sys.exit 0 getopt t akes eit her t wo or t hree argum ent s: • A list of com m and argum ent s. This should not include t he program nam e, sys.argv[0] . You can use sys.argv[1:] t o refer t o t he list of argum ent s t hat follow t he program nam e. • A st ring nam ing t he short opt ion let t ers. Any of t hese m ay be followed by a colon charact er : t o indicat e t hat t he opt ion requires a following argum ent t hat specifies t he opt ions value. • An opt ional list of long opt ion nam es. Each nam e m ay be followed by = t o indicat e t hat t he opt ion requires a following argum ent . getopt ret urns t wo values. The first is a list of opt ion value pairs, and t he second is a list of any rem aining argum ent s following t he last opt ion. cm dline.py it erat es t hrough t he opt ion list t o det erm ine which opt ions are present and what t heir values are. Not e t hat alt hough you do not specify leading dashes in t he opt ion nam es passed t o getopt , t he nam es ret urned from t hat funct ion do include leading dashes. cm dline.py doesnt prom pt for a m issing password, because t he getopt m odule doesnt provide any way t o specify t hat an opt ions argum ent is opt ional. Unfort unat ely, t his m eans t he -p and - - password argum ent s cannot be specified wit hout a password value. 2 .1 1 .4 .4 Ja va Java passes com m and- line argum ent s t o program s in t he array t hat you nam e in t he main declarat ion. The following declarat ion uses args for t hat array: public static void main String[ ] args A Getopt class for parsing argum ent s in Java is available at ht t p: www.urbanophile.com arenn coding download.ht m l I nst all t his class som ewhere and m ake sure it s inst allat ion direct ory is nam ed in t he value of your CLASSPATH environm ent variable. Then you can use Getopt as shown in t he following exam ple program : Cmdline.java - demonstrate command-line option parsing in Java import java.io.; import java.sql.; import gnu.getopt.; need this for the Getopt class public class Cmdline { public static void main String[ ] args { Connection conn = null; String url = null; String hostName = null; String password = null; String userName = null; boolean promptForPassword = false; LongOpt[ ] longOpt = new LongOpt[3]; int c; longOpt[0] = new LongOpt host, LongOpt.REQUIRED_ARGUMENT, null, h; longOpt[1] = new LongOpt password, LongOpt.OPTIONAL_ARGUMENT, null, p; longOpt[2] = new LongOpt user, LongOpt.REQUIRED_ARGUMENT, null, u; instantiate option-processing object, then loop until there are no more options Getopt g = new Getopt Cmdline, args, h:p::u:, longOpt; while c = g.getopt = -1 { switch c { case h: hostName = g.getOptarg ; break; case p: if password option was given with no following value, need to prompt for the password password = g.getOptarg ; if password == null promptForPassword = true; break; case u: userName = g.getOptarg ; break; case :: a required argument is missing case ?: some other error occurred no error message needed; getopt prints its own System.exit 1; } } if password == null promptForPassword { try { DataInputStream s = new DataInputStream System.in; System.err.print Enter password: ; really should turn off character echoing here... password = s.readLine ; } catch Exception e { System.err.println Error reading password; System.exit 1; } } try { construct URL, noting whether or not hostName was given; if not, MySQL will assume localhost if hostName == null hostName = ; url = jdbc:mysql: + hostName + cookbook; Class.forName com.mysql.jdbc.Driver.newInstance ; conn = DriverManager.getConnection url, userName, password; System.out.println Connected; } catch Exception e { System.err.println Cannot connect to server; } finally { if conn = null { try { conn.close ; System.out.println Disconnected; } catch Exception e { } } } } } As t he exam ple program dem onst rat es, you prepare t o parse argum ent s by inst ant iat ing a new Getopt obj ect t o which you pass t he program s argum ent s and inform at ion describing t he opt ions t he program allows. Then you call getopt in a loop unt il it ret urns - 1 t o indicat e t hat no m ore opt ions are present . Each t im e t hrough t he loop, getopt ret urns a value indicat ing which opt ion it s seen, and getOptarg m ay be called t o obt ain t he opt ions argum ent , if necessary. getOptarg ret urns null if no following argum ent was provided. When you creat e an inst ance of t he Getopt class, pass it eit her t hree or four argum ent s: • The program nam e; t his is used for error m essages. • The argum ent array nam ed in your main declarat ion. • A st ring list ing t he short opt ion let t ers wit hout leading dashes . Any of t hese m ay be followed by a colon : t o indicat e t hat t he opt ion requires a following argum ent , or by a double colon :: t o indicat e t hat a following argum ent is opt ional. • An opt ional array t hat cont ains long opt ion inform at ion. To specify long opt ions, you m ust set up an array of LongOpt obj ect s. Each of t hese describes a single opt ion, using four param et ers: o The opt ion nam e as a st ring wit hout leading dashes . o A value indicat ing whet her t he opt ion t akes a following argum ent . This value m ay be LongOpt.NO_ARGUMENT , LongOpt.REQUIRED_ARGUMENT , or LongOpt.OPTIONAL_ARGUMENT . o A StringBuffer obj ect or null . getopt det erm ines how t o use t his value based on t he fourt h param et er of t he LongOpt obj ect . o A value t o be used when t he opt ion is encount ered. This value becom es t he ret urn value of getopt if t he StringBuffer obj ect nam ed in t he t hird param et er is null . I f t he buffer is non- null , getopt ret urns zero aft er placing a st ring represent at ion of t he fourt h param et er int o t he buffer. The exam ple program uses null as t he StringBuffer param et er for each long opt ion obj ect and t he corresponding short opt ion let t er as t he fourt h param et er. This is an easy way t o cause getopt t o ret urn t he short opt ion let t er for bot h t he short and long opt ions, so t hat you can handle t hem wit h t he sam e case st at em ent . Aft er getopt ret urns - 1 t o indicat e t hat no m ore opt ions were found in t he argum ent array, getOptind ret urns t he index of t he first argum ent following t he last opt ion. The following code fragm ent shows one way t o access t he rem aining argum ent s: for int i = g.getOptind ; i args.length; i++ System.out.println args[i]; The Getopt class offers ot her opt ion-processing behavior in addit ion t o what I ve described here. Read t he docum ent at ion included wit h t he class for m ore inform at ion. One deficiency of Cm dline.j ava t hat you m ay want t o address is t hat it doesnt disable charact er echoing while it s reading t he password.

2.11.5 Getting Parameters from Option Files