1 // SPDX-License-Identifier: GPL-2.0-only or License-Ref-kk-custom
2 /*
3  * Copyright (C) 2020 Kernkonzept GmbH.
4  * Author(s): Adam Lackorzynski <adam.lackorzynski@kernkonzept.com>
5  *            Sarah Hoffmann <sarah.hoffmann@kernkonzept.com>
6  *
7  * This file is distributed under the terms of the GNU General Public
8  * License, version 2.  Please see the COPYING-GPL-2 file for details.
9  */
10 
11 /**
12  *
13  * A command line prompt using ned's server interface.
14  *
15  * Usage: ned-prompt [<prompt>]
16  *
17  * The capability to the ned server is expected under the name srv.
18  * Optionally a different prompt than 'Cmd>' may be set via the command
19  * line.
20  */
21 
22 #include <cstdio>
23 #include <cstdlib>
24 
25 #include <readline/history.h>
26 #include <readline/readline.h>
27 
28 #include <l4/ned/cmd_control>
29 #include <l4/re/env>
30 #include <l4/re/error_helper>
31 
32 /**
33  * Add a line to the readline history.
34  *
35  * This function mimicks the 'ignoreboth' HISTCONTROL setting.
36  */
add_to_history(char * line)37 static void add_to_history(char *line)
38 {
39   if (line[0] == ' ')
40     return;
41 
42   HIST_ENTRY **hist_list = history_list();
43   if (hist_list)
44     {
45       HIST_ENTRY *hist = hist_list[history_length - 1];
46       if (hist && strcmp(line, hist->line) == 0)
47         return;
48     }
49 
50   add_history(line);
51 }
52 
run_cmds(char const * prompt)53 static void run_cmds(char const* prompt)
54 {
55   char fullprompt[64];
56 
57   snprintf(fullprompt, sizeof(fullprompt), "%s ", prompt);
58 
59   using L4Re::Ned::Cmd_control;
60   auto srv = L4Re::chkcap(L4Re::Env::env()->get_cap<Cmd_control>("svr"),
61                           "Searching ned command capability 'svr'");
62 
63   for (;;)
64     {
65       char *cmd;
66       do
67         {
68          cmd = readline(fullprompt);
69         }
70       while (!cmd);
71 
72       if (*cmd)
73         {
74           char buffer[L4_UTCB_GENERIC_DATA_SIZE * sizeof(l4_umword_t)];
75           L4::Ipc::String<> c(cmd);
76           L4::Ipc::String<char> result(sizeof(buffer), buffer);
77           int e = srv->execute(c, &result);
78           if (e < 0)
79             printf("Error calling ned: %d\n", e);
80           else if (result.length != 3 || strncmp("nil", result.data, 3) != 0)
81             printf("%.*s\n", (int)result.length, result.data);
82           add_to_history(cmd);
83         }
84 
85       free(cmd);
86     }
87 }
88 
main(int argc,char * argv[])89 int main(int argc, char *argv[])
90 {
91   printf("Welcome to ned prompt.\n");
92   try
93     {
94       run_cmds(argc < 2 ? "Cmd>" : argv[1]);
95     }
96   catch (L4::Runtime_error &e)
97     {
98       printf("%s: %s\n", e.str(), e.extra_str());
99       return 1;
100     }
101 
102   return 0;
103 }
104