1 /**
2  * @file command.c
3  * @author Joe Wingbermuehle
4  * @date 2004-2006
5  *
6  * @brief Handle running startup, shutdown, and restart commands.
7  *
8  */
9 
10 #include "jwm.h"
11 #include "command.h"
12 #include "misc.h"
13 #include "main.h"
14 #include "error.h"
15 
16 /** Structure to represent a list of commands. */
17 typedef struct CommandNode {
18    char *command;             /**< The command. */
19    struct CommandNode *next;  /**< The next command in the list. */
20 } CommandNode;
21 
22 static CommandNode *startupCommands = NULL;
23 static CommandNode *shutdownCommands = NULL;
24 static CommandNode *restartCommands = NULL;
25 
26 static void RunCommands(CommandNode *commands);
27 static void ReleaseCommands(CommandNode **commands);
28 static void AddCommand(CommandNode **commands, const char *command);
29 
30 /** Process startup/restart commands. */
StartupCommands(void)31 void StartupCommands(void)
32 {
33    if(isRestarting) {
34       RunCommands(restartCommands);
35    } else {
36       RunCommands(startupCommands);
37    }
38 }
39 
40 /** Process shutdown commands. */
ShutdownCommands(void)41 void ShutdownCommands(void)
42 {
43    if(!shouldRestart) {
44       RunCommands(shutdownCommands);
45    }
46 }
47 
48 /** Destroy the command lists. */
DestroyCommands(void)49 void DestroyCommands(void)
50 {
51    ReleaseCommands(&startupCommands);
52    ReleaseCommands(&shutdownCommands);
53    ReleaseCommands(&restartCommands);
54 }
55 
56 /** Run the commands in a command list. */
RunCommands(CommandNode * commands)57 void RunCommands(CommandNode *commands) {
58 
59    CommandNode *cp;
60 
61    for(cp = commands; cp; cp = cp->next) {
62       RunCommand(cp->command);
63    }
64 
65 }
66 
67 /** Release a command list. */
ReleaseCommands(CommandNode ** commands)68 void ReleaseCommands(CommandNode **commands)
69 {
70 
71    CommandNode *cp;
72 
73    Assert(commands);
74    while(*commands) {
75       cp = (*commands)->next;
76       Release((*commands)->command);
77       Release(*commands);
78       *commands = cp;
79    }
80 
81 }
82 
83 /** Add a command to a command list. */
AddCommand(CommandNode ** commands,const char * command)84 void AddCommand(CommandNode **commands, const char *command)
85 {
86 
87    CommandNode *cp;
88 
89    Assert(commands);
90    if(!command) {
91       return;
92    }
93 
94    cp = Allocate(sizeof(CommandNode));
95    cp->next = *commands;
96    *commands = cp;
97    cp->command = CopyString(command);
98 
99 }
100 
101 /** Add a startup command. */
AddStartupCommand(const char * command)102 void AddStartupCommand(const char *command)
103 {
104    AddCommand(&startupCommands, command);
105 }
106 
107 /** Add a shutdown command. */
AddShutdownCommand(const char * command)108 void AddShutdownCommand(const char *command) {
109    AddCommand(&shutdownCommands, command);
110 }
111 
112 /** Add a restart command. */
AddRestartCommand(const char * command)113 void AddRestartCommand(const char *command) {
114    AddCommand(&restartCommands, command);
115 }
116 
117 /** Execute an external program. */
RunCommand(const char * command)118 void RunCommand(const char *command)
119 {
120 
121    const char *displayString;
122 
123    if(JUNLIKELY(!command)) {
124       return;
125    }
126 
127    displayString = DisplayString(display);
128    if(!fork()) {
129       close(ConnectionNumber(display));
130       if(displayString && displayString[0]) {
131          const size_t var_len = strlen(displayString) + 9;
132          char *str = malloc(var_len);
133          snprintf(str, var_len, "DISPLAY=%s", displayString);
134          putenv(str);
135       }
136       setsid();
137       execl(SHELL_NAME, SHELL_NAME, "-c", command, NULL);
138       Warning(_("exec failed: (%s) %s"), SHELL_NAME, command);
139       exit(EXIT_SUCCESS);
140    }
141 
142 }
143 
144