bincimap

Log | Files | Refs | LICENSE

session-initialize-bincimapd.cc (9276B)


      1 /* -*- Mode: c++; -*- */
      2 /*  --------------------------------------------------------------------
      3  *  Filename:
      4  *    session-initialize-bincimap-up.cc
      5  *  
      6  *  Description:
      7  *    <--->
      8  *
      9  *  Authors:
     10  *    Andreas Aardal Hanssen <andreas-binc curly bincimap spot org>
     11  *
     12  *  Bugs:
     13  *
     14  *  ChangeLog:
     15  *
     16  *  --------------------------------------------------------------------
     17  *  Copyright 2002-2005 Andreas Aardal Hanssen
     18  *
     19  *  This program is free software; you can redistribute it and/or modify
     20  *  it under the terms of the GNU General Public License as published by
     21  *  the Free Software Foundation; either version 2 of the License, or
     22  *  (at your option) any later version.
     23  *
     24  *  This program is distributed in the hope that it will be useful,
     25  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
     26  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     27  *  GNU General Public License for more details.
     28  *
     29  *  You should have received a copy of the GNU General Public License
     30  *  along with this program; if not, write to the Free Software
     31  *  Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
     32  *  --------------------------------------------------------------------
     33  */
     34 #ifdef HAVE_CONFIG_H
     35 #include <config.h>
     36 #endif
     37 
     38 #include <syslog.h>
     39 
     40 #include "broker.h"
     41 #include "maildir.h"
     42 #include "depot.h"
     43 #include "io-ssl.h"
     44 #include "io.h"
     45 #include "session.h"
     46 #include "storage.h"
     47 #include "tools.h"
     48 #include "convert.h"
     49 #include <string>
     50 #include <map>
     51 #include <signal.h>
     52 
     53 using namespace ::std;
     54 using namespace Binc;
     55 
     56 extern char **environ;
     57 
     58 namespace {
     59   //------------------------------------------------------------------------
     60   void usage(char *name)
     61   {
     62     IO &logger = IOFactory::getInstance().get(2);
     63 
     64     logger << "Please refer to the man pages for bincimap-up and bincimapd"
     65 	   << endl;
     66     logger << "for more information about how to invoke Binc IMAP." << endl;
     67     logger.flushContent();
     68   }
     69 }
     70 
     71 //----------------------------------------------------------------------
     72 bool Session::initialize(int argc, char *argv[])
     73 {
     74   IOFactory &iofactory = IOFactory::getInstance();
     75   iofactory.assign(1, new IO(stdout));
     76   iofactory.assign(2, new IO(stderr));
     77 
     78   IO &com = iofactory.get(1);
     79   IO &logger = iofactory.get(2);
     80   logger.disable();
     81 
     82   Session &session = Session::getInstance();
     83 
     84   session.importFromEnv();
     85 
     86   // Read command line arguments
     87   if (!session.parseRequestLine(argc, argv))
     88     return false;
     89 
     90   // Assign command line arguments to global config.
     91   session.assignCommandLineArgs();
     92 
     93   // log settings
     94   string ipenv = session.globalconfig["Log"]["ip environment variable"];
     95   // Initialize logger
     96   string ip = getenv(ipenv.c_str()) ? getenv(ipenv.c_str()) :
     97     getenv("TCPREMOTEIP") ? getenv("TCPREMOTEIP") :
     98     getenv("REMOTEIP") ? getenv("REMOTEIP") :
     99     getenv("SSLREMOTEIP") ? getenv("SSLREMOTEIP") : "?";
    100   session.setIP(ip);
    101 
    102   if (session.globalconfig["Log"]["type"] == "multilog") {
    103     logger.setLogPrefix(session.getUserID() + "@" + ip + ":");
    104     logger.enableLogPrefix();
    105   } else if (session.globalconfig["Log"]["type"] == "stderr" ) {
    106     // stderr is the default
    107   } else if (session.globalconfig["Log"]["type"] == "" 
    108 	     || session.globalconfig["Log"]["type"] == "syslog") {
    109     const string f = session.globalconfig["Log"]["syslog facility"];
    110     const string fn = session.globalconfig["Log"]["syslog facility number"];
    111 
    112     int facility;
    113 
    114     if (fn != "") facility = atoi(fn);
    115     else {
    116       if (f == "LOG_USER") facility = LOG_USER;
    117       else if (f == "LOG_LOCAL0") facility = LOG_LOCAL0;
    118       else if (f == "LOG_LOCAL1") facility = LOG_LOCAL1;
    119       else if (f == "LOG_LOCAL2") facility = LOG_LOCAL2;
    120       else if (f == "LOG_LOCAL3") facility = LOG_LOCAL3;
    121       else if (f == "LOG_LOCAL4") facility = LOG_LOCAL4;
    122       else if (f == "LOG_LOCAL5") facility = LOG_LOCAL5;
    123       else if (f == "LOG_LOCAL6") facility = LOG_LOCAL6;
    124       else if (f == "LOG_LOCAL7") facility = LOG_LOCAL7;
    125       else facility = LOG_DAEMON;
    126     }
    127 
    128     session.globalconfig["Log"]["syslog facility number"] = toString(facility);
    129 
    130     logger.setModeSyslog("bincimapd", facility);
    131   }
    132 
    133   logger.enable();
    134 
    135   // Now that we know the log type, we can flush.
    136   logger.flushContent();
    137   logger.flushOnEndl();
    138 
    139   // Read command line arguments
    140   if (!session.parseRequestLine(argc, argv)) {
    141     logger << session.getLastError() << endl;
    142     return false;
    143   }
    144 
    145   // Show help if asked for it
    146   if (session.command.help) {
    147     usage(argv[0]);
    148     return false;
    149   }
    150 
    151   // Show help if asked for it
    152   if (session.command.version) {
    153     logger << "Binc IMAP v" << VERSION << endl;
    154     return false;
    155   }
    156 
    157   char *logindetails = getenv("BINCIMAP_LOGIN");
    158   if (logindetails == 0) {
    159     logger 
    160       << "BINCIMAP_LOGIN missing from environment (are you sure you invoked " 
    161       << argv[0] << " properly?)" << endl;
    162     return false;
    163   }
    164 
    165   //-----
    166 
    167   // try to read local settings.
    168   Storage lconfig(".bincimap", Storage::ReadOnly);
    169   string section, key, value;
    170   while (lconfig.get(&section, &key, &value))
    171     session.localconfig[section][key] = value;
    172 
    173   string tmp;
    174   if ((tmp = session.localconfig["Mailbox"]["depot"]) != "")
    175     session.globalconfig["Mailbox"]["depot"] = tmp;
    176   if ((tmp = session.localconfig["Mailbox"]["path"]) != "")
    177     session.globalconfig["Mailbox"]["path"] = tmp;
    178   if ((tmp = session.localconfig["Mailbox"]["type"]) != "")
    179     session.globalconfig["Mailbox"]["type"] = tmp;
    180 
    181   DepotFactory &depotfactory = DepotFactory::getInstance();
    182   depotfactory.assign(new IMAPdirDepot());
    183   depotfactory.assign(new MaildirPPDepot());
    184 
    185   string depottype = session.globalconfig["Mailbox"]["depot"];
    186   if (depottype == "") depottype = "Maildir++";
    187 
    188   if ((depot = depotfactory.get(depottype)) == 0) {
    189     logger << "Found no Depot for \"" << depottype
    190 	   << "\". Please check "
    191       " your configurations file under the Mailbox section."
    192 	   << endl;
    193     logger.flushContent();
    194     return false;
    195   }
    196 
    197   depot->assign(new Maildir());
    198   depot->setDefaultType("Maildir");
    199 
    200   BrokerFactory &brokerfactory = BrokerFactory::getInstance();
    201 
    202   brokerfactory.assign("APPEND", new AppendOperator());
    203   brokerfactory.assign("CAPABILITY", new CapabilityOperator());
    204   brokerfactory.assign("CHECK", new CheckOperator());
    205   brokerfactory.assign("CLOSE", new CloseOperator());
    206   brokerfactory.assign("COPY", new CopyOperator());
    207   brokerfactory.assign("CREATE", new CreateOperator());
    208   brokerfactory.assign("DELETE", new DeleteOperator());
    209   brokerfactory.assign("EXAMINE", new ExamineOperator());
    210   brokerfactory.assign("EXPUNGE", new ExpungeOperator());
    211   brokerfactory.assign("FETCH", new FetchOperator());
    212   brokerfactory.assign("LIST", new ListOperator());
    213   brokerfactory.assign("LOGOUT", new LogoutOperator());
    214   brokerfactory.assign("LSUB", new LsubOperator());
    215   brokerfactory.assign("NOOP", new NoopPendingOperator());
    216   brokerfactory.assign("RENAME", new RenameOperator());
    217   brokerfactory.assign("SEARCH", new SearchOperator());
    218   brokerfactory.assign("SELECT", new SelectOperator());
    219   brokerfactory.assign("STATUS", new StatusOperator());
    220   brokerfactory.assign("STORE", new StoreOperator());
    221   brokerfactory.assign("SUBSCRIBE", new SubscribeOperator());
    222   brokerfactory.assign("UNSUBSCRIBE", new UnsubscribeOperator());
    223 
    224   string path = session.globalconfig["Mailbox"]["path"];
    225   if (session.args.getUnqualifiedArgs().size() > 0)
    226     path = session.args.getUnqualifiedArgs()[0];
    227   if (path == "") path = ".";
    228   else if (chdir(path.c_str()) != 0) {
    229     mkdir(path.c_str(), 0777);
    230     if (chdir(path.c_str()) != 0) {
    231       logger << "when entering depot " + toImapString(path) + ": "
    232 	     << strerror(errno) << endl;
    233       return false;
    234     }
    235   }
    236 
    237   if (depot->get("INBOX") == 0) {
    238     if (session.globalconfig["Mailbox"]["auto create inbox"] == "yes")
    239       if (!depot->createMailbox("INBOX")) {
    240 	logger << depot->getLastError() << endl;
    241 	return false;
    242       }
    243   }
    244 
    245   // load subscription list
    246   session.loadSubscribes();
    247 
    248   session.setState(Session::AUTHENTICATED);
    249 
    250   // Read timeout settings from global config
    251   idletimeout = atoi(session.globalconfig["Session"]["idle timeout"]);
    252   if (idletimeout < 30 * 60)
    253     idletimeout = 30 * 60;
    254   
    255   transfertimeout = atoi(session.globalconfig["Session"]["transfer timeout"]);
    256 
    257   // Set transfer timeout
    258   com.setTransferTimeout(transfertimeout);
    259   logger.setTransferTimeout(transfertimeout);
    260 
    261   // Read transfer buffer size
    262   int buffersize = atoi(session.globalconfig["Session"]["transfer buffer size"]);
    263   com.setBufferSize(buffersize >= 0 ? buffersize : 0);
    264 
    265   // umask settings
    266   string umsk = session.globalconfig["Mailbox"]["umask"];
    267   if (umsk != "") {
    268     unsigned int mode;
    269     sscanf(session.globalconfig["Mailbox"]["umask"].c_str(), "%o", &mode);
    270     umask((mode_t) mode);
    271   }
    272 
    273   const string details = logindetails;
    274   string::size_type det = details.find('+');
    275   if (det == string::npos) {
    276     logger << "invalid content of BINCIMAP_LOGIN - did you invoke "
    277        << argv[0] << " correctly?" << endl;
    278     return false;
    279   }
    280 
    281   const string tag = details.substr(det + 1);
    282   const string command = details.substr(0, det);
    283   com << tag << " OK " << command << " completed" << endl;
    284   com.flushContent();
    285 
    286   return true;
    287 }