#include <popt.h> "poptContext poptGetContext(const char * " name ", int " argc , " const char ** "argv , " const struct poptOption * " options , " int " flags ); "void poptFreeContext(poptContext " con ); "void poptResetContext(poptContext " con ); "int poptGetNextOpt(poptContext " con ); "const char * poptGetOptArg(poptContext " con ); "const char * poptGetArg(poptContext " con ); "const char * poptPeekArg(poptContext " con ); "const char ** poptGetArgs(poptContext " con ); "const char *const poptStrerror(const int " error ); "const char * poptBadOption(poptContext " con ", int " flags ); "int poptReadDefaultConfig(poptContext " con ", int " flags ); "int poptReadConfigFile(poptContext " con ", char * " fn ); "int poptAddAlias(poptContext " con ", struct poptAlias " alias , " int " flags ); "int poptParseArgvString(char * " s ", int * " argcPtr , " const char *** " argvPtr ); "int poptDupArgv(int " argc ", const char ** " argv ", int * " argcPtr ", " const char *** " argvPtr ");" "int poptStuffArgs(poptContext " con ", const char ** " argv );
struct poptOption { const char * longName; /* may be NULL */ char shortName; /* may be '\\0' */ int argInfo; void * arg; /* depends on argInfo */ int val; /* 0 means don't return, just update flag */ char * descrip; /* description for autohelp -- may be NULL */ char * argDescrip; /* argument description for autohelp */ };Each member of the table defines a single option that may be passed to the program. Long and short options are considered a single option that may occur in two different forms. The first two members, longName " and " shortName ", define the names of the option;" the first is a long name, while the latter is a single character. The argInfo " member tells popt what type of argument is expected" after the option. If no argument is expected, POPT_ARG_NONE should be used. The rest of the valid values are shown in the following table:
Value Description arg Type |
POPT_ARG_NONE No argument expected int |
POPT_ARG_STRING No type checking to be performed char * |
POPT_ARG_ARGV No type checking to be performed char ** |
POPT_ARG_SHORT An short argument is expected short |
POPT_ARG_INT An integer argument is expected int |
POPT_ARG_LONG A long integer is expected long |
POPT_ARG_LONGLONG A long long integer is expected long long |
POPT_ARG_VAL Integer value taken from val int |
POPT_ARG_FLOAT An float argument is expected float |
POPT_ARG_DOUBLE A double argument is expected double |
"void poptCallbackType(poptContext con, " const struct poptOption * opt, " const char * arg, void * data);The first parameter is the context which is being parsed (see the next section for information on contexts), opt points to the option which triggered this callback, and arg is the option's argument. If the option does not take an argument, arg is NULL. The final parameter, data is taken from the descrip field of the option table entry which defined the callback. As descrip is a pointer, this allows callback functions to be passed an arbitrary set of data (though a typecast will have to be used). The option table entry which defines a callback has an argInfo of POPT_ARG_CALLBACK, an arg which points to the callback function, and a descrip field which specifies an arbitrary pointer to be passed to the callback.
"poptContext poptGetContext(const char * " name ", int "argc ", " const char ** "argv ", " const struct poptOption * "options ", " int "flags ");"The first parameter, name ", is used only for alias handling (discussed later). It " should be the name of the application whose options are being parsed, "or should be " NULL " if no option aliasing is desired. The next " two arguments specify the command-line arguments to parse. These are "generally passed to " poptGetContext() " exactly as they were " "passed to the program's " main() " function. The " options " parameter points to the table of command-line options, " which was described in the previous section. The final parameter, flags , can take one of three values:
Value Description |
POPT_CONTEXT_NO_EXEC Ignore exec expansions |
POPT_CONTEXT_KEEP_FIRST Do not ignore argv[0] |
POPT_CONTEXT_POSIXMEHARDER Options cannot follow arguments |
#include <popt.h> "void poptFreeContext(poptContext " con ");" "void poptResetContext(poptContext " con ");"
#include <popt.h> "int poptGetNextOpt(poptContext " con ");"Taking the context as its sole argument, this function parses the next command-line argument found. After finding the next argument in the option table, the function fills in the object pointed to by the option "table entry's " arg "pointer if it is not " NULL ". If the val entry for the option is " non-0, the function then returns that value. Otherwise, poptGetNextOpt() " continues on to the next argument." poptGetNextOpt() " returns -1 when the final argument has been " parsed, and other negative values when errors occur. This makes it a good idea to "keep the " val " elements in the options table greater than 0." "If all of the command-line options are handled through " arg pointers, command-line parsing is reduced to the following line of code:
rc = poptGetNextOpt(poptcon);Many applications require more complex command-line parsing than this, however, and use the following structure:
while ((rc = poptGetNextOpt(poptcon)) > 0) { switch (rc) { /* specific arguments are handled here */ } }When returned options are handled, the application needs to know the value of any arguments that were specified after the option. There are two ways to discover them. One is to ask popt to fill in a variable with the "value of the option through the option table's " arg " elements. The " "other is to use " poptGetOptArg() ":"
#include <popt.h> "char * poptGetOptArg(poptContext " con ");"This function returns the argument given for the final option returned by poptGetNextOpt() ", or it returns " NULL " if no argument was specified." The calling function is responsible for deallocating this string.
This function returns the next leftover argument and marks it as processed."const char * poptGetArg(poptContext " con ");"
The next leftover argument is returned but not marked as processed. This allows an application to look ahead into the argument list, without modifying the list."const char * poptPeekArg(poptContext " con ");"
All the leftover arguments are returned in a manner identical to argv ". The final element in the returned array points to " NULL ", indicating the end of the arguments."const char ** poptGetArgs(poptContext " con ");"
#include <popt.h> "void poptPrintHelp(poptContext " con ", FILE * " f ", int " flags "); "void poptPrintUsage(poptContext " con ", FILE * " f ", int " flags ");poptPrintHelp() displays the standard help message to the stdio file descriptor f, while poptPrintUsage() displays the shorter usage message. Both functions currently ignore the flags argument; it is there to allow future changes.
" Error Description" "POPT_ERROR_NOARG " "Argument missing for an option." "POPT_ERROR_BADOPT " "Option's argument couldn't be parsed." "POPT_ERROR_OPTSTOODEEP " "Option aliasing nested too deeply." "POPT_ERROR_BADQUOTE " "Quotations do not match." "POPT_ERROR_BADNUMBER " "Option couldn't be converted to number." "POPT_ERROR_OVERFLOW " "A given number was too big or small."Here is a more detailed discussion of each error:
POPT_ERROR_NOARG An option that requires an argument was specified on the command line, but no argument was given. This can be returned only by poptGetNextOpt() .
POPT_ERROR_BADOPT "An option was specified in " argv " but is not in the option "table. This error can be returned only from " poptGetNextOpt() .
POPT_ERROR_OPTSTOODEEP A set of option aliases is nested too deeply. Currently, popt follows options only 10 levels to prevent infinite recursion. Only poptGetNextOpt() " can return this error."
POPT_ERROR_BADQUOTE A parsed string has a quotation mismatch (such as a single quotation "mark). " poptParseArgvString() ", " poptReadConfigFile() ", or " poptReadDefaultConfig() " can return this error."
POPT_ERROR_BADNUMBER A conversion from a string to a number (int or long) failed due to the string containing non-numeric characters. This occurs when poptGetNextOpt() " is processing an argument of type " POPT_ARG_INT ", " POPT_ARG_SHORT ", " POPT_ARG_LONG ", " POPT_ARG_LONGLONG ", " POPT_ARG_FLOAT ", or " POPT_ARG_DOUBLE "."
POPT_ERROR_OVERFLOW A string-to-number conversion failed because the number was too "large or too small. Like " POPT_ERROR_BADNUMBER ", this error "can occur only when " poptGetNextOpt() " is processing an " "argument of type " POPT_ARG_INT ", " POPT_ARG_SHORT ", " POPT_ARG_LONG ", " POPT_ARG_LONGLONG ", " POPT_ARG_FLOAT ", or " POPT_ARG_DOUBLE "."
POPT_ERROR_ERRNO "A system call returned with an error, and " errno " still contains the error from the system call. Both poptReadConfigFile() " and " poptReadDefaultConfig() " can " return this error.
Two functions are available to make it easy for applications to provide good error messages.
"const char *const poptStrerror(const int " error ");"
This function takes a popt error code and returns a string describing
"the error, just as with the standard " strerror() " function."
"const char * poptBadOption(poptContext " con ", int " flags ");"
"If an error occurred during " poptGetNextOpt() ", this function " "returns the option that caused the error. If the " flags " argument" "is set to " POPT_BADOPTION_NOALIAS ", the outermost option is " "returned. Otherwise, " flags " should be 0, and the option that is " returned may have been specified through an alias.
These two functions make popt error handling trivial for most applications. When an error is detected from most of the functions, an error message is printed along with the error string from poptStrerror() ". When an error occurs during argument parsing, " code similar to the following displays a useful error message:
fprintf(stderr, "%s: %s\\n", poptBadOption(optCon, POPT_BADOPTION_NOALIAS), poptStrerror(rc));
"int poptReadDefaultConfig(poptContext " con ", int " flags ");"
"This function reads aliases from " /etc/popt " and the " .popt " file in the user's home directory. Currently, " flags " should be " NULL ", as it is provided only for future expansion."
"int poptReadConfigFile(poptContext " con ", char * " fn ");"
"The file specified by " fn " is opened and parsed as a popt " configuration file. This allows programs to use program-specific
configuration files.
"int poptAddAlias(poptContext " con ", struct poptAlias " alias ", " int " flags ");"Occasionally, processes want to specify aliases without having to read them from a configuration file. This function adds a new alias "to a context. The " flags " argument should be 0, as it is " currently reserved for future expansion. The new alias is specified "as a " "struct poptAlias" ", which is defined as:"
struct poptAlias { const char * longName; /* may be NULL */ char shortName; /* may be '\\0' */ int argc; const char ** argv; /* must be free()able */ };"The first two elements, " longName " and " shortName ", specify " "the option that is aliased. The final two, " argc " and " argv "," define the expansion to use when the aliases option is encountered.
"#include <popt.h>" "int poptParseArgvString(char * " s ", int * " argcPtr ", " char *** " argvPtr ");" "int poptDupArgv(int " argc ", const char ** " argv ", int * " argcPtr ", " const char *** " argvPtr ");""The string s is parsed into an " argv "-style array. The integer " "pointed to by the " argcPtr " parameter contains the number of elements " "parsed, and the final " argvPtr " parameter contains the address of the" newly created array. "The routine " poptDupArgv() " can be used to make a copy of an existing " argument array. "The " argvPtr "created by " poptParseArgvString() " or " poptDupArgv() " is suitable to pass directly " "to " poptGetContext() . Both routines return a single dynamically allocated contiguous "block of storage and should be " free() "ed when the application is" finished with the storage.
"#include <popt.h>" "int poptStuffArgs(poptContext "con ", const char ** " argv ");""The passed " argv "must have a " NULL " pointer as its final element. When " poptGetNextOpt() " is next called, the " "stuffed" arguments are the first to be parsed. popt returns to the normal arguments once all the stuffed arguments have been exhausted.
#include <popt.h> #include <stdio.h> void usage(poptContext optCon, int exitcode, char *error, char *addl) { poptPrintUsage(optCon, stderr, 0); if (error) fprintf(stderr, "%s: %s\n", error, addl); exit(exitcode); } int main(int argc, char *argv[]) { char c; /* used for argument parsing */ int i = 0; /* used for tracking options */ char *portname; int speed = 0; /* used in argument parsing to set speed */ int raw = 0; /* raw mode? */ int j; char buf[BUFSIZ+1]; poptContext optCon; /* context for parsing command-line options */ struct poptOption optionsTable[] = { { "bps", 'b', POPT_ARG_INT, &speed, 0, "signaling rate in bits-per-second", "BPS" }, { "crnl", 'c', 0, 0, 'c', "expand cr characters to cr/lf sequences", NULL }, { "hwflow", 'h', 0, 0, 'h', "use hardware (RTS/CTS) flow control", NULL }, { "noflow", 'n', 0, 0, 'n', "use no flow control", NULL }, { "raw", 'r', 0, &raw, 0, "don't perform any character conversions", NULL }, { "swflow", 's', 0, 0, 's', "use software (XON/XOF) flow control", NULL } , POPT_AUTOHELP { NULL, 0, 0, NULL, 0 } }; optCon = poptGetContext(NULL, argc, argv, optionsTable, 0); poptSetOtherOptionHelp(optCon, "[OPTIONS]* <port>"); if (argc < 2) { poptPrintUsage(optCon, stderr, 0); exit(1); } /* Now do options processing, get portname */ while ((c = poptGetNextOpt(optCon)) >= 0) { switch (c) { case 'c': buf[i++] = 'c'; break; case 'h': buf[i++] = 'h'; break; case 's': buf[i++] = 's'; break; case 'n': buf[i++] = 'n'; break; } } portname = poptGetArg(optCon); if((portname == NULL) || !(poptPeekArg(optCon) == NULL)) usage(optCon, 1, "Specify a single port", ".e.g., /dev/cua0"); if (c < -1) { /* an error occurred during option processing */ fprintf(stderr, "%s: %s\\n", poptBadOption(optCon, POPT_BADOPTION_NOALIAS), poptStrerror(c)); return 1; } /* Print out options, portname chosen */ printf("Options chosen: "); for(j = 0; j < i ; j++) printf("-%c ", buf[j]); if(raw) printf("-r "); if(speed) printf("-b %d ", speed); printf("\\nPortname chosen: %s\\n", portname); poptFreeContext(optCon); exit(0); }RPM, a popular Linux package management program, makes heavy use of popt's features. Many of its command-line arguments are implemented through popt aliases, which makes RPM an excellent example of how to take advantage of the popt library. For more information on RPM, see http://www.rpm.org. The popt source code distribution includes test program(s) which use all of the features of the popt libraries in various ways. If a feature isn't working for you, the popt test code is the first place to look.
This man page is derived in part from "Linux Application Development" by Michael K. Johnson and Erik W. Troan, Copyright (c) 1998 by Addison Wesley Longman, Inc., and included in the popt documentation with the permission of the Publisher and the appreciation of the Authors.
Thanks to Robert Lynch for his extensive work on this man page.