\section{cmdlineopt.cpp} \footnotesize\begin{verbatim}1 // Copyright (C) 2001 Gianni Mariani 2 // 3 // This program is free software; you can redistribute it and/or modify 4 // it under the terms of the GNU General Public License as published by 5 // the Free Software Foundation; either version 2 of the License, or 6 // (at your option) any later version. 7 // 8 // This program is distributed in the hope that it will be useful, 9 // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 // GNU General Public License for more details. 12 // 13 // You should have received a copy of the GNU General Public License 14 // along with this program; if not, write to the Free Software 15 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 16 // 17 // As a special exception to the GNU General Public License, permission is 18 // granted for additional uses of the text contained in its release 19 // of Common C++. 20 // 21 // The exception is that, if you link the Common C++ library with other 22 // files to produce an executable, this does not by itself cause the 23 // resulting executable to be covered by the GNU General Public License. 24 // Your use of that executable is in no way restricted on account of 25 // linking the Common C++ library code into it. 26 // 27 // This exception does not however invalidate any other reasons why 28 // the executable file might be covered by the GNU General Public License. 29 // 30 // This exception applies only to the code released under the 31 // name Common C++. If you copy code from other releases into a copy of 32 // Common C++, as the General Public License permits, the exception does 33 // not apply to the code that you add in this way. To avoid misleading 34 // anyone as to the status of such modified files, you must delete 35 // this exception notice from them. 36 // 37 // If you write modifications of your own for Common C++, it is your choice 38 // whether to permit this exception to apply to your modifications. 39 // If you do not wish that, delete this exception notice. 40 // 41 42 43 // 44 // Example for Common C++ the command line parser interface. 45 // 46 // 47 // This exmaple code shows how to use the command line parser provided by 48 // CommonC++. The command line parser provides an interface which is 49 // "object oriented" such that command line parameters are true "objects". 50 // 51 // Each command line option needs to be created. By defining "CommandOption"s 52 // statically, the C++ constructor is called when the objects are loaded and 53 // before the "main" function is called. The constructor links itself to 54 // a list of other CommandOptionXXX in the list provided. If no 55 // list is specified in the constructor, a default one is used. Because of 56 // the undefined nature as to the order in which constructors are called, 57 // no assumption as to the order in which the CommandOptionXXX constructors 58 // are called should be made. 59 // 60 // CommandOptionXXX classes can be used to derive specialized parameter 61 // classes that are specific to applications. The second example shows 62 // just how this can be done. 63 // 64 65 // 66 // Include the CommandOption definitions 67 // 68 #include <cc++/common.h> 69 70 #include <iostream> 71 72 #ifdef CCXX_NAMESPACES 73 using namespace std; 74 using namespace ost; 75 #endif 76 77 // 78 // The following definition of options all use the list header 79 // defaultCommandOptionList (which is specified as the value of the 80 // default parameter in the constructor. This convention would 81 // allow other object files to link into the same list and add parameters 82 // to the command line of this executable. 83 84 CommandOptionArg test_option1( 85 "test_option1", "p", "This option takes an argument", true 86 ); 87 88 CommandOptionNoArg test_noarg( 89 "test_noarg", "b", "This option does not take an argument" 90 ); 91 92 CommandOptionNoArg helparg( 93 "help", "?", "Print help usage" 94 ); 95 96 CommandOptionCollect restoargs( 97 0, 0, "Collect all the parameters", true 98 ); 99 100 101 // 102 // Normally this would me the regular main(). In this example 103 // this processes the first command option list. 104 // 105 int Example_main( int argc, char ** argv ) 106 { 107 108 // Create a CommandOptionParse object. This takes the 109 // defaultCommandOptionList and parses the command line arguments. 110 // 111 CommandOptionParse * args = makeCommandOptionParse( 112 argc, argv, 113 "CommonC++ command like option interface. This is example\n" 114 " code only." 115 ); 116 117 // If the user requested help then suppress all the usage error 118 // messages. 119 if ( helparg.numSet ) { 120 cerr << args->printUsage(); 121 ::exit(0); 122 } 123 124 // Print usage your way. 125 if ( args->argsHaveError() ) { 126 cerr << args->printErrors(); 127 cerr << args->printUsage(); 128 ::exit(1); 129 } 130 131 // Go off and run any option specific task 132 args->performTask(); 133 134 // print all the -p options 135 for ( int i = 0; i < test_option1.numValue; i ++ ) { 136 cerr << "test_option1 = " << test_option1.values[ i ] << endl; 137 } 138 139 // print all the other options. 140 for ( int i = 0; i < restoargs.numValue; i ++ ) { 141 cerr << "restoargs " << i << " : " << restoargs.values[ i ] << endl; 142 } 143 144 delete args; 145 146 return 0; 147 } 148 149 150 // 151 // This shows how to build a second option list. The example is similar to 152 // the first as well as it shows how to derive a new command object. 153 // 154 155 CommandOption * TestList = 0; 156 157 extern CommandOptionRest test_restoargs; 158 159 160 #include <unistd.h> 161 #include <sys/types.h> 162 #include <sys/stat.h> 163 #include <fcntl.h> 164 #include <strstream> 165 #include <errno.h> 166 #include <string.h> 167 #include <stdlib.h> 168 #include <sys/wait.h> 169 170 171 // 172 // This is a parameter class derived from CommandOptionArg that takes 173 // a file name parameter and detects wether the file is accessible 174 // flagging an error if the file is inaccessible to read. 175 // 176 class file_option : public CommandOptionArg { 177 public: 178 179 // the constructor calls the regular CommandOptionArg constructor 180 // and all should be well. 181 file_option( 182 const char * in_option_name, 183 const char * in_option_letter, 184 const char * in_description, 185 bool in_required = false, 186 CommandOption ** pp_next = & defaultCommandOptionList 187 ) 188 : CommandOptionArg( 189 in_option_name, 190 in_option_letter, 191 in_description, 192 in_required, 193 pp_next 194 ) 195 { 196 } 197 198 // 199 // When parsing is done check if the file is accessible and register 200 // an error with the CommandOptionParse object to let it know so. 201 virtual void parseDone( CommandOptionParse * cop ) 202 { 203 if ( numValue ) { 204 if ( ::access( values[ numValue - 1 ], R_OK ) ) { 205 int errno_s = errno; 206 strstream msg; 207 msg << "Error: " << optionName << " '" << values[ numValue - 1 ]; 208 msg << "' : " << ::strerror( errno_s ); 209 210 cop->registerError( msg.str() ); 211 } 212 } 213 } 214 215 // 216 // Open said file. Do some operations on things - like open the file. 217 int OpenFile() 218 { 219 // Should put in way more error handling here ... 220 return ::open( values[ numValue - 1 ], O_RDONLY ); 221 } 222 223 // 224 // The most elaborate way to spit the contents of a file 225 // to standard output. 226 pid_t pid; 227 virtual void performTask( CommandOptionParse * cop ) 228 { 229 pid = ::fork(); 230 231 if ( pid ) { 232 return; 233 } 234 235 int fd = OpenFile(); 236 if ( fd < 0 ) { 237 int errno_s = errno; 238 cerr 239 << "Error: '" 240 << values[ numValue - 1 ] 241 << "' : " 242 << ::strerror( errno_s ) 243 ; 244 245 ::exit( 1 ); 246 } 247 dup2(fd, 0); 248 ::execvp( test_restoargs.values[0], (char**) test_restoargs.values ); 249 ::exit(1); 250 } 251 252 ~file_option() 253 { 254 if ( pid <= 0 ) return; 255 int status; 256 ::wait(&status); 257 } 258 }; 259 260 261 // 262 // This is the linked list head for the options in the second example. 263 // Note that the first example used the default value defined in the 264 // method. Here it is explicitly specified as TestList in all the following 265 // CommandOption constructors. 266 267 file_option test_file( 268 "test_file", "f", "Filename to read from", true, &TestList 269 ); 270 271 CommandOptionNoArg test_xnoarg( 272 "test_xnoarg", "b", "This option does not take an argument", false, &TestList 273 ); 274 275 CommandOptionNoArg test_helparg( 276 "help", "?", "Print help usage", false, &TestList 277 ); 278 279 CommandOptionRest test_restoargs( 280 0, 0, "Command to be executed", true, &TestList 281 ); 282 283 // 284 // in most apps this would be the regular "main" function. 285 int Test_main( int argc, char ** argv ) 286 { 287 CommandOptionParse * args = makeCommandOptionParse( 288 argc, argv, 289 "Command line parser X test.\n" 290 " This example is executed when the command ends in 'x'\n" 291 " It shows how the -f parameter can be specialized.\n", 292 TestList 293 ); 294 295 // If the user requested help then suppress all the usage error 296 // messages. 297 if ( test_helparg.numSet ) { 298 cerr << args->printUsage(); 299 ::exit(0); 300 } 301 302 // Print usage your way. 303 if ( args->argsHaveError() ) { 304 cerr << args->printErrors(); 305 cerr << "Get help by --help\n"; 306 ::exit(1); 307 } 308 309 // Go off and run any option specific task 310 args->performTask(); 311 312 for ( int i = 0; i < test_file.numValue; i ++ ) { 313 cerr << "test_file = " << test_file.values[ i ] << endl; 314 } 315 316 for ( int i = 0; i < test_restoargs.numValue; i ++ ) { 317 cerr << "test_restoargs " << i << " : " << test_restoargs.values[ i ] << endl; 318 } 319 320 delete args; 321 322 return 0; 323 } 324 325 326 // 327 // This switches behaviour of this executable depending of wether it is 328 // invoked with a command ending in "x". This is mimicking for example 329 // the behaviour of bunzip2 and bzip2. These executables are THE SAME 330 // file i.e. 331 // 0 lrwxrwxrwx 1 root root 5 Oct 11 14:04 /usr/bin/bunzip2 -> bzip2* 332 // and the behaviour is determined by the executable name. 333 // 334 // This example is way more complex than the way most people will end up 335 // using feature. 336 337 int main( int argc, char ** argv ) 338 { 339 340 int i = ::strlen( argv[ 0 ] ); 341 342 // determine which real "main" function do I call 343 if ( argv[ 0 ][ i - 1 ] == 'x' ) { 344 return Test_main( argc, argv ); 345 } else { 346 return Example_main( argc, argv ); 347 } 348 349 } \end{verbatim} \normalsize