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