| 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; |
| 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 | } |