Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:19

0001 /**
0002  * @file
0003  * 
0004  * @brief Shell Command Set Management
0005  */
0006 
0007 /*
0008  * Copyright (c) 2001 Fernando Ruiz Casas <fruizcasas@gmail.com>
0009  *
0010  *  The license and distribution terms for this file may be
0011  *  found in the file LICENSE in this distribution or at
0012  *  http://www.rtems.org/license/LICENSE.
0013  */
0014 
0015 #ifdef HAVE_CONFIG_H
0016 #include "config.h"
0017 #endif
0018 
0019 #include <stdio.h>
0020 #include <time.h>
0021 #include <termios.h>
0022 #include <string.h>
0023 #include <stdlib.h>
0024 #include <ctype.h>
0025 #include <sys/stat.h>
0026 #include <unistd.h>
0027 #include <errno.h>
0028 
0029 
0030 #include <rtems.h>
0031 #include <rtems/shell.h>
0032 #include <rtems/shellconfig.h>
0033 #include <rtems/libio_.h>
0034 #include "internal.h"
0035 
0036 /*
0037  * Common linked list of shell commands.
0038  *
0039  * Because the help report is very long, there is a topic for each command.
0040  *
0041  * Help list the topics
0042  *   help [topic] list the commands for the topic
0043  *   help [command] help for the command
0044  *
0045  */
0046 
0047 rtems_shell_cmd_t   * rtems_shell_first_cmd;
0048 rtems_shell_topic_t * rtems_shell_first_topic;
0049 
0050 /*
0051  *  Find the topic from the set of topics registered.
0052  */
0053 rtems_shell_topic_t * rtems_shell_lookup_topic(const char * topic) {
0054   rtems_shell_topic_t * shell_topic;
0055   shell_topic=rtems_shell_first_topic;
0056 
0057   while (shell_topic) {
0058     if (!strcmp(shell_topic->topic,topic))
0059       return shell_topic;
0060     shell_topic=shell_topic->next;
0061   }
0062   return NULL;
0063 }
0064 
0065 /*
0066  *  Add a new topic to the list of topics
0067  */
0068 static rtems_shell_topic_t * rtems_shell_add_topic(const char * topic) {
0069   rtems_shell_topic_t * current,*aux;
0070 
0071   if (!rtems_shell_first_topic) {
0072     aux = malloc(sizeof(rtems_shell_topic_t));
0073     aux->topic = topic;
0074     aux->next  = NULL;
0075     return rtems_shell_first_topic = aux;
0076   }
0077   current=rtems_shell_first_topic;
0078   if (!strcmp(topic,current->topic))
0079     return current;
0080 
0081   while (current->next) {
0082     if (!strcmp(topic,current->next->topic))
0083       return current->next;
0084     current=current->next;
0085   }
0086   aux = malloc(sizeof(rtems_shell_topic_t));
0087   aux->topic = topic;
0088   aux->next = NULL;
0089   current->next = aux;
0090   return aux;
0091 }
0092 
0093 /*
0094  *  Find the command in the set
0095  */
0096 rtems_shell_cmd_t * rtems_shell_lookup_cmd(const char * cmd) {
0097   rtems_shell_cmd_t * shell_cmd;
0098   shell_cmd=rtems_shell_first_cmd;
0099   while (shell_cmd) {
0100    if (!strcmp(shell_cmd->name,cmd)) return shell_cmd;
0101    shell_cmd=shell_cmd->next;
0102   };
0103   return NULL;
0104 }
0105 
0106 /*
0107  *  Add a command structure to the set of known commands
0108  */
0109 rtems_shell_cmd_t *rtems_shell_add_cmd_struct(
0110   rtems_shell_cmd_t *shell_cmd
0111 )
0112 {
0113   rtems_shell_cmd_t **next_ptr = &rtems_shell_first_cmd;
0114   rtems_shell_cmd_t *existing;
0115 
0116   if (shell_cmd == NULL)
0117     return NULL;
0118   if (shell_cmd->name == NULL)
0119     return NULL;
0120 
0121   /*
0122    * Iterate through all commands and check if a command with this name is
0123    * already present.
0124    */
0125   while ((existing = *next_ptr) != NULL) {
0126     if (strcmp(existing->name, shell_cmd->name) == 0)
0127       return NULL;
0128 
0129     next_ptr = &existing->next;
0130   }
0131 
0132   /* Ensure that the user can read and execute commands */
0133   shell_cmd->mode |= S_IRUSR | S_IXUSR;
0134 
0135   /* Append */
0136   *next_ptr = shell_cmd;
0137 
0138   rtems_shell_add_topic( shell_cmd->topic );
0139 
0140   return shell_cmd;
0141 }
0142 
0143 /*
0144  *  Add a command as a set of arguments to the set and
0145  *  allocate the command structure on the fly.
0146  */
0147 rtems_shell_cmd_t * rtems_shell_add_cmd(
0148   const char            *name,
0149   const char            *topic,
0150   const char            *usage,
0151   rtems_shell_command_t  command
0152 )
0153 {
0154   rtems_shell_cmd_t *shell_cmd = NULL;
0155   char *my_name = NULL;
0156   char *my_topic = NULL;
0157   char *my_usage = NULL;
0158 
0159   /* Reject empty commands */
0160   if (name == NULL || command == NULL) {
0161     return NULL;
0162   }
0163 
0164   /* Allocate command stucture */
0165   shell_cmd = (rtems_shell_cmd_t *) calloc(1, sizeof(*shell_cmd));
0166   if (shell_cmd == NULL) {
0167     return NULL;
0168   }
0169 
0170   /* Allocate strings */
0171   my_name  = strdup(name);
0172   my_topic = strdup(topic);
0173   my_usage = strdup(usage);
0174 
0175   /* Assign values */
0176   shell_cmd->name    = my_name;
0177   shell_cmd->topic   = my_topic;
0178   shell_cmd->usage   = my_usage;
0179   shell_cmd->command = command;
0180 
0181   if (rtems_shell_add_cmd_struct(shell_cmd) == NULL) {
0182     /* Something is wrong, free allocated resources */
0183     free(my_usage);
0184     free(my_topic);
0185     free(my_name);
0186     free(shell_cmd);
0187 
0188     return NULL;
0189   }
0190 
0191   return shell_cmd;
0192 }
0193 
0194 /* ----------------------------------------------- *
0195  * you can make an alias for every command.
0196  * ----------------------------------------------- */
0197 rtems_shell_cmd_t *rtems_shell_alias_cmd(
0198   const char *cmd,
0199   const char *alias
0200 )
0201 {
0202   rtems_shell_cmd_t *shell_cmd, *shell_aux;
0203 
0204   shell_aux = (rtems_shell_cmd_t *) NULL;
0205 
0206   if (alias) {
0207     shell_aux = rtems_shell_lookup_cmd(alias);
0208     if (shell_aux != NULL) {
0209       return NULL;
0210     }
0211     shell_cmd = rtems_shell_lookup_cmd(cmd);
0212     if (shell_cmd != NULL) {
0213       shell_aux = rtems_shell_add_cmd(
0214          alias,
0215          shell_cmd->topic,
0216          shell_cmd->usage,
0217          shell_cmd->command
0218       );
0219       if (shell_aux) {
0220         shell_aux->alias = shell_cmd;
0221         shell_aux->mode = shell_cmd->mode;
0222         shell_aux->uid = shell_cmd->uid;
0223         shell_aux->gid = shell_cmd->gid;
0224       }
0225     }
0226   }
0227   return shell_aux;
0228 }
0229 
0230 bool rtems_shell_can_see_cmd(const rtems_shell_cmd_t *shell_cmd)
0231 {
0232   return rtems_filesystem_check_access(
0233     RTEMS_FS_PERMS_READ,
0234     shell_cmd->mode,
0235     shell_cmd->uid,
0236     shell_cmd->gid
0237   );
0238 }
0239 
0240 static bool rtems_shell_can_execute_cmd(const rtems_shell_cmd_t *shell_cmd)
0241 {
0242   return rtems_filesystem_check_access(
0243     RTEMS_FS_PERMS_EXEC,
0244     shell_cmd->mode,
0245     shell_cmd->uid,
0246     shell_cmd->gid
0247   );
0248 }
0249 
0250 int rtems_shell_execute_cmd(const char *cmd, int argc, char *argv[])
0251 {
0252   rtems_shell_cmd_t *shell_cmd;
0253 
0254   if (argv[0] == NULL) {
0255     return -1;
0256   }
0257 
0258   shell_cmd = rtems_shell_lookup_cmd(argv[0]);
0259 
0260   if (shell_cmd != NULL && !rtems_shell_can_see_cmd(shell_cmd)) {
0261     shell_cmd = NULL;
0262   }
0263 
0264   if (shell_cmd == NULL) {
0265     return rtems_shell_script_file(argc, argv);
0266   } else if (rtems_shell_can_execute_cmd(shell_cmd)) {
0267     return shell_cmd->command(argc, argv);
0268   } else {
0269     fprintf(stderr, "%s: Permission denied\n", cmd);
0270 
0271     return -1;
0272   }
0273 }