phy_init_lte_ue_signal was renamed init_lte_ue_signal in openair1/PHY/INIT/defs.h maybe it's the opposite that should have been done? Functions used in one file and defined in another may have been declared in the wrong header file.
377 lines
8.3 KiB
C
377 lines
8.3 KiB
C
/*
|
|
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
|
* contributor license agreements. See the NOTICE file distributed with
|
|
* this work for additional information regarding copyright ownership.
|
|
* The OpenAirInterface Software Alliance licenses this file to You under
|
|
* the OAI Public License, Version 1.0 (the "License"); you may not use this file
|
|
* except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.openairinterface.org/?page_id=698
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*-------------------------------------------------------------------------------
|
|
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
|
* contact@openairinterface.org
|
|
*/
|
|
|
|
/*! \file cli.c
|
|
* \brief oai main cli core
|
|
* \author Navid Nikaein
|
|
* \date 2011 - 2014
|
|
* \version 0.1
|
|
* \warning This component can be runned only in user-space
|
|
* @ingroup util
|
|
|
|
*/
|
|
|
|
|
|
#include <unistd.h>
|
|
#include <signal.h>
|
|
#include <sys/types.h>
|
|
#include <sys/socket.h>
|
|
#include <sys/wait.h>
|
|
#include <ctype.h>
|
|
|
|
#include "cli.h"
|
|
|
|
extern cli_config *cli_cfg;
|
|
|
|
|
|
|
|
command commands[] = {
|
|
{0, "help",NULL,com_help, NULL,"Display this text" },
|
|
{0, "?",NULL,com_help, NULL, "help at any point" },
|
|
{2, "prompt",NULL,prompt, prompt_usage,"Set/get cli prompt" },
|
|
{2, "info",NULL,info, NULL,"get software information" },
|
|
{1, "start",NULL,start, start_usage,"Start eNB/UE instance" },
|
|
{1, "set",NULL,set, set_usage,"set log for a give component" },
|
|
{0, "exit",NULL,com_exit, NULL,"Exit using OpenAir CLI Interface" },
|
|
{0, (char *)NULL,NULL, NULL,NULL, (char *)NULL }
|
|
};
|
|
|
|
|
|
static uid_t real_uid;
|
|
void priv_init(void)
|
|
{
|
|
real_uid = getuid();
|
|
}
|
|
|
|
void priv_up(void)
|
|
{
|
|
if (seteuid(0) != 0) {
|
|
printf("[CLI] Error setting uid to %d\n", real_uid);
|
|
}
|
|
}
|
|
|
|
void priv_down(void)
|
|
{
|
|
if (seteuid(real_uid) != 0) {
|
|
printf("[CLI] Error setting uid to %d\n", 0);
|
|
}
|
|
}
|
|
|
|
int cli_start(void)
|
|
{
|
|
|
|
priv_init();
|
|
|
|
priv_down();
|
|
putenv("REMADDR=");
|
|
|
|
// get username
|
|
if ((username = getlogin()) == NULL) {
|
|
username = getenv("USER");
|
|
}
|
|
|
|
set_permissions_map();
|
|
|
|
// set login info
|
|
cli_login(username, CLI_MAX_NODES, CLI_MAX_CMDS);
|
|
// send welcome msg to the client
|
|
sprintf(buffer, "%s", WELCOME_MSG);
|
|
send(cli_cfg->cfd, buffer, strlen(buffer), 0);
|
|
|
|
printf(WELCOME_MSG);
|
|
printf("[CLI] started...\n");
|
|
sprintf(cli_cfg->prompt,"%s%c ", cli_prompt(), cli_cfg->promptchar);
|
|
send(cli_cfg->cfd,cli_cfg->prompt, strlen(cli_cfg->prompt), 0);
|
|
return 1;
|
|
}
|
|
|
|
|
|
int cli_loop(char * msg)
|
|
{
|
|
|
|
char *s;
|
|
|
|
/* Remove leading and trailing whitespace from the line.
|
|
Then, if there is anything left, add it to the history list
|
|
and execute it. */
|
|
s = stripwhite(msg);
|
|
|
|
if (*s) {
|
|
//add_history(s);
|
|
execute_line(s);
|
|
}
|
|
|
|
send(cli_cfg->cfd, cli_cfg->prompt, strlen(cli_cfg->prompt), 0);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/**
|
|
* The permissions map is a bit map which defines which modes are available
|
|
* to a user. The permissions groups map to linux groups in the following
|
|
* way: subtract 1000. The remainder is the bit number.
|
|
* Thus unix groups 1000, 1001, 1002 etc represent the permissions groups
|
|
* default, config and admin respectively.
|
|
*
|
|
*/
|
|
int set_permissions_map(void)
|
|
{
|
|
gid_t group[10];
|
|
int n, i;
|
|
int perm_num;
|
|
// get the number of supplementary group IDs
|
|
n = getgroups(10, group);
|
|
|
|
// give show permissions even if user has none
|
|
map_permissions = ADMIN_PERMISSION;
|
|
|
|
for (i=0; i<n; i++) {
|
|
perm_num = group[i] - 1000;
|
|
|
|
if (perm_num < 0 || perm_num > 31) {
|
|
continue;
|
|
}
|
|
|
|
//map_permissions |= (1 << perm_num);
|
|
map_permissions |= ((1 << (perm_num+1)) - 1);
|
|
}
|
|
|
|
printf("[CLI] Permissions %04x for this session\n", map_permissions);
|
|
return 0;
|
|
}
|
|
|
|
|
|
int cli_login(const char *username, int maxnodes, int maxcmds)
|
|
{
|
|
|
|
cli_set_prompt_char();
|
|
|
|
printf("[CLI] Client initialised\n");
|
|
|
|
// log the connection
|
|
// telnets use REMADDR
|
|
host = getenv("REMADDR");
|
|
|
|
if (host) {
|
|
snprintf(g_sid, MAX_SID, "%s#%s", username, host);
|
|
printf("[CLI] login via telnet by user %s from address %s\n", username, host);
|
|
} else {
|
|
host = getenv("SSH_CLIENT");
|
|
|
|
if (host) {
|
|
char *cp;
|
|
// format is <rem_addr> <rem_port> <local_port>
|
|
// replace first space with ':', second terminates the string
|
|
cp = strchr(host, ' ');
|
|
|
|
if (cp) {
|
|
*cp = ':';
|
|
}
|
|
|
|
cp = strchr(host, ' ');
|
|
|
|
if (cp) {
|
|
*cp = '\0';
|
|
}
|
|
|
|
snprintf(g_sid, MAX_SID, "%s$%s", username, host);
|
|
printf("[CLI] login via SSH by user %s from address %s", username, host);
|
|
} else {
|
|
host = getenv("HOST");
|
|
|
|
if (host) {
|
|
snprintf(g_sid, MAX_SID, "%s$%s", username, host);
|
|
printf("[CLI] by user %s from host %s", username, host);
|
|
} else {
|
|
printf("[CLI]Login by user %s from unknown destination\n", username);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
//register an exit function
|
|
atexit(cli_finish);
|
|
return 0;
|
|
}
|
|
|
|
char *cli_prompt(void)
|
|
{
|
|
static char promptstr[256];
|
|
promptstr[0]='\0';
|
|
snprintf(promptstr, 200,"%s@%s",username, cli_cfg->prompt);
|
|
return promptstr;
|
|
}
|
|
|
|
int cli_set_prompt_char(void)
|
|
{
|
|
if (map_permissions & ADMIN_PERMISSION) {
|
|
cli_cfg->promptchar = '#';
|
|
} else if (map_permissions & CONFIG_PERMISSION) {
|
|
cli_cfg->promptchar = '%';
|
|
} else if (map_permissions & SHOW_PERMISSION) {
|
|
cli_cfg->promptchar = '$';
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void cli_finish(void)
|
|
{
|
|
char *cp;
|
|
|
|
if ((cp = strchr(g_sid, '#'))) {
|
|
*cp = '\0';
|
|
printf("[CLI] logout via telnet by user %s from address %s\n", g_sid, cp+1);
|
|
} else if ((cp = strchr(g_sid, '$'))) {
|
|
*cp = '\0';
|
|
printf("[CLI] logout via SSH by user %s from address %s\n", g_sid, cp+1);
|
|
} else {
|
|
printf("[CLI] logout from %s\n", g_sid);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
/* Execute a command line. */
|
|
int execute_line (char *line)
|
|
{
|
|
register int i;
|
|
command *command;
|
|
char *word;
|
|
|
|
/* Isolate the command word. */
|
|
i = 0;
|
|
|
|
while (line[i] && whitespace (line[i]))
|
|
i++;
|
|
|
|
word = line + i;
|
|
|
|
while (line[i] && !whitespace (line[i]))
|
|
i++;
|
|
|
|
if (line[i])
|
|
line[i++] = '\0';
|
|
|
|
command = find_command(word);
|
|
|
|
if (!command) {
|
|
sprintf(buffer, "%s: %s \n", word, NOCOMMAND_MSG);
|
|
send(cli_cfg->cfd, buffer, strlen(buffer), 0);
|
|
printf("[CLI] commnad %s does not exist !\n", word);
|
|
return (-1);
|
|
}
|
|
|
|
/* Get argument to command, if any. */
|
|
while (whitespace (line[i]))
|
|
i++;
|
|
|
|
word = line + i;
|
|
|
|
/* Call the function. */
|
|
return ((*(command->func)) (word));
|
|
}
|
|
|
|
/* Look up NAME as the name of a command, and return a pointer to that
|
|
command. Return a NULL pointer if NAME isn't a command name. */
|
|
command * find_command (char *name)
|
|
{
|
|
register int i;
|
|
|
|
for (i = 0; commands[i].name; i++) {
|
|
if (strcmp (name, commands[i].name) == 0)
|
|
return (&commands[i]);
|
|
}
|
|
|
|
return ((command *)NULL);
|
|
}
|
|
|
|
/* Strip whitespace from the start and end of STRING. Return a pointer
|
|
into STRING. */
|
|
char * stripwhite (char *string)
|
|
{
|
|
register char *s, *t;
|
|
|
|
for (s = string; whitespace (*s); s++)
|
|
;
|
|
|
|
if (*s == 0)
|
|
return (s);
|
|
|
|
t = s + strlen (s) - 1;
|
|
|
|
while (t > s && whitespace (*t))
|
|
t--;
|
|
|
|
*++t = '\0';
|
|
|
|
return s;
|
|
}
|
|
|
|
|
|
/* Generator function for command completion. STATE lets us know whether
|
|
to start from scratch; without any state (i.e. STATE == 0), then we
|
|
start at the top of the list. */
|
|
|
|
|
|
/* Print out help for ARG, or for all of the commands if ARG is
|
|
not present. */
|
|
int com_help (char *arg)
|
|
{
|
|
register int i;
|
|
int printed = 0;
|
|
|
|
for (i = 0; commands[i].name != NULL; i++) {
|
|
// if (!*arg || (strcmp (arg, commands[i].name) == 0)){
|
|
sprintf (buffer,"%s\t\t<%s>\n", commands[i].name, commands[i].doc);
|
|
send(cli_cfg->cfd, buffer, strlen(buffer), 0);
|
|
printed++;
|
|
// }
|
|
}
|
|
|
|
if (!printed) {
|
|
printf("No commands match `%s'. Possibilties are:\n", arg);
|
|
|
|
for (i = 0; commands[i].name; i++) {
|
|
/* Print in six columns. */
|
|
if (printed == 6) {
|
|
printed = 0;
|
|
printf("\n");
|
|
}
|
|
|
|
printf("%s\t", commands[i].name);
|
|
printed++;
|
|
}
|
|
|
|
if (printed)
|
|
printf("\n");
|
|
}
|
|
|
|
return (0);
|
|
}
|
|
|
|
int whitespace (char c)
|
|
{
|
|
|
|
return (isspace((int)c));
|
|
}
|