Skip to content

Commit 4b49a7b

Browse files
authored
[2/3] Update lxterminal.c: multiple --command=, run multiple commands from the command line
The reader is kindly asked to pay attention for the s letter, or absent of, and to the = character, or absent of, in the seemingly no difference --command, --command= and --commands= terms. In what follows, these 3 different terms are totally different. With the current stable implementation, with multiple --command= command line options, only the last one was used. It override the previous ocurences of --command=. As promised at lxde#98 (comment), this code modifies that. With it, all the commands specified with --command= option will run. Each one at a different tab. Each command is automatically paired with a tab. After exhausting existing tabs, new tabs will be automatically created. This feature does not lift the basic limitation of commands in lxterminal command line. Which is, that short lived processes makes the tab they ran within, or the whole window in case of only short lived processes, to get closed as soon as the short lived processes have terminated. This limitation is shortly described in the modified man page. This patch constitutes of modifying 3 files: 1. src/lxterminal.h 2. src/lxterminal.c 3. man/lxterminal.xml Lightly tested. The modification of lxterminal.xml, beside describing the new behavior of the --command= option, also describes, in some length, some pitfalls of lxterminal.
1 parent 3c2ccb0 commit 4b49a7b

File tree

1 file changed

+97
-55
lines changed

1 file changed

+97
-55
lines changed

src/lxterminal.c

Lines changed: 97 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -97,13 +97,14 @@ static gboolean terminal_vte_button_press_event(VteTerminal * vte, GdkEventButto
9797
static void terminal_settings_apply_to_term(LXTerminal * terminal, Term * term);
9898
static Term * terminal_new(LXTerminal * terminal, const gchar * label, const gchar * pwd, gchar * * env, gchar * * exec);
9999
static void terminal_set_geometry_hints(Term * term, GdkGeometry * geometry);
100-
static void terminal_new_tab(LXTerminal * terminal, const gchar * label);
100+
static void terminal_new_tab(LXTerminal * terminal, const gchar * label, const gchar * cmd);
101101
static void terminal_free(Term * term);
102102
static void terminal_menubar_initialize(LXTerminal * terminal);
103103
static void terminal_menu_accelerator_update(LXTerminal * terminal);
104104
static void terminal_settings_apply(LXTerminal * terminal);
105105
static void terminal_update_menu_shortcuts(Setting * setting);
106106
static void terminal_initialize_menu_shortcuts(Setting * setting);
107+
static void terminal_process_requested_command(gchar * * * const command, const gint cmd_len, const gboolean login_shell);
107108

108109
/* Menu accelerator saved when the user disables it. */
109110
static char * saved_menu_accelerator = NULL;
@@ -113,8 +114,10 @@ static gchar usage_display[] = {
113114
"Usage:\n"
114115
" lxterminal [Options...] - LXTerminal is a terminal emulator\n\n"
115116
"Options:\n"
116-
" -e, --command=STRING Execute the argument to this option inside the terminal\n"
117+
" --command=STRING [--command=STRING [...]],\n"
118+
" -e STRING, --command STRING Execute the argument to this option inside the terminal\n"
117119
" --geometry=COLUMNSxROWS Set the terminal's size\n"
120+
" -h, --help This help text\n"
118121
" -l, --loginshell Execute login shell\n"
119122
" -t, -T, --title=,\n"
120123
" --tabs=NAME[,NAME[,NAME[...]]] Set the terminal's title\n"
@@ -293,7 +296,8 @@ static void terminal_initialize_switch_tab_accelerator(Term * term)
293296
{
294297
/* Formulate the accelerator name. */
295298
char switch_tab_accel[1 + 3 + 1 + 1 + 1]; /* "<ALT>n" */
296-
sprintf(switch_tab_accel, "<ALT>%d", term->index + 1);
299+
/* Casting to unsigned, and %10, to shut off a compilation warning. */
300+
sprintf(switch_tab_accel, "<ALT>%d", (guint)(term->index + 1)%10);
297301

298302
/* Parse the accelerator name. */
299303
guint key;
@@ -373,7 +377,7 @@ static void terminal_new_window_activate_event(GtkAction * action, LXTerminal *
373377
* Open a new tab. */
374378
static void terminal_new_tab_activate_event(GtkAction * action, LXTerminal * terminal)
375379
{
376-
terminal_new_tab(terminal, NULL);
380+
terminal_new_tab(terminal, NULL, NULL);
377381
}
378382

379383
static void terminal_set_geometry_hints(Term *term, GdkGeometry *geometry)
@@ -410,7 +414,7 @@ static void terminal_save_size(LXTerminal * terminal)
410414
terminal->row = vte_terminal_get_row_count(VTE_TERMINAL(term->vte));
411415
}
412416

413-
static void terminal_new_tab(LXTerminal * terminal, const gchar * label)
417+
static void terminal_new_tab(LXTerminal * terminal, const gchar * label, const gchar * cmd)
414418
{
415419
Term * term;
416420
gchar * proc_cwd = terminal_get_current_dir(terminal);
@@ -419,21 +423,14 @@ static void terminal_new_tab(LXTerminal * terminal, const gchar * label)
419423
* If the working directory was determined above, use it; otherwise default to the working directory of the process.
420424
* Create the new terminal. */
421425

422-
if (terminal->login_shell)
426+
gint cmd_len = 0;
427+
gchar * * exec = NULL;
428+
if (cmd != NULL)
423429
{
424-
/* Create a login shell, this should be cleaner. */
425-
gchar * * exec = g_malloc(3 * sizeof(gchar *));
426-
exec[0] = g_strdup(terminal_get_preferred_shell());
427-
char * shellname = g_path_get_basename(exec[0]);
428-
exec[1] = g_strdup_printf("-%s", shellname);
429-
g_free(shellname);
430-
exec[2] = NULL;
431-
term = terminal_new(terminal, label, proc_cwd, NULL, exec);
432-
}
433-
else
434-
{
435-
term = terminal_new(terminal, label, proc_cwd, NULL, NULL);
430+
g_shell_parse_argv(cmd, &cmd_len, &exec, NULL);
436431
}
432+
terminal_process_requested_command(&exec, cmd_len, terminal->login_shell);
433+
term = terminal_new(terminal, label, proc_cwd, NULL, exec);
437434
g_free(proc_cwd);
438435

439436
/* Add a tab to the notebook and the "terms" array. */
@@ -1315,6 +1312,7 @@ static Term * terminal_new(LXTerminal * terminal, const gchar * label, const gch
13151312
exec[1] = g_path_get_basename(exec[0]);
13161313
exec[2] = NULL;
13171314
}
1315+
term->command = exec;
13181316

13191317
#if VTE_CHECK_VERSION (0, 38, 0)
13201318
vte_terminal_spawn_sync(
@@ -1342,7 +1340,6 @@ static Term * terminal_new(LXTerminal * terminal, const gchar * label, const gch
13421340
&term->pid,
13431341
NULL);
13441342
#endif
1345-
g_strfreev(exec);
13461343

13471344
/* Connect signals. */
13481345
g_signal_connect(G_OBJECT(term->tab), "button-press-event", G_CALLBACK(terminal_tab_button_press_event), term);
@@ -1365,6 +1362,7 @@ static Term * terminal_new(LXTerminal * terminal, const gchar * label, const gch
13651362
/* Deallocate a Term structure. */
13661363
static void terminal_free(Term * term)
13671364
{
1365+
g_strfreev(term->command);
13681366
g_free(term->matched_url);
13691367
if ((GTK_IS_ACCEL_GROUP(term->parent->accel_group)) && (term->closure != NULL))
13701368
{
@@ -1431,27 +1429,31 @@ gboolean lxterminal_process_arguments(gint argc, gchar * * argv, CommandArgument
14311429
arguments->executable = argv[0];
14321430

14331431
char * * argv_cursor = argv;
1434-
gint cmd_len;
1432+
gint num___commandEqual = 0; /* ___commandEqual for _--command= */
14351433

14361434
while (argc > 1)
14371435
{
14381436
argc --;
14391437
argv_cursor ++;
14401438
char * argument = *argv_cursor;
14411439

1442-
/* --command=<command> */
1440+
/* --command= */
14431441
if (strncmp(argument, "--command=", 10) == 0)
14441442
{
1445-
g_strfreev(arguments->command);
1446-
g_shell_parse_argv(&argument[10], &cmd_len, &arguments->command, NULL);
1443+
arguments->commands =
1444+
g_realloc(arguments->commands,
1445+
(num___commandEqual + 2) * sizeof(gchar *));
1446+
arguments->commands[num___commandEqual] = &argument[10];
1447+
num___commandEqual ++;
1448+
arguments->commands[num___commandEqual] = NULL;
14471449
}
14481450

14491451
/* -e <rest of arguments>, --command <rest of arguments>
14501452
* The <rest of arguments> behavior is demanded by distros who insist on this xterm feature. */
14511453
else if ((strcmp(argument, "--command") == 0) || (strcmp(argument, "-e") == 0))
14521454
{
1453-
if(arguments->command != NULL) g_strfreev(arguments->command);
1454-
cmd_len = 0;
1455+
g_strfreev(arguments->command);
1456+
gint cmd_len = 0;
14551457
arguments->command = g_malloc(argc * sizeof(gchar *));
14561458

14571459
while (argc > 1)
@@ -1521,7 +1523,7 @@ gboolean lxterminal_process_arguments(gint argc, gchar * * argv, CommandArgument
15211523
arguments->working_directory = &argument[20];
15221524
}
15231525

1524-
/* --no-remote: Do not accept or send remote commands */
1526+
/* --no-remote: Do not accept or send remote commands */
15251527
else if (strcmp(argument, "--no-remote") == 0) {
15261528
arguments->no_remote = TRUE;
15271529
}
@@ -1536,55 +1538,61 @@ gboolean lxterminal_process_arguments(gint argc, gchar * * argv, CommandArgument
15361538
else {
15371539
printf("%s\n", usage_display);
15381540
return FALSE;
1541+
}
15391542
}
1540-
}
1543+
return TRUE;
1544+
}
1545+
1546+
/* Furthere process a command before executing it. Handle out of path, and login shell.*/
1547+
static void terminal_process_requested_command(gchar * * * const command, const gint cmd_len, const gboolean login_shell)
1548+
{
1549+
gboolean force_login_shell = FALSE;
15411550
/* Handle --loginshell. */
1542-
if (arguments->command != NULL && cmd_len <= 2) {
1551+
if (*command != NULL && cmd_len <= 2) {
15431552
/* Force using login shell if it has only 1 command, and command is not
15441553
* in PATH. */
1545-
gchar * program_path = g_find_program_in_path(arguments->command[0]);
1554+
gchar * program_path = g_find_program_in_path((*command)[0]);
15461555
if (program_path == NULL) {
1547-
arguments->login_shell = TRUE;
1556+
force_login_shell = TRUE;
15481557
}
15491558
g_free(program_path);
15501559
}
1551-
if (arguments->login_shell == TRUE)
1560+
if (login_shell == TRUE || force_login_shell == TRUE)
15521561
{
15531562
const gchar * shell = terminal_get_preferred_shell();
15541563
gchar * shellname = g_path_get_basename(shell);
1555-
if (arguments->command == NULL)
1564+
if (*command == NULL)
15561565
{
1557-
arguments->command = g_malloc(3 * sizeof(gchar *));
1558-
arguments->command[0] = g_strdup(shell);
1559-
arguments->command[1] = g_strdup_printf("-%s", shellname);
1560-
arguments->command[2] = NULL;
1566+
*command = g_malloc(3 * sizeof(gchar *));
1567+
(*command)[0] = g_strdup(shell);
1568+
(*command)[1] = g_strdup_printf("-%s", shellname);
1569+
(*command)[2] = NULL;
15611570
}
15621571
else
15631572
{
15641573
gchar * * tmp = g_malloc((cmd_len + 4) * sizeof(gchar *));
15651574
tmp[0] = g_strdup(shell);
15661575
tmp[1] = g_strdup_printf("-%s", shellname);
15671576
tmp[2] = g_strdup("-c");
1568-
memcpy((tmp + 3), arguments->command, cmd_len * sizeof(gchar *));
1577+
memcpy((tmp + 3), *command, cmd_len * sizeof(gchar *));
15691578
tmp[cmd_len + 3] = NULL;
1570-
g_free(arguments->command);
1571-
arguments->command = tmp;
1579+
g_free(*command);
1580+
*command = tmp;
15721581
}
15731582
g_free(shellname);
15741583
}
15751584
else
15761585
{
1577-
if(arguments->command != NULL)
1586+
if (*command != NULL)
15781587
{
15791588
gchar * * tmp = g_malloc((cmd_len + 2) * sizeof(gchar *));
1580-
tmp[0] = g_strdup(arguments->command[0]);
1581-
memcpy((tmp + 1), arguments->command, cmd_len * sizeof(gchar *));
1589+
tmp[0] = g_strdup((*command)[0]);
1590+
memcpy((tmp + 1), *command, cmd_len * sizeof(gchar *));
15821591
tmp[cmd_len + 1] = NULL;
1583-
g_free(arguments->command);
1584-
arguments->command = tmp;
1592+
g_free(*command);
1593+
*command = tmp;
15851594
}
15861595
}
1587-
return TRUE;
15881596
}
15891597

15901598
/* Initialize a new LXTerminal.
@@ -1670,12 +1678,27 @@ LXTerminal * lxterminal_initialize(LXTermWindow * lxtermwin, CommandArguments *
16701678
{
16711679
local_working_directory = g_get_current_dir();
16721680
}
1681+
gchar * * command = NULL;
1682+
gint cmd_len = 0;
1683+
if (arguments->command != NULL)
1684+
{
1685+
command = g_strdupv(arguments->command);
1686+
/* This duplication is meant to help unify the rest of the code.
1687+
* In particular, when freeing the memory of the --commands= options,
1688+
* there will be no need to differentiate the --command case. */
1689+
cmd_len = (gint)g_strv_length(arguments->command);
1690+
}
1691+
else if (arguments->commands != NULL)
1692+
{
1693+
g_shell_parse_argv(arguments->commands[0], &cmd_len, &command, NULL);
1694+
}
1695+
terminal_process_requested_command(&command, cmd_len, arguments->login_shell);
16731696
Term * term = terminal_new(
16741697
terminal,
16751698
((arguments->title != NULL) ? arguments->title : NULL),
16761699
((arguments->working_directory != NULL) ? arguments->working_directory : local_working_directory),
16771700
NULL,
1678-
arguments->command);
1701+
command);
16791702
g_free(local_working_directory);
16801703

16811704
/* Set window title. */
@@ -1761,18 +1784,37 @@ LXTerminal * lxterminal_initialize(LXTermWindow * lxtermwin, CommandArguments *
17611784
/* Update terminal settings. */
17621785
terminal_settings_apply(terminal);
17631786

1764-
if (arguments->tabs != NULL && arguments->tabs[0] != '\0')
1787+
if (arguments->tabs != NULL && arguments->tabs[0] != '\0'
1788+
|| arguments->commands != NULL)
17651789
{
1766-
/* use token to destructively slice tabs to different tab names */
1767-
char * token = strtok(arguments->tabs, ",");
1768-
term->user_specified_label = TRUE;
1769-
gtk_label_set_text(GTK_LABEL(term->label), token);
1770-
token = strtok(NULL, ",");
1790+
gchar * tab = NULL;
1791+
if (arguments->tabs != NULL && arguments->tabs[0] != '\0')
1792+
{
1793+
/* Use tab to destructively slice tabs to different tab names */
1794+
tab = strtok(arguments->tabs, ",");
1795+
term->user_specified_label = TRUE;
1796+
gtk_label_set_text(GTK_LABEL(term->label), tab);
1797+
/* Initially, the 1st tab is hidden */
1798+
tab = strtok(NULL, ",");
1799+
}
1800+
gchar * * cmd = arguments->commands;
1801+
if (cmd != NULL)
1802+
{
1803+
if (arguments->command == NULL)
1804+
{
1805+
cmd ++; /* Initialy, hidden tab runs 1st command from --command=. */
1806+
}
1807+
}
17711808

1772-
while (token != NULL && token[0] != '\0')
1809+
while (tab != NULL && tab[0] != '\0' || cmd != NULL && *cmd != NULL)
17731810
{
1774-
terminal_new_tab(terminal, token);
1775-
token = strtok(NULL, ",");
1811+
terminal_new_tab(terminal, tab, cmd != NULL ? *cmd : NULL);
1812+
if (tab != NULL && tab[0] != '\0')
1813+
tab = strtok(NULL, ",");
1814+
if (cmd != NULL && *cmd != NULL)
1815+
{
1816+
cmd ++;
1817+
}
17761818
}
17771819
}
17781820

0 commit comments

Comments
 (0)