/* * OpenBTS provides an open source alternative to legacy telco protocols and * traditionally complex, proprietary hardware systems. * * Copyright 2011, 2012, 2013, 2014 Range Networks, Inc. * * This software is distributed under the terms of the GNU Affero General * See the COPYING and NOTICE files in the current or main directory for * directory for licensing information. * * This use of this software may be subject to additional restrictions. * See the LEGAL file in the main directory for details. */ // KEEP THIS FILE CLEAN FOR PUBLIC RELEASE. #include #include #include #include #include #include #include #include #include #define HAVE_LIBREADLINE #ifdef HAVE_LIBREADLINE # include # include #endif #define DEFAULT_CMD_PATH "/var/run/OpenBTS-UMTS-command" #define DEFAULT_RSP_PATH "./response" int main(int argc, char *argv[]) { printf("OpenBTS-UMTS Commnd Line Interface (CLI) utility\n"); printf("Copyright 2012, 2013, 2014 Range Networks, Inc.\n"); printf("Licensed under GPLv2.\n"); #ifdef HAVE_LIBREADLINE printf("Includes libreadline, GPLv2.\n"); #endif const char* cmdPath = DEFAULT_CMD_PATH; if (argc!=1) { cmdPath = argv[1]; } char rspPath[200]; sprintf(rspPath,"/tmp/OpenBTS-UMTS.console.%d.%8lx",getpid(),time(NULL)); printf("command socket path is %s\n", cmdPath); char prompt[strlen(cmdPath) + 20]; sprintf(prompt,"OpenBTS-UMTS> "); // the socket int sock = socket(AF_UNIX,SOCK_DGRAM,0); if (sock<0) { perror("opening datagram socket"); exit(1); } // destination address struct sockaddr_un cmdSockName; cmdSockName.sun_family = AF_UNIX; strcpy(cmdSockName.sun_path,cmdPath); // locally bound address struct sockaddr_un rspSockName; rspSockName.sun_family = AF_UNIX; char rmcmd[strlen(rspPath)+10]; sprintf(rmcmd,"rm -f %s",rspPath); system(rmcmd); strcpy(rspSockName.sun_path,rspPath); if (bind(sock, (struct sockaddr *) &rspSockName, sizeof(struct sockaddr_un))) { perror("binding name to datagram socket"); exit(1); } printf("response socket bound to %s\n",rspSockName.sun_path); #ifdef HAVE_LIBREADLINE // start console using_history(); static const char * const history_file_name = "/.openbts-umts_history"; char *history_name = 0; char *home_dir = getenv("HOME"); if(home_dir) { size_t home_dir_len = strlen(home_dir); size_t history_file_len = strlen(history_file_name); size_t history_len = home_dir_len + history_file_len + 1; if(history_len > home_dir_len) { if(!(history_name = (char *)malloc(history_len))) { perror("malloc failed"); exit(2); } memcpy(history_name, home_dir, home_dir_len); memcpy(history_name + home_dir_len, history_file_name, history_file_len + 1); read_history(history_name); } } #endif printf("Remote Interface Ready.\nType:\n \"help\" to see commands,\n \"version\" for version information,\n \"notices\" for licensing information.\n \"quit\" to exit console interface\n"); while (1) { #ifdef HAVE_LIBREADLINE char *cmd = readline(prompt); if (!cmd) break; if (*cmd) add_history(cmd); #else // HAVE_LIBREADLINE printf("%s",prompt); fflush(stdout); char *inbuf = (char*)malloc(200); char *cmd = fgets(inbuf,199,stdin); if (!cmd) continue; // strip trailing CR cmd[strlen(cmd)-1] = '\0'; #endif // local quit? if (strcmp(cmd,"quit")==0) { printf("closing remote console\n"); break; } // shell escape? if (cmd[0]=='!') { system(cmd+1); continue; } // use the socket if (sendto(sock,cmd,strlen(cmd)+1,0,(struct sockaddr*)&cmdSockName,sizeof(cmdSockName))<0) { perror("sending datagram"); printf("Is the remote application running?\n"); continue; } free(cmd); const int bufsz = 100000; char resbuf[bufsz]; int nread = recv(sock,resbuf,bufsz-1,0); if (nread<0) { perror("receiving response"); continue; } resbuf[nread] = '\0'; printf("%s\n",resbuf); if (nread==(bufsz-1)) printf("(response truncated at %d characters)\n",nread); } #ifdef HAVE_LIBREADLINE if(history_name) { int e = write_history(history_name); if(e) { fprintf(stderr, "error: history: %s\n", strerror(e)); } free(history_name); history_name = 0; } #endif close(sock); // Delete the path to limit clutter in /tmp. sprintf(rmcmd,"rm -f %s",rspPath); system(rmcmd); }