docs: public void execute(Reader reader) {
  
          try {
              pushShell(this);
              LineNumberReader lnr = new LineNumberReader(reader);
              while (!m_exitCalled) {
                  String line = lnr.readLine();
                  if (m_interactive || m_echo) {
                      // print the prompt in front of the commands to process only when 'interactive'
                      if ((line != null) | m_interactive) {
                          printPrompt();
                      }
                  }
  
                  if (line == null) {
                      // if null the file has been read to the end
                      if (m_interactive) {
                          try {
                              Thread.sleep(500);
                          } catch (Throwable t) {
                              // noop
                          }
                      }
                      // end the while loop
                      break;
                  }
                  if (line.trim().startsWith("#")) {
                      m_out.println(line);
                      continue;
                  }
                  // In linux, the up and down arrows generate escape sequences that cannot be properly handled.
                  // If a escape sequence is detected, OpenCms prints a warning message
                  if (line.indexOf(KeyEvent.VK_ESCAPE) != -1) {
                      m_out.println(m_messages.key(Messages.GUI_SHELL_ESCAPE_SEQUENCES_NOT_SUPPORTED_0));
                      continue;
                  }
                  StringReader lineReader = new StringReader(line);
                  StreamTokenizer st = new StreamTokenizer(lineReader);
                  st.eolIsSignificant(true);
                  st.wordChars('*', '*');
                  // put all tokens into a List
                  List<String> parameters = new ArrayList<String>();
                  while (st.nextToken() != StreamTokenizer.TT_EOF) {
                      if (st.ttype == StreamTokenizer.TT_NUMBER) {
                          parameters.add(Integer.toString(new Double(st.nval).intValue()));
                      } else {
                          if (null != st.sval) {
                              parameters.add(st.sval);
                          }
                      }
                  }
                  lineReader.close();
  
                  if (parameters.size() == 0) {
                      // empty line, just need to check if echo is on
                      if (m_echo) {
                          m_out.println();
                      }
                      continue;
                  }
  
                  // extract command and arguments
                  String command = parameters.get(0);
                  List<String> arguments = parameters.subList(1, parameters.size());
  
                  // execute the command with the given arguments
                  executeCommand(command, arguments);
              }
          } catch (Throwable t) {
              if (!(t instanceof CmsShellCommandException)) {
                  // in case it's a shell command exception, the stack trace has already been written
                  t.printStackTrace(m_err);
              }
              if (m_errorCode != -1) {
                  System.exit(m_errorCode);
              }
          } finally {
              popShell();
          }
      }