bincimap

Log | Files | Refs | LICENSE

commit 77cf6b84663beaea00cfebf6698aeac799658289
parent 92c1c57ea1328691373b335c28ca282461a5e8c3
Author: andreaha <andreaha@b31fe1f4-c0d1-0310-8000-a34f4ae90293>
Date:   Tue, 10 Feb 2004 22:16:32 +0000

- Removed template based command line parser.
- Added a much smaller and simpler command line parser.


git-svn-id: file:///home/cwright/convert/bincimap/trunk@36 b31fe1f4-c0d1-0310-8000-a34f4ae90293

Diffstat:
Msrc/Makefile.am | 4++--
Dsrc/arg-arg.cc | 93-------------------------------------------------------------------------------
Dsrc/arg-arg.h | 205-------------------------------------------------------------------------------
Dsrc/arg-checkers.h | 129-------------------------------------------------------------------------------
Dsrc/arg-error.cc | 70----------------------------------------------------------------------
Dsrc/arg-error.h | 73-------------------------------------------------------------------------
Dsrc/arg-parser.cc | 208-------------------------------------------------------------------------------
Dsrc/arg-parser.h | 149-------------------------------------------------------------------------------
Asrc/argparser.cc | 338+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/argparser.h | 89+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/session-initialize-bincimap-up.cc | 1-
Msrc/session-initialize-bincimapd.cc | 1-
Msrc/session.cc | 150+++++++++++++++++++++++++++++++++++--------------------------------------------
Msrc/session.h | 3+--
14 files changed, 496 insertions(+), 1017 deletions(-)

diff --git a/src/Makefile.am b/src/Makefile.am @@ -12,10 +12,10 @@ bin_PROGRAMS = bincimapd bincimap-up #-------------------------------------------------------------------------- -bincimapd_SOURCES = address.cc address.h arg-arg.cc arg-arg.h arg-checkers.h arg-error.cc arg-error.h arg-parser.cc arg-parser.h authenticate.cc base64.cc base64.h bincimapd.cc broker.cc broker.h convert.cc convert.h depot.h depot.cc imapparser.cc imapparser.h io.cc io.h mailbox.cc mailbox.h maildir.cc maildir-close.cc maildir-create.cc maildir-delete.cc maildir-expunge.cc maildir.h maildir-readcache.cc maildir-scan.cc maildir-scanfilesnames.cc maildir-select.cc maildir-updateflags.cc maildir-writecache.cc message.h maildirmessage.cc maildirmessage.h bincimapd-module.cc bincimapd-module.h mime.cc mime-getpart.cc mime.h mime-parsefull.cc mime-parseonlyheader.cc mime-printbody.cc mime-printdoc.cc mime-printheader.cc mime-utils.h operators.h operator-authenticate.cc operator-capability.cc operator-noop.cc operator-noop-pending.cc operator-login.cc operator-logout.cc operators.h operator-append.cc operator-examine.cc operator-select.cc operator-create.cc operator-delete.cc operator-list.cc operator-lsub.cc operator-rename.cc operator-status.cc operator-subscribe.cc operator-unsubscribe.cc operators.h operator-check.cc operator-close.cc operator-copy.cc operator-expunge.cc operator-fetch.cc operator-search.cc operator-store.cc pendingupdates.cc pendingupdates.h recursivedescent.cc recursivedescent.h regmatch.cc regmatch.h session.h session.cc session-initialize-bincimapd.cc status.cc status.h storage.cc storage.h tools.cc tools.h +bincimapd_SOURCES = address.cc address.h argparser.cc argparser.h authenticate.cc base64.cc base64.h bincimapd.cc broker.cc broker.h convert.cc convert.h depot.h depot.cc imapparser.cc imapparser.h io.cc io.h mailbox.cc mailbox.h maildir.cc maildir-close.cc maildir-create.cc maildir-delete.cc maildir-expunge.cc maildir.h maildir-readcache.cc maildir-scan.cc maildir-scanfilesnames.cc maildir-select.cc maildir-updateflags.cc maildir-writecache.cc message.h maildirmessage.cc maildirmessage.h bincimapd-module.cc bincimapd-module.h mime.cc mime-getpart.cc mime.h mime-parsefull.cc mime-parseonlyheader.cc mime-printbody.cc mime-printdoc.cc mime-printheader.cc mime-utils.h operators.h operator-authenticate.cc operator-capability.cc operator-noop.cc operator-noop-pending.cc operator-login.cc operator-logout.cc operators.h operator-append.cc operator-examine.cc operator-select.cc operator-create.cc operator-delete.cc operator-list.cc operator-lsub.cc operator-rename.cc operator-status.cc operator-subscribe.cc operator-unsubscribe.cc operators.h operator-check.cc operator-close.cc operator-copy.cc operator-expunge.cc operator-fetch.cc operator-search.cc operator-store.cc pendingupdates.cc pendingupdates.h recursivedescent.cc recursivedescent.h regmatch.cc regmatch.h session.h session.cc session-initialize-bincimapd.cc status.cc status.h storage.cc storage.h tools.cc tools.h #-------------------------------------------------------------------------- -bincimap_up_SOURCES = arg-arg.cc arg-arg.h arg-checkers.h arg-error.cc arg-error.h arg-parser.cc arg-parser.h authenticate.cc authenticate.h base64.cc base64.h bincimap-up.cc broker.cc broker.h convert.cc convert.h greeting.cc imapparser.cc imapparser.h io.cc io.h io-ssl.cc io-ssl.h operators.h operator-authenticate.cc operator-capability.cc operator-noop.cc operator-login.cc operator-logout.cc operator-starttls.cc recursivedescent.cc recursivedescent.h session.h session.cc session-initialize-bincimap-up.cc status.cc status.h storage.cc storage.h tools.cc tools.h +bincimap_up_SOURCES = argparser.cc argparser.h authenticate.cc authenticate.h base64.cc base64.h bincimap-up.cc broker.cc broker.h convert.cc convert.h greeting.cc imapparser.cc imapparser.h io.cc io.h io-ssl.cc io-ssl.h operators.h operator-authenticate.cc operator-capability.cc operator-noop.cc operator-login.cc operator-logout.cc operator-starttls.cc recursivedescent.cc recursivedescent.h session.h session.cc session-initialize-bincimap-up.cc status.cc status.h storage.cc storage.h tools.cc tools.h #-------------------------------------------------------------------------- bincimap_up_LDADD = @LIBSSL@ @LIBDL@ diff --git a/src/arg-arg.cc b/src/arg-arg.cc @@ -1,93 +0,0 @@ -/* -*- Mode: c++; -*- */ -/* -------------------------------------------------------------------- - * Filename: - * arg-arg.cc - * - * Description: - * Implementation of standard command line types - * - * Authors: - * Eivind Kvedalen <argparser@eivind.kvedalen.name> - * - * Bugs: - * - * ChangeLog: - * - * -------------------------------------------------------------------- - * Copyright 2003 Eivind Kvedalen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. - * -------------------------------------------------------------------- - */ - -#include "arg-arg.h" -#include <stdlib.h> - -using namespace ArgParser; -using namespace std; - -void ArgParser::setValue(const string &name, int &value, const char * a, ArgumentError & error) -{ - if (a != NULL) { - char * end; - value = strtol(a, &end, 10); - if (*end != '\0') error = ArgumentError(ArgumentError::INVALID, name); - // cout << "int argument " << "name" << " = " << value << endl; - } - else - error = ArgumentError(ArgumentError::MISSING, name); -} - -void ArgParser::setValue(const string &name, float &value, const char * a, ArgumentError & error) -{ - if (a != NULL) { - char * end; - value = strtod(a, &end); - if (*end != '\0') error = ArgumentError(ArgumentError::INVALID, name); - // cout << "float argument " << name << " = " << value << endl; - } - else - error = ArgumentError(ArgumentError::MISSING, name); -} - -void ArgParser::setValue(const string &name, string &value, const char * a, ArgumentError & error) -{ - if (a != NULL) { - value = a; - // cout << "string argument " << name << " = " << value << endl; - } - else - error = ArgumentError(ArgumentError::MISSING, name); -} - -string ArgT<bool>::getParam(void) const -{ - return ""; -} - -string ArgT<int>::getParam(void) const -{ - return "=integer[" + Binc::toString(valueRef) + "]"; -} - -string ArgT<float>::getParam(void) const -{ - return "=number"; -} - -string ArgT<string>::getParam(void) const -{ - return "=string[" + valueRef + "]"; -} diff --git a/src/arg-arg.h b/src/arg-arg.h @@ -1,205 +0,0 @@ -/* -*- Mode: c++; -*- */ -/* -------------------------------------------------------------------- - * Filename: - * arg-arg.h - * - * Description: - * Class encapsulating one argument - * - * Authors: - * Eivind Kvedalen <argparser@eivind.kvedalen.name> - * - * Bugs: - * - * ChangeLog: - * - * -------------------------------------------------------------------- - * Copyright 2003 Eivind Kvedalen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. - * -------------------------------------------------------------------- - */ - -#ifndef _ARG_ARG_H -#define _ARG_ARG_H - -#include "arg-error.h" -#include "arg-checkers.h" -#include <string> -#include <vector> -#include <map> -#include <iostream> - -namespace ArgParser { - - // Base abstract class for one argument - - class Arg { - protected: - int num; - std::string name; - bool used; - public: - const static int OPTIONAL = 0; - const static int REQUIRED = 1; - Arg(int nu, const std::string &n) : num(nu), name(n), used(false) { } - virtual ~Arg(void) { } - virtual bool parse(const char * a, ArgumentError & error) = 0; - virtual std::string getParam(void) const = 0; - virtual void assign(void) = 0; - bool isUsed(void) { return used; } - template<class T> void get(T &v) = 0; - friend class Args; - }; - - // template function to set argument value - - - template<class T> void setValue(const std::string &name, T&value, - const char * param, - ArgumentError & Error) { - // std::cerr << "Unimplemented setValue invoked" << endl; - error = ArgumentError(ArgumentError::INVALID); - } - - template<class T> class ArgT : public Arg { - T value; - T & valueRef; - int type; - checker<T> & sc; - public: - ArgT(int n, const std::string &name, T & v, int t, checker<T> & _sc) : - Arg(n, name), - valueRef(v), - type(t), - sc(_sc) { - value = v; - } - - virtual void assign(void) { - valueRef = value; - } - - virtual void get(T &v) { - v = value; - } - - - std::string getParam(void) const; - - virtual bool parse(const char * a, ArgumentError & error) { - used = true; - setValue(name, value, a, error); - std::string err; - if (!sc(value, err)) { - error = ArgumentError(ArgumentError::CHECK, name, err); - return a == NULL ? false : true; - } - return true; - } - }; - - // Standard types: int, float, and std::string, vectors and maps - - void setValue(const std::string &name, int &value, const char * a, ArgumentError & error); - void setValue(const std::string &name, float &value, const char * a, ArgumentError & error); - void setValue(const std::string &name, std::string &value, const char * a, ArgumentError & error); - - template<class T> void setValue(const std::string &name, - std::vector<T> &value, - const char * a, - ArgumentError & error) - { - // cerr << "setValue vector<T>" << endl; - if (a != NULL) { - T arg; - setValue(name, arg, a, error); - // cout << "vector<T> argument " << name << " = " << arg << endl; - value.push_back(arg); - } - else - error = ArgumentError(ArgumentError::MISSING, name); - } - - template<class K, class V> void setValue(const std::string &name, - std::map<K, V> &value, - const char * a, - ArgumentError & error) - { - // cerr << "setValue map<K, V>" << endl; - if (a != NULL) { - K key; - V val; - std::string k(a); - char * eq = strchr(a, '='); - while (eq != NULL && eq != a && (*(eq-1) == '\\')) - eq = strchr(eq + 1, '='); - if (eq == NULL) { - error = ArgumentError(ArgumentError::MISSING, name); - return; - } - k.resize(eq - a); - std::string::size_type p = k.find("\\="); - while (p != std::string::npos) { - k = k.substr(0, p) + k.substr(p + 1); - p = k.find("\\="); - } - std::string v(eq + 1); - setValue(name, key, k.c_str(), error); - setValue(name, val, v.c_str(), error); - cout << "vector<T> argument " << name << " = (" - << k << " => " << val << ")" << endl; - value[key] = val; - } - else - error = ArgumentError(ArgumentError::MISSING, name); - } - - class StringBoolArg { - std::string & target; - std::string yes; - std::string no; - public: - StringBoolArg(std::string &t, - const std::string &y = "yes", - const std::string &n ="no") - : target(t), yes(y), no(n) - { - target = no; - } - void set(void) { - target = yes; - } - }; - - template<> - inline bool ArgParser::ArgT<bool>::parse(const char * a, ArgumentError & error) - { - used = true; - value = true; - return false; - } - - template<> - inline bool ArgParser::ArgT<StringBoolArg>::parse(const char * a, ArgumentError & error) - { - used = true; - value.set(); - return false; - } - -} - -#endif diff --git a/src/arg-checkers.h b/src/arg-checkers.h @@ -1,129 +0,0 @@ -/* -*- Mode: c++; -*- */ -/* -------------------------------------------------------------------- - * Filename: - * arg-checkers.h - * - * Description: - * Checker classes for Argument Parser - * - * Authors: - * Eivind Kvedalen <argparser@eivind.kvedalen.name> - * - * Bugs: - * - * ChangeLog: - * - * -------------------------------------------------------------------- - * Copyright 2002-2004 Eivind Kvedalen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. - * -------------------------------------------------------------------- - */ - -#ifndef _ARG_CHECKERS_H -#define _ARG_CHECKERS_H - -#include <string> -#include "convert.h" -#include <functional> -#include <set> - -namespace ArgParser { - - // - // Argument checkers - // - - // check interface - - template<class T> class checker : public std::unary_function<T, bool> { - public: - virtual bool operator()(const T &value, std::string & error) const = 0; - }; - - // Default checker, always returns true - - template<class T> class ok_function : public checker<T> { - public: - bool operator()(const T &value, std::string & error) const { - // cerr << "ok_function" << endl; - error = ""; - return true; - } - }; - - // less than - - template<class T> class less_than : public checker<T> { - T value; - public: - less_than(const T &v) : value(v) {} - bool operator()(const T &value, std::string & error) const { - bool result = std::less<T>()(value, this->value); - Binc::BincStream s; - if (!result) - s << "value " << value << "not less than " << this->value; - error = s.str(); - return result; - } - }; - - // range check - - template<class V> class range_check : public checker<V> { - V lower; - V upper; - public: - range_check(const V & l, const V & u) : lower(l), upper(u) { } - bool operator()(const V & value, std::string & error) const { - bool result = (lower <= value && value <= upper); - Binc::BincStream s; - if (!result) - s << "value " << value - << " not in range [" - << lower << ", " << upper << "]"; - error = s.str(); - return result; - } - }; - - template<class V> class enum_check : public checker<V> { - std::set<V> values; - public: - void add(const V&v) { - values.insert(v); - } - bool operator()(const V & value, std::string & error) const { - bool result = values.find(value) != values.end(); - Binc::BincStream s; - // cerr << "enum check" << endl; - if (!result) - s << "value " << value << " not in enumeration"; - error = s.str(); - return result; - } - enum_check<V> & operator,(const V & value) { - add(value); - return *this; - } - enum_check<V> & operator+=(const V & value) { - add(value); - return *this; - } - }; - -} - -#endif diff --git a/src/arg-error.cc b/src/arg-error.cc @@ -1,70 +0,0 @@ -/* -*- Mode: c++; -*- */ -/* -------------------------------------------------------------------- - * Filename: - * arg-error.cc - * - * Description: - * Implementation of error class for Argument Parser - * - * Authors: - * Eivind Kvedalen <argparser@eivind.kvedalen.name> - * - * Bugs: - * - * ChangeLog: - * - * -------------------------------------------------------------------- - * Copyright 2002-2004 Eivind Kvedalen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. - * -------------------------------------------------------------------- - */ - -#include "arg-error.h" - -using namespace std; -using namespace ArgParser; - -ArgumentError::ArgumentError(Type t, const string &name, const string &e) - : argName(name), - type(t), - error(e) -{ -} - -const string & ArgumentError::getName(void) const -{ - return argName; -} - -const string & ArgumentError::getErrorStr(void) const -{ - return error; -} - -const ArgumentError::Type ArgumentError::getErrorType(void) const -{ - return type; -} - -const set<string> & ArgumentError::getMissing(void) const -{ - return missing; -} - -void ArgumentError::add(const string & s) -{ - missing.insert(s); -} diff --git a/src/arg-error.h b/src/arg-error.h @@ -1,73 +0,0 @@ -/* -*- Mode: c++; -*- */ -/* -------------------------------------------------------------------- - * Filename: - * arg-error.h - * - * Description: - * Error class for Argument Parser - * - * Authors: - * Eivind Kvedalen <argparser@eivind.kvedalen.name> - * - * Bugs: - * - * ChangeLog: - * - * -------------------------------------------------------------------- - * Copyright 2002-2004 Eivind Kvedalen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. - * -------------------------------------------------------------------- - */ - -#ifndef _ARG_EXCEPTIONS_H -#define _ARG_EXCEPTIONS_H - -#include <string> -#include <set> - -namespace ArgParser { - - class ArgumentError { - public: - enum Type { - NONE, - CHECK, - REQUIRED_COMMAND, - REQUIRED_ARGUMENT, - UNKNOWN, - MISSING, - INVALID - }; - protected: - std::string argName; - Type type; - std::string error; - std::set<std::string> missing; - public: - ArgumentError(Type t, const std::string &name = "", const std::string &e = ""); - - const std::string & getName(void) const; - const std::string & getErrorStr(void) const; - const Type getErrorType(void) const; - const std::set<std::string> & getMissing(void) const; - - void add(const std::string & s); - - }; - -} - -#endif diff --git a/src/arg-parser.cc b/src/arg-parser.cc @@ -1,208 +0,0 @@ -/* -*- Mode: c++; -*- */ -/* -------------------------------------------------------------------- - * Filename: - * arg-parser.cc - * - * Description: - * Implementation of argument parser - * - * Authors: - * Eivind Kvedalen <argparser@eivind.kvedalen.name> - * - * Bugs: - * - * ChangeLog: - * - * -------------------------------------------------------------------- - * Copyright 2003 Eivind Kvedalen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. - * -------------------------------------------------------------------- - */ - -#include "arg-parser.h" -#include <algorithm> - -using namespace ArgParser; -using namespace std; - -Args::~Args(void) { - StringArgPtrMap::const_iterator i = args.begin(); - while (i != args.end()) { - delete i->second; - ++i; - } -} - -void Args::tokenize(const string &s, char sep, - vector<string> &result) const -{ - string::size_type p; - string::size_type o = 0; - while ((p = s.find(sep, o)) != string::npos) { - result.push_back(s.substr(0, p)); - o = p + 1; - } - result.push_back(s.substr(o)); -} - -int Args::parse(vector<string> & rest, ArgumentError & error) const { - set<int> parsed; - int i; - for (i = 1; i < argc; ++i) { - const string & arg = argv[i]; - // If we encounter '--' then stop parsing - if (arg == "--") { - ++i; - break; - } - - // Find next argument, and put in next if it doesn't start with - // '-' - string::size_type c = arg.find("="); - char const * next; - string a; - if (c != string::npos) { - a = arg.substr(0, c); - //cerr << a << endl; - next = arg.c_str() + c + 1; - } - else { - a = arg; - next = i < (argc - 1) ? argv[i + 1] : NULL; - } - - vector<string> cmd; - - // Strip "--" and "-" from argument - if (a.substr(0, 2) == "--") { - a = a.substr(2); - cmd.push_back(a); - } - else if (a.substr(0, 1) == "-") { - a = a.substr(1); - for (string::const_iterator j = a.begin(); j != a.end(); ++j) - cmd.push_back(string("") + *j); - } - else { - // Not starting with "--" or "-"; push them on the rest vector - rest.push_back(argv[i]); - continue; - } - - if (next != NULL && *next == '-') next = NULL; - - vector<string>::const_iterator k = cmd.begin(); - int used = 0; - while (k != cmd.end()) { - // Find handler - map<string, Arg*>::const_iterator j = args.find(*k); - if (j != args.end()) { - if (j->second->parse(next, error)) used = (next == NULL); - parsed.insert(j->second->num); - } - else { - // Handler not found; if the argument starts with a "-", then - // flag an error, or else push it on the rest vector. - if (arg.size() > 0 && arg[0] == '-') { - error = ArgumentError(ArgumentError::UNKNOWN, *k); - return -1; - } - rest.push_back(argv[i]); - } - ++k; - } - i += used; - } - if (!includes(parsed.begin(), parsed.end(), - requiredArgs.begin(), requiredArgs.end())) { - ArgumentError e(ArgumentError::REQUIRED_ARGUMENT); - set<int> missing; - insert_iterator<set<int> > missing_ins(missing, missing.begin()); - set_difference(requiredArgs.begin(), requiredArgs.end(), - parsed.begin(), parsed.end(), missing_ins); - set<int>::const_iterator i = missing.begin(); - while (i != missing.end()) { - e.add(argNum.find(*i)->second); - ++i; - } - error = e; - return -1; - } - if (mode.size() > 0) { - set<int> other; - insert_iterator<set<int> > other_ins(other, other.begin()); - set_intersection(mode.begin(), mode.end(), - parsed.begin(), parsed.end(), other_ins); - if (other.size() != 1) { - error = ArgumentError(ArgumentError::REQUIRED_COMMAND); - return -1; - } - } - return i; -} - -void Args::assign(void) -{ - StringArgPtrMap::iterator i = args.begin(); - while (i != args.end()) { - if (i->second->isUsed()) - i->second->assign(); - ++i; - } -} - -void Args::assign(const std::string s) -{ - StringArgPtrMap::iterator i = args.find(s); - if (i != args.end() && i->second->isUsed()) - i->second->assign(); -} - -void Args::addHelpString(const string & key, const string & help) -{ - helpStrings[key] = help; -} - -void Args::displayHelp(ostream & o) const -{ - for (map<string, string>::const_iterator i = helpStrings.begin(); i != helpStrings.end(); ++i) { - vector<string> v; - tokenize(i->first, '|', v); - vector<string>::const_iterator j = v.begin(); - while (j != v.end()) { - StringArgPtrMap::const_iterator pi = args.find(*j); - if (pi != args.end()) { - if ((*j).size() == 1) - o << "-" << *j << pi->second->getParam(); - else - o << "--" << *j << pi->second->getParam(); - ++j; - if (j != v.end()) - o << ", "; - } - } - o << endl; - - v.clear(); - tokenize(i->second, '\n', v); - j = v.begin(); - while (j != v.end()) { - o << "\t" << *j << endl; - ++j; - } - o << endl; - } -} diff --git a/src/arg-parser.h b/src/arg-parser.h @@ -1,149 +0,0 @@ -/* -*- Mode: c++; -*- */ -/* -------------------------------------------------------------------- - * Filename: - * arg-arg.h - * - * Description: - * Class for command line parsing - * - * Authors: - * Eivind Kvedalen <argparser@eivind.kvedalen.name> - * - * Bugs: - * - * ChangeLog: - * - * -------------------------------------------------------------------- - * Copyright 2003 Eivind Kvedalen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. - * -------------------------------------------------------------------- - */ - -#ifndef _ARG_PARSER_H -#define _ARG_PARSER_H - -#include "arg-arg.h" -#include <set> -#include <map> - -namespace ArgParser { - - class Args { - typedef std::map<std::string, Arg*> StringArgPtrMap; - StringArgPtrMap args; - std::map<int, std::string> argNum; - int argc; - char ** argv; - std::set<int> requiredArgs; - std::set<int> mode; - std::map<std::string, std::string> helpStrings; - protected: - template<class T> int addArgs(const std::string &name, - T &var, - int type, - checker<T> & sc) { - const int num = args.size(); - std::vector<std::string> v; - tokenize(name, '|', v); - std::vector<std::string>::const_iterator i = v.begin(); - while (i != v.end()) { - if (type == Arg::REQUIRED) - requiredArgs.insert(num); - args[*i] = new ArgT<T>(num, *i, var, type, sc); - argNum[num] = *i; - ++i; - } - return num; - } - - template<class T> class mapArg { - T & target; - T value; - public: - mapArg(T & t, const T &v) : target(t), value(v) { } - void set(void) { - target = value; - } - }; - - public: - Args(void) : argc(0), argv(NULL) { } - Args(int c, char * v[]) : argc(c), argv(v) { } - ~Args(void); - - void addHelpString(const std::string & key, const std::string & help); - - void displayHelp(std::ostream & o) const; - - void tokenize(const std::string &s, char sep, - std::vector<std::string> &result) const; - template<class T> void addMode(const std::string &name, - T &var, - const T &value) { - static ok_function<mapArg<T> > f; - int i = addArgs(name, *(new mapArg<T>(var, value)), Arg::OPTIONAL, f); - mode.insert(args[argNum[i]]->num); - } - - template<class T> void addMode(const std::string &name, - T &var, - const T &value, - const checker<T> & sc) { - int i = addArgs(name, mapArg<T>(var, value), Arg::OPTIONAL, sc); - mode.insert(args[argNum[i]]->num); - } - - template<class T> void addOptional(const std::string &name, T &var, - checker<T> & sc) { - addArgs(name, var, Arg::OPTIONAL, sc); - } - - template<class T> void addOptional(const std::string &name, T &var) { - static ok_function<T> f; - addArgs(name, var, Arg::OPTIONAL, f); - } - - template<class T> void addRequired(const std::string &name, T &var, - const checker<T> & sc) { - addArgs(name, var, Arg::REQUIRED, sc); - } - - template<class T> void addRequired(const std::string &name, T &var) { - static ok_function<T> f; - addArgs(name, var, Arg::REQUIRED, f); - } - - template<class T> bool get(const std::string &name, T &var) { - StringArgPtrMap::iterator i = args.find(name); - if (i == args.end()) return false; - i->second->get(name, var); - return true; - } - - int parse(std::vector<std::string> & rest, ArgumentError & error) const; - - void assign(void); - void assign(const std::string s); - - template<class T> void setValue(const std::string &name, - Args::mapArg<T> &value, const char * a) - { - value.set(); - } - }; -} - -#endif diff --git a/src/argparser.cc b/src/argparser.cc @@ -0,0 +1,338 @@ +/* -*- Mode: c++; -*- */ +/* -------------------------------------------------------------------- + * Filename: + * src/argparser.cc + * + * Description: + * <---> + * + * Authors: + * Andreas Aardal Hanssen <bincimap@andreas.hanssen.name> + * + * Bugs: + * + * ChangeLog: + * + * -------------------------------------------------------------------- + * Copyright 2002-2004 Andreas Aardal Hanssen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. + * -------------------------------------------------------------------- + */ +#include "argparser.h" +#include <string> +#include <map> + +using namespace ::std; +using namespace Binc; + +//---------------------------------------------------------------------- +CommandLineArgs::CommandLineArgs() +{ + errString = "Unknown error"; + ac = 0; +} + +//---------------------------------------------------------------------- +bool CommandLineArgs::parse(int argc, char *argv[]) +{ + ac = -1; + head = argv[0]; + head += " <options> --\n"; + + if (argc > 1) { + string lastKey; + bool lastIsBoolean = false; + + for (int i = 1; i < argc; ++i) { + string s = argv[i]; + if (s.length() < 2) { + errString = "syntax error: " + s; + return false; + } + + if (s[0] != '-') { + // read value of last argument + if (lastKey == "") { + errString = "syntax error: " + s; + return false; + } + + if (lastIsBoolean && (s != "yes" && s != "no")) { + errString = "syntax error: " + s; + errString += " (expected yes or no)"; + return false; + } + + args[lastKey] = s; + lastKey = ""; + lastIsBoolean = false; + } else if (s[1] == '-') { + if (lastKey != "") { + if (lastIsBoolean) { + args[lastKey] = "yes"; + lastKey = ""; + lastIsBoolean = false; + } else { + errString = "expected value of "; + errString += lastKey; + return false; + } + } + + // break if '--' is detected + if (s.length() == 2) { + ac = i + 1; + break; + } + + // parse --argument + string arg = s.substr(2); + string val; + string::size_type epos = arg.find('='); + if (epos != string::npos) { + val = arg.substr(epos + 1); + arg = arg.substr(0, epos); + } + + if (reg.find(arg) == reg.end()) { + errString = "unrecognized argument: --" + arg; + return false; + } + + if (reg.find(arg)->second.b) { + if (val != "" && val != "yes" && val != "no") { + errString = "syntax error: " + val; + errString += " (expected yes or no)"; + return false; + } else if (val == "") { + val = "yes"; + } + } + + if (val == "") { + errString = "syntax error: " + arg; + errString += " (expected --" + arg + "=<str>)"; + return false; + } + + args[arg] = val; + lastKey = ""; + lastIsBoolean = false; + } else { + if (lastKey != "") { + if (lastIsBoolean) { + args[lastKey] = "yes"; + lastKey = ""; + lastIsBoolean = false; + } else { + errString = "expected value of "; + errString += lastKey; + return false; + } + } + + // parse -argument + string arg = s.substr(1); + if (arg.length() == 1) { + map<string, ArgOpts>::const_iterator it = reg.begin(); + bool match = false; + for (; it != reg.end(); ++it) { + if (it->second.c.find(arg[0]) != string::npos) { + lastKey = it->first; + if (it->second.b) + lastIsBoolean = true; + match = true; + break; + } + } + + if (!match) { + errString = "unrecognized argument: -"; + errString += arg[0]; + return false; + } + + } else { + string::const_iterator its = arg.begin(); + for (; its != arg.end(); ++its) { + map<string, ArgOpts>::const_iterator it = reg.begin(); + bool match = false; + for (; it != reg.end(); ++it) { + if (it->second.c.find(*its) != string::npos) { + if (!it->second.b) { + errString = "argument is not a boolean: "; + errString += "--" + it->first; + errString += " / -"; + errString += it->second.c; + return false; + } + + match = true; + args[it->first] = "yes"; + lastKey = ""; + lastIsBoolean = false; + break; + } + } + + if (!match) { + errString = "unrecognized argument: "; + errString += s; + return false; + } + } + } + } + } + + if (lastKey != "") { + if (lastIsBoolean) { + args[lastKey] = "yes"; + } else { + errString = "expected value of "; + errString += lastKey; + return false; + } + } + } + + map<string, ArgOpts>::const_iterator it = reg.begin(); + for (; it != reg.end(); ++it) { + if (args.find(it->first) == args.end()) { + if (!it->second.o) { + errString = "missing argument: "; + errString += it->first; + return false; + } + + if (it->second.b) + args[it->first] = "no"; + } + } + + if (ac == -1) + ac = argc; + + return true; +} + +//---------------------------------------------------------------------- +string CommandLineArgs::errorString(void) const +{ + return errString; +} + +//---------------------------------------------------------------------- +const string CommandLineArgs::operator [](const string &arg) const +{ + if (args.find(arg) == args.end()) + return ""; + + return args.find(arg)->second; +} + +//---------------------------------------------------------------------- +void CommandLineArgs::addOptional(const string &arg, const string &desc, + bool boolean) +{ + registerArg(arg, desc, boolean, true); +} + +//---------------------------------------------------------------------- +void CommandLineArgs::addRequired(const string &arg, + const string &desc, bool boolean) +{ + registerArg(arg, desc, boolean, false); +} + +//---------------------------------------------------------------------- +void CommandLineArgs::registerArg(const string &arg, const string &desc, + bool boolean, bool optional) +{ + string name = arg; + + string shorts; + while (name.size() > 1 && name[1] == '|') { + shorts += name[0]; + name = name.substr(2); + } + + reg.insert(make_pair(name, ArgOpts(shorts, boolean, optional, desc))); +} + +//---------------------------------------------------------------------- +string CommandLineArgs::usageString(void) const +{ + string tmp = head; + tmp += '\n'; + + map<string, ArgOpts>::const_iterator it = reg.begin(); + for (; it != reg.end(); ++it) { + if (it->second.c != "") { + string::const_iterator sit = it->second.c.begin(); + for (; sit != it->second.c.end(); ++sit) { + if (sit != it->second.c.begin()) + tmp += '\n'; + tmp += " -"; + tmp += *sit; + } + tmp += ", "; + } else { + tmp += " "; + } + + tmp += "--"; + tmp += it->first; + if (!it->second.b) { + tmp += "=<str>"; + } + + if (!it->second.o) + tmp += " (required)"; + + string::size_type lineStart = tmp.rfind('\n'); + if (lineStart == string::npos) + lineStart = 0; + + int pad = 21 - (tmp.length() - lineStart); + if (pad < 0) { + tmp += '\n'; + pad = 20; + } + + tmp += string(pad, ' '); + tmp += it->second.desc; + tmp += '\n'; + } + + tmp += '\n'; + tmp += tail; + tmp += '\n'; + + return tmp; +} + +//---------------------------------------------------------------------- +int CommandLineArgs::argc(void) const +{ + return ac; +} + +//---------------------------------------------------------------------- +void CommandLineArgs::setTail(const string &str) +{ + tail = str; +} diff --git a/src/argparser.h b/src/argparser.h @@ -0,0 +1,89 @@ +/* -*- Mode: c++; -*- */ +/* -------------------------------------------------------------------- + * Filename: + * src/argparser.h + * + * Description: + * <---> + * + * Authors: + * Andreas Aardal Hanssen <bincimap@andreas.hanssen.name> + * + * Bugs: + * + * ChangeLog: + * + * -------------------------------------------------------------------- + * Copyright 2002-2004 Andreas Aardal Hanssen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. + * -------------------------------------------------------------------- + */ +#ifndef ARGPARSER_H_INCLUDED +#define ARGPARSER_H_INCLUDED +#include <string> +#include <map> + +namespace Binc { + class ArgOpts { + public: + std::string c; + bool b; + bool o; + std::string desc; + + inline ArgOpts(const std::string &chr, bool boolean, bool optional, + const std::string &descr) + { + c = chr; + b = boolean; + o = optional; + desc = descr; + } + }; + + class CommandLineArgs { + public: + CommandLineArgs(void); + + bool parse(int argc, char *argv[]); + std::string errorString(void) const; + + int argc(void) const; + + const std::string operator [](const std::string &arg) const; + + void addOptional(const std::string &arg, const std::string &desc, + bool boolean); + void addRequired(const std::string &arg, const std::string &desc, + bool boolean); + std::string usageString(void) const; + + void setTail(const std::string &str); + + private: + void registerArg(const std::string &arg, const std::string &desc, + bool boolean, bool optional); + + std::string errString; + std::map<std::string, ArgOpts> reg; + std::map<std::string, std::string> args; + std::string tail; + std::string head; + int ac; + }; +} + +#endif diff --git a/src/session-initialize-bincimap-up.cc b/src/session-initialize-bincimap-up.cc @@ -49,7 +49,6 @@ using namespace ::std; using namespace Binc; -using namespace ArgParser; extern char **environ; diff --git a/src/session-initialize-bincimapd.cc b/src/session-initialize-bincimapd.cc @@ -53,7 +53,6 @@ using namespace ::std; using namespace Binc; -using namespace ArgParser; extern char **environ; diff --git a/src/session.cc b/src/session.cc @@ -37,6 +37,7 @@ #include <syslog.h> +#include "argparser.h" #include "io.h" #include "session.h" #include "storage.h" @@ -47,7 +48,6 @@ using namespace ::std; using namespace Binc; -using namespace ArgParser; extern char **environ; @@ -74,7 +74,6 @@ Session &Session::getInstance(void) //---------------------------------------------------------------------- void Session::initConfig(void) { - args.assign(); } //---------------------------------------------------------------------- @@ -175,91 +174,74 @@ int Session::getReadBytes(void) const bool Session::parseRequestLine(int argc, char * argv[]) { - args = ArgParser::Args(argc, argv); - - args.addOptional("h|?|help", command.help); - args.addOptional("v|version", command.version); - args.addOptional("s|ssl", command.ssl); - args.addOptional("c|conf", command.configfile); - - // Override config file settings with command line options - string arg; - args.addOptional("a|allow-plain", - globalconfig["Authentication"]["allow plain auth in non ssl"]); - args.addOptional("p|auth-penalty", - globalconfig["Authentication"]["auth penalty"]); - args.addOptional("d|disable-starttls", - globalconfig["Authentication"]["disable starttls"]); - - args.addOptional("L|logtype", globalconfig["Log"]["type"]); - args.addOptional("I|ip-variable", - globalconfig["Log"]["environment ip variable"]); - - args.addOptional("d|depot", globalconfig["Mailbox"]["depot"]); - args.addOptional("M|mailbox-type", globalconfig["Mailbox"]["type"]); - args.addOptional("m|mailbox-path", globalconfig["Mailbox"]["path"]); - args.addOptional("C|create-inbox", globalconfig["Mailbox"]["auto create inbox"]); - args.addOptional("S|subscribe-mailboxes", - globalconfig["Mailbox"]["auto subscribe mailboxes"]); - args.addOptional("u|umask", globalconfig["Mailbox"]["umask"]); - - args.addOptional("J|jail-path", globalconfig["Security"]["jail path"]); - args.addOptional("x|jail-user", globalconfig["Security"]["jail user"]); - args.addOptional("X|jail-group", globalconfig["Security"]["jail group"]); - - args.addOptional("i|idle-timeout", globalconfig["Session"]["idle timeout"]); - args.addOptional("t|auth-timeout", globalconfig["Session"]["auth timeout"]); - args.addOptional("T|transfer-timeout", - globalconfig["Session"]["transfer timeout"]); - args.addOptional("b|transfer-buffersize", - globalconfig["Session"]["transfer buffer size"]); - - args.addOptional("p|pem-file", globalconfig["SSL"]["pem file"]); - args.addOptional("P|ca-path", globalconfig["SSL"]["ca path"]); - args.addOptional("f|ca-file", globalconfig["SSL"]["ca file"]); - args.addOptional("l|cipher-list", globalconfig["SSL"]["cipher list"]); - args.addOptional("V|verify-peer", globalconfig["SSL"]["verify peer"]); - - ArgumentError e(ArgParser::ArgumentError::NONE); - vector<string> rest; - - int i = args.parse(rest, e); - if (i == -1) { - string err = e.getErrorStr(); - if (err == "") { - switch (e.getErrorType()) { - case ArgParser::ArgumentError::NONE: - err = "Unknown error (none)"; - break; - case ArgParser::ArgumentError::CHECK: - err = "Syntax error"; - break; - case ArgParser::ArgumentError::REQUIRED_COMMAND: - err = "Required command"; - break; - case ArgParser::ArgumentError::REQUIRED_ARGUMENT: - err = "Required argument"; - break; - case ArgParser::ArgumentError::UNKNOWN: - err = "No such argument"; - break; - case ArgParser::ArgumentError::MISSING: - err = "Missing argument"; - break; - case ArgParser::ArgumentError::INVALID: - err = "Invalid argument"; - break; - default: - break; - } - } - - setLastError("Command line \"" + e.getName() + "\": " + err); + CommandLineArgs args; + + args.addOptional("h|?|help", "Display this help screen", true); + args.addOptional("v|version", "Display the version of Binc IMAP", true); + args.addOptional("s|ssl", "Toggle enabling of SSL", true); + args.addOptional("c|conf", "Sets the path to the config file", false); + args.addOptional("a|allow-plain", "Allow authentication when not in SSL", true); + args.addOptional("p|auth-penalty", "Sets the auth penalty", false); + args.addOptional("d|disable-starttls", "Toggles disabling of STARTTLS", false); + args.addOptional("L|logtype", "Sets the method used for logging", false); + args.addOptional("I|ip-variable", "Sets the env variable that contains the remote IP", false); + args.addOptional("d|depot", "Sets the depot type", false); + args.addOptional("M|mailbox-type", "Sets the mailbox tyoe", false); + args.addOptional("m|mailbox-path", "Sets the mailbox path", false); + args.addOptional("C|create-inbox", "Toggles auto-creating INBOX", false); + args.addOptional("S|subscribe-mailboxes", "CSV list of mailboxes to subscribe to", false); + args.addOptional("u|umask", "Sets the default umask", false); + args.addOptional("J|jail-path", "Sets the jail path", false); + args.addOptional("x|jail-user", "Sets the jail user", false); + args.addOptional("X|jail-group", "Sets the jail group", false); + args.addOptional("i|idle-timeout", "Sets the idle timeout", false); + args.addOptional("t|auth-timeout", "Sets the auth timeout", false); + args.addOptional("T|transfer-timeout", "Sets the transfer timeout", false); + args.addOptional("b|transfer-buffersize", "Sets the transfer buffer size", false); + args.addOptional("p|pem-file", "Sets the path to the SSL PEM file", false); + args.addOptional("P|ca-path", "Sets the path to the CA cert file", false); + args.addOptional("f|ca-file", "Sets the path to the CA cert directory", false); + args.addOptional("l|cipher-list", "Sets the SSL cipher list", false); + args.addOptional("V|verify-peer", "Toggles peer verificatin", true); + + if (!args.parse(argc, argv)) { + setLastError("Command line error, " + args.errorString()); return false; } - unparsedArgs = argv + i; - args.assign(); + command.help = args["help"] == "yes" ? true : false; + command.version = args["version"] == "yes" ? true : false; + command.ssl = args["ssl"] == "yes" ? true : false; + command.configfile = args["conf"]; + globalconfig["Authentication"]["allow plain auth in non ssl"] = args["allow-plain"]; + globalconfig["Authentication"]["auth penalty"] = args["auth-penalty"]; + globalconfig["Authentication"]["disable starttls"] = args["disable-starttls"]; + + globalconfig["Log"]["type"] = args["logtype"]; + globalconfig["Log"]["environment ip variable"] = args["ip-variable"]; + + globalconfig["Mailbox"]["type"] = args["mailbox-type"]; + globalconfig["Mailbox"]["path"] = args["mailbox-path"]; + globalconfig["Mailbox"]["auto create inbox"] = args["create-inbox"]; + globalconfig["Mailbox"]["auto subscribe mailboxes"] = args["subscribe-mailboxes"]; + globalconfig["Mailbox"]["umask"] = args["umask"]; + + globalconfig["Security"]["jail path"] = args["jail-path"]; + globalconfig["Security"]["jail user"] = args["jail-user"]; + globalconfig["Security"]["jail group"] = args["jail-group"]; + + globalconfig["Session"]["idle timeout"] = args["idle-timeout"]; + globalconfig["Session"]["auth timeout"] = args["auth-timeout"]; + globalconfig["Session"]["transfer timeout"] = args["transfer-timeout"]; + globalconfig["Session"]["transfer buffer size"] = args["transfer-buffersize"]; + + globalconfig["SSL"]["pem file"] = args["pem-file"]; + globalconfig["SSL"]["ca path"] = args["ca-path"]; + globalconfig["SSL"]["ca file"] = args["ca-file"]; + globalconfig["SSL"]["cipher list"] = args["cipher-list"]; + globalconfig["SSL"]["verify peer"] = args["verify-peer"]; + + unparsedArgs = argv + args.argc(); return true; } diff --git a/src/session.h b/src/session.h @@ -37,9 +37,9 @@ #ifndef session_h_included #define session_h_included -#include "arg-parser.h" #include <string> #include <vector> +#include <map> namespace Binc { @@ -143,7 +143,6 @@ namespace Binc { mutable std::string lastError; mutable std::string responseCode; - ArgParser::Args args; pid_t pid; std::string hostname;