Changeset 3690

Show
Ignore:
Timestamp:
05/30/2012 07:05:22 PM (12 months ago)
Author:
kurtis.heimerl
Message:

New-style socketed CLI support. Hooray histories!

Location:
openbts/trunk/apps
Files:
2 added
3 modified

Legend:

Unmodified
Added
Removed
  • openbts/trunk/apps/Makefile.am

    r2242 r3690  
    2626 
    2727noinst_PROGRAMS = \ 
    28         OpenBTS 
     28        OpenBTS \ 
     29        OpenBTSDo \ 
     30        OpenBTSCLI 
    2931 
    3032OpenBTS_SOURCES = OpenBTS.cpp 
     
    4345        $(ORTP_LIBS) 
    4446 
     47OpenBTSCLI_SOURCES = OpenBTSCLI.cpp 
     48OpenBTSDo_SOURCES = OpenBTSDo.cpp 
     49OpenBTSCLI_LDADD = -lreadline -lncurses 
     50 
    4551EXTRA_DIST = \ 
    4652        OpenBTS.example.sql 
  • openbts/trunk/apps/OpenBTS.cpp

    r3688 r3690  
    5858#include <string.h> 
    5959#include <signal.h> 
    60  
    61 #ifdef HAVE_LIBREADLINE // [ 
    62 //#  include <stdio.h> 
    63 #  include <readline/readline.h> 
    64 #  include <readline/history.h> 
    65 #endif // HAVE_LIBREADLINE ] 
    6660 
    6761using namespace std; 
     
    139133int main(int argc, char *argv[]) 
    140134{ 
     135 
     136        int sock = socket(AF_UNIX,SOCK_DGRAM,0); 
     137        if (sock<0) { 
     138                perror("opening cmd datagram socket"); 
     139                exit(1); 
     140        } 
    141141 
    142142        try { 
     
    315315        gBTS.start(); 
    316316 
    317 #ifdef HAVE_LIBREADLINE // [ 
    318         // start console 
    319         using_history(); 
    320  
    321         static const char * const history_file_name = "/.openbts_history"; 
    322         char *history_name = 0; 
    323         char *home_dir = getenv("HOME"); 
    324  
    325         if(home_dir) { 
    326                 size_t home_dir_len = strlen(home_dir); 
    327                 size_t history_file_len = strlen(history_file_name); 
    328                 size_t history_len = home_dir_len + history_file_len + 1; 
    329                 if(history_len > home_dir_len) { 
    330                         if(!(history_name = (char *)malloc(history_len))) { 
    331                                 LOG(ERR) << "malloc failed: " << strerror(errno); 
    332                                 exit(2); 
    333                         } 
    334                         memcpy(history_name, home_dir, home_dir_len); 
    335                         memcpy(history_name + home_dir_len, history_file_name, 
    336                            history_file_len + 1); 
    337                         read_history(history_name); 
     317 
     318        cout << "\nsystem ready\n"; 
     319        cout << "\nuse the OpenBTSCLI utility to access CLI\n"; 
     320        LOG(INFO) << "system ready"; 
     321 
     322        struct sockaddr_un cmdSockName; 
     323        cmdSockName.sun_family = AF_UNIX; 
     324        const char* sockpath = gConfig.getStr("CLI.SocketPath","/var/run/OpenBTS/command").c_str(); 
     325        char rmcmd[strlen(sockpath)+5]; 
     326        sprintf(rmcmd,"rm %s",sockpath); 
     327        system(rmcmd); 
     328        strcpy(cmdSockName.sun_path,sockpath); 
     329        if (bind(sock, (struct sockaddr *) &cmdSockName, sizeof(struct sockaddr_un))) { 
     330                perror("binding name to cmd datagram socket"); 
     331                exit(1); 
     332        } 
     333 
     334        while (1) { 
     335                char cmdbuf[1000]; 
     336                struct sockaddr_un source; 
     337                socklen_t sourceSize = sizeof(source); 
     338                int nread = recvfrom(sock,cmdbuf,sizeof(cmdbuf)-1,0,(struct sockaddr*)&source,&sourceSize); 
     339                cmdbuf[nread]='\0'; 
     340                LOG(INFO) << "received command \"" << cmdbuf << "\" from " << source.sun_path; 
     341                std::ostringstream sout; 
     342                int res = gParser.process(cmdbuf,sout); 
     343                const std::string rspString= sout.str(); 
     344                const char* rsp = rspString.c_str(); 
     345                LOG(INFO) << "sending " << strlen(rsp) << "-char result to " << source.sun_path; 
     346                if (sendto(sock,rsp,strlen(rsp)+1,0,(struct sockaddr*)&source,sourceSize)<0) { 
     347                        LOG(ERR) << "can't send CLI response to " << source.sun_path; 
    338348                } 
    339         } 
    340 #endif // HAVE_LIBREADLINE ] 
    341  
    342  
    343  
    344         LOG(INFO) << "system ready"; 
    345         COUT("\n\nWelcome to OpenBTS.  Type \"help\" to see available commands."); 
    346         // FIXME: We want to catch control-d (emacs keybinding for exit()) 
    347  
    348  
    349         // The logging parts were removed from this loop. 
    350         // If we want them back, they will need to go into their own thread. 
    351         while (1) { 
    352 #ifdef HAVE_LIBREADLINE // [ 
    353                 char *inbuf = readline(gConfig.getStr("CLI.Prompt").c_str()); 
    354                 if (!inbuf) break; 
    355                 if (*inbuf) { 
    356                         add_history(inbuf); 
    357                         // The parser returns -1 on exit. 
    358                         if (gParser.process(inbuf, cout, cin)<0) { 
    359                                 free(inbuf); 
    360                                 break; 
    361                         } 
    362                 } 
    363                 free(inbuf); 
    364 #else // HAVE_LIBREADLINE ][ 
    365                 cout << endl << gConfig.getStr("CLI.Prompt"); 
    366                 cout.flush(); 
    367                 char inbuf[1024]; 
    368                 cin.getline(inbuf,1024,'\n'); 
    369                 // The parser returns -1 on exit. 
    370                 if (gParser.process(inbuf,cout,cin)<0) break; 
    371 #endif // !HAVE_LIBREADLINE ] 
    372         } 
    373  
    374 #ifdef HAVE_LIBREADLINE // [ 
    375         if(history_name) { 
    376                 int e = write_history(history_name); 
    377                 if(e) { 
    378                         fprintf(stderr, "error: history: %s\n", strerror(e)); 
    379                 } 
    380                 free(history_name); 
    381                 history_name = 0; 
    382         } 
    383 #endif // HAVE_LIBREADLINE ] 
     349                // res<0 means to exit the application 
     350                if (res<0) break; 
     351        } 
     352 
     353        } // try 
     354 
     355        catch (ConfigurationTableKeyNotFound e) { 
     356                LOG(ALERT) << "required configuration key " << e.key() << " not defined, aborting"; 
     357        } 
    384358 
    385359        if (gTransceiverPid) kill(gTransceiverPid, SIGKILL); 
    386  
    387  
    388         } 
    389  
    390         catch (ConfigurationTableKeyNotFound e) { 
    391  
    392                 LOG(ALERT) << "configuration key " << e.key() << " not defined"; 
    393                 exit(2); 
    394         } 
     360        close(sock); 
    395361 
    396362} 
  • openbts/trunk/apps/OpenBTS.example.sql

    r3124 r3690  
    22BEGIN TRANSACTION; 
    33CREATE TABLE CONFIG ( KEYSTRING TEXT UNIQUE NOT NULL, VALUESTRING TEXT, STATIC INTEGER DEFAULT 0, OPTIONAL INTEGER DEFAULT 0, COMMENTS TEXT DEFAULT ''); 
    4 INSERT INTO "CONFIG" VALUES('CLI.Prompt','OpenBTS> ',0,0,'Prompt for the OpenBTS command line interface.'); 
     4INSERT INTO "CONFIG" VALUES('CLI.SocketPath','/var/run/command',0,0,'Path for Unix domain datagram socket used for the OpenBTS console interface.'); 
    55INSERT INTO "CONFIG" VALUES('Control.Reporting.PhysStatusTable','/var/run/OpenBTSChannelTable.db',1,0,'File path for channel status reporting database.  Static.'); 
    66INSERT INTO "CONFIG" VALUES('Control.Reporting.TMSITable','/var/run/OpenBTSTMSITable.db',1,0,'File path for TMSITable database.  Static.');