-
Notifications
You must be signed in to change notification settings - Fork 1
/
command-line.c
295 lines (262 loc) · 14.6 KB
/
command-line.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
#include "command-line.h"
#include "apps.h"
#include "config.h"
#include <stdlib.h>
static void PrintUsage()
{
printf("\n");
printf("sommelier platforms print list of supported platforms\n");
printf("sommelier categories print list of application categories\n");
printf("sommelier list [options] print list of apps available for install. use -platform option to display apps for a given platform\n");
printf("sommelier install <name> [<name>] [options] install an application by name\n");
printf("sommelier uninstall <name> [<name>] uninstall an application by name\n");
printf("sommelier reconfig <name> [<name>] reconfigure an installed application (seek for executables, re-write desktop file)\n");
printf("sommelier reconfigure <name> [<name>] reconfigure an installed application (seek for executables, re-write desktop file)\n");
printf("sommelier run <name> run an application by name\n");
printf("sommelier winecfg <name> run 'winecfg' for named wine application\n");
printf("sommelier download <name> just download installer/package to current directory\n");
printf("sommelier set <setting string> <name> [<name>] change settings of an installed application\n");
printf("sommelier autostart run programs from ~/.config/autostart\n");
printf("\n");
printf("options are:\n");
printf(" -d print debugging (there will be a lot!)\n");
printf(" -debug print debugging (there will be a lot!)\n");
printf(" -c <config file> specify a config (list of apps) file, rather than using the default\n");
printf(" -url supply an alternative url for an install (this can be an http, https, or ssh url, or just a file path. File paths must be absolute, not relative)\n");
printf(" -install-name <name> Name that program will be installed under and called/run under\n");
printf(" -install-as <name> Name that program will be installed under and called/run under\n");
printf(" -f force install even if expected sha256 doesn't match the download\n");
printf(" -force force install even if expected sha256 doesn't match the download\n");
printf(" -proxy <url> use a proxy for downloading installs\n");
printf(" -platform <platform> platform to use when installing or displaying lists of apps\n");
printf(" -category <category> category to use when displaying lists of apps\n");
printf(" -installed display only installed apps when displaying lists of apps\n");
printf(" -k keep installer or .zip file instead of deleting it after install\n");
printf(" -S install app system-wide under /opt, to be run as a normal native app\n");
printf(" -system install app system-wide under /opt, to be run as a normal native app\n");
printf(" -n <name> specify name to install the app under, allows installing multiple instances of the same app\n");
printf(" -install-name <name> specify name to install the app under, allows installing multiple instances of the same app\n");
printf(" -install-as <name> specify name to install the app under, allows installing multiple instances of the same app\n");
printf(" -emu <emulator> specify a specific emulator to use when installing an app\n");
printf(" -emulator <emulator> specify a specific emulator to use when installing an app\n");
printf(" -icache <dir> installer cache: download installer to directory'dir' and leave it there\n");
printf(" -hash hash downloads even if they have no expected hash value\n");
printf(" -no-xrandr don't use xrandr to reset screen resolution after running and application\n");
printf(" -user-agent <agent string> set user-agent to send when communicating over http\n");
printf(" -ua <agent string> set user-agent to send when communicating over http\n");
printf("\n");
printf("Proxy urls have the form: \n");
printf(" <protocol>:<user>:<password>@<host>:<protocol>. \n");
printf("'protocol' can be 'socks4', 'socks5' 'https' or 'sshtunnel'. For 'sshtunnel' the names defined in the ~/.ssh/config file can be used, so that most of the information can be ommited.\n");
printf("examples:\n");
printf(" https:bill:secret@proxy.com\n");
printf(" socks4:proxy.com:1080\n");
printf(" socks5:bill:secret@proxy.com:1080\n");
printf(" sshtunnel:bill:secret@ssh_host.com\n");
printf(" sshtunnel:sshproxy\n");
printf("\n");
printf("There are currently only settings for 'wine' that can be configured with the 'set' command:\n");
printf("vdesk=y/n run program within a virtual desktop, or not\n");
printf("vdesk=<resolution> run program within a virtual desktop with supplied resolution\n");
printf("vdesk=<resolution> run program within a virtual desktop with supplied resolution\n");
printf("winmanage=y/n allow window manager to decorate and manage windows of this program, or not\n");
printf("smoothfonts=y/n use font anti-aliasing, or not\n");
printf("os-version=<os> set version of windows to emulate. Choices are: win10, win81, win8, win7, win2008, vista, win2003, winxp, win2k, nt40, winme, win98, win95, win31\n");
printf("sound=y/n/sfx DOOM only: sound on/off, or only effects (no music)\n");
printf("mouse=y/n DOOM only: use mouse in-game, or not\n");
printf("grab=y/n DOOM only: grab mouse, or not\n");
printf("\n");
printf("Environment Variables\n");
printf("Sommelier looks for the variables SOMMELIER_CA_BUNDLE, CURL_CA_BUNDLE and SSL_VERIFY_FILE, in that order, to discover the path of the Certificate Bundle for certificate verification.\n");
printf("If SOMMELIER_INSTALLER_CACHE is set, sommelier will download installer and .zip files to the specified directory, and leave them there for future use with the -url option\n");
}
void PrintVersion()
{
printf("sommelier version %s\n", VERSION);
printf("compiled: %s %s\n", __DATE__, __TIME__);
printf("default platform: %s\n", PlatformDefault());
}
static void ParseCommandLineOption(TAction *Act, CMDLINE *CmdLine)
{
const char *p_Opt;
char *Tempstr=NULL;
if (! Act) return;
if (! CmdLine) return;
p_Opt=CommandLineCurr(CmdLine);
if (strcmp(p_Opt, "-c")==0) Config->AppConfigPath=CopyStr(Config->AppConfigPath, CommandLineNext(CmdLine));
else if (strcmp(p_Opt, "-f")==0) Act->Flags |= FLAG_FORCE;
else if (strcmp(p_Opt, "-force")==0) Act->Flags |= FLAG_FORCE;
else if (strcmp(p_Opt, "-s")==0) LoadAppConfigToAct(Act, CommandLineNext(CmdLine));
else if (strcmp(p_Opt, "-set")==0) LoadAppConfigToAct(Act, CommandLineNext(CmdLine));
else if (strcmp(p_Opt, "-k")==0) Act->Flags |= FLAG_KEEP_INSTALLER;
else if (strcmp(p_Opt, "-S")==0) Config->Flags |= FLAG_SYSTEM_INSTALL;
else if (strcmp(p_Opt, "-system")==0) Config->Flags |= FLAG_SYSTEM_INSTALL;
else if (strcmp(p_Opt, "-n")==0) Act->InstallName=CopyStr(Act->InstallName, CommandLineNext(CmdLine));
else if (strcmp(p_Opt, "-hash")==0) Act->Flags |= FLAG_HASH_DOWNLOAD;
else if (strcmp(p_Opt, "-sandbox")==0) Act->Flags |= FLAG_SANDBOX;
else if (strcmp(p_Opt, "+net")==0) Act->Flags |= FLAG_NET;
else if (strcmp(p_Opt, "-net")==0) Act->Flags &= ~FLAG_NET;
else if (strcmp(p_Opt, "-url")==0) Act->URL=realpath(CommandLineNext(CmdLine), NULL);
else if (strcmp(p_Opt, "-install-name")==0) Act->InstallName=CopyStr(Act->InstallName, CommandLineNext(CmdLine));
else if (strcmp(p_Opt, "-install-as")==0) Act->InstallName=CopyStr(Act->InstallName, CommandLineNext(CmdLine));
else if (strcmp(p_Opt, "-emu")==0) SetVar(Act->Vars, "required_emulator", CommandLineNext(CmdLine));
else if (strcmp(p_Opt, "-emulator")==0) SetVar(Act->Vars, "required_emulator", CommandLineNext(CmdLine));
else if (strcmp(p_Opt, "-platform")==0) Act->Platform=CopyStr(Act->Platform, PlatformUnAlias(CommandLineNext(CmdLine)));
else if (strcmp(p_Opt, "-installed")==0) Act->Flags |= FLAG_INSTALLED;
else if (strcmp(p_Opt, "-proxy")==0) SetGlobalConnectionChain(CommandLineNext(CmdLine));
else if (strcmp(p_Opt, "-no-xrandr")==0) Config->Flags |= FLAG_NO_XRANDR;
else if (strcmp(p_Opt, "-user-agent")==0) LibUsefulSetValue("HTTP:UserAgent",CommandLineNext(CmdLine));
else if (strcmp(p_Opt, "-ua")==0) LibUsefulSetValue("HTTP:UserAgent",CommandLineNext(CmdLine));
else if (strcmp(p_Opt, "-category")==0) SetVar(Act->Vars, "category", CommandLineNext(CmdLine));
else if (strcmp(p_Opt, "-icache")==0)
{
Config->InstallerCache=CopyStr(Config->InstallerCache, CommandLineNext(CmdLine));
Act->Flags |= FLAG_KEEP_INSTALLER;
}
else if (
(strcmp(p_Opt, "-d")==0) ||
(strcmp(p_Opt, "-debug")==0)
)
{
LibUsefulSetValue("HTTP:Debug","Y");
Config->Flags |= FLAG_DEBUG;
}
else Act->Args=MCatStr(Act->Args, " '",p_Opt,"'",NULL);
Destroy(Tempstr);
}
static TAction *CommandLineParseOptions(CMDLINE *CmdLine)
{
TAction *Options=NULL;
const char *arg;
Options=ActionCreate(ACT_INSTALL, "");
arg=CommandLineNext(CmdLine);
while (arg)
{
if (*arg=='-') ParseCommandLineOption(Options, CmdLine);
arg=CommandLineNext(CmdLine);
}
return(Options);
}
TAction *ParseSimpleAction(ListNode *Acts, int Type, CMDLINE *CmdLine)
{
TAction *Act=NULL, *ListAct=NULL;
const char *arg;
//list is one of the few actions that doesn't need an argument
//so if we were asked to list, but there are no arguments, just add
//a blank 'list all'.
if ((Type==ACT_LIST) || (Type==ACT_LIST_PLATFORMS) || (Type==ACT_LIST_CATEGORIES))
{
Act=ActionCreate(Type, "");
ListAddItem(Acts, Act);
}
arg=CommandLineNext(CmdLine);
while (arg)
{
if (*arg == '-')
{
ParseCommandLineOption(Act, CmdLine);
}
else
{
if (Type==ACT_LIST) Act->Name=CopyStr(Act->Name, arg);
else if ((Type==ACT_RUN) && Act) Act->Args=MCatStr(Act->Args, " ", arg, NULL);
else
{
Act=ActionCreate(Type, arg);
ListAddItem(Acts, Act);
}
}
arg=CommandLineNext(CmdLine);
}
return(Act);
}
TAction *ParseStandardCommand(CMDLINE *CmdLine, const char *Cmd, int ActID, ListNode *Acts, TAction *Options)
{
const char *arg;
TAction *Act=NULL;
arg=CommandLineNext(CmdLine);
if (! arg) printf("Error: No applications given as targets for '%s' command\n", Cmd);
while (arg)
{
if (*arg == '-') ParseCommandLineOption(Options, CmdLine);
else
{
Act=ActionCreate(ActID, arg);
if (Act) ListAddItem(Acts, Act);
}
arg=CommandLineNext(CmdLine);
}
return(Act);
}
ListNode *ParseCommandLine(int argc, char *argv[])
{
CMDLINE *CmdLine;
ListNode *Acts;
TAction *Act=NULL, *Options=NULL;
char *StdDepsPath=NULL, *SettingsStr=NULL;
int Flags;
const char *arg;
ListNode *Curr;
Acts=ListCreate();
CmdLine=CommandLineParserCreate(argc, argv);
//do an options run so that options like -c can be used anywhere on command-line
//this makes things very messy, 'cos we have to reparse them when examinging the
//command-line proper
Options=CommandLineParseOptions(CmdLine);
arg=CommandLineFirst(CmdLine);
if (arg)
{
if (strcmp(arg, "install")==0) Act=ParseStandardCommand(CmdLine, "install", ACT_INSTALL, Acts, Options);
else if (strncmp(arg, "reconf", 6)==0) Act=ParseStandardCommand(CmdLine, "reconfigure", ACT_RECONFIGURE, Acts, Options);
else if (strcmp(arg, "uninstall")==0) Act=ParseStandardCommand(CmdLine, "uninstall", ACT_UNINSTALL, Acts, Options);
else if (strcmp(arg, "download")==0) Act=ParseStandardCommand(CmdLine, "download", ACT_DOWNLOAD, Acts, Options);
else if (strcmp(arg, "run")==0) ParseSimpleAction(Acts, ACT_RUN, CmdLine);
else if (strcmp(arg, "list")==0) ParseSimpleAction(Acts, ACT_LIST, CmdLine);
else if (strcmp(arg, "platforms")==0) ParseSimpleAction(Acts, ACT_LIST_PLATFORMS, CmdLine);
else if (strcmp(arg, "categories")==0) ParseSimpleAction(Acts, ACT_LIST_CATEGORIES, CmdLine);
else if (strcmp(arg, "rebuild")==0) ParseSimpleAction(Acts, ACT_REBUILD, CmdLine);
else if (strcmp(arg, "hashes")==0) ParseSimpleAction(Acts, ACT_REBUILD_HASHES, CmdLine);
else if (strcmp(arg, "winecfg")==0) ParseSimpleAction(Acts, ACT_WINECFG, CmdLine);
else if (strcmp(arg, "version")==0) PrintVersion();
else if (strcmp(arg, "-version")==0) PrintVersion();
else if (strcmp(arg, "--version")==0) PrintVersion();
else if (strcmp(arg, "autostart")==0)
{
Act=ActionCreate(ACT_AUTOSTART, "");
ListAddItem(Acts, Act);
}
else if (strcmp(arg, "set")==0)
{
SettingsStr=CopyStr(SettingsStr, CommandLineNext(CmdLine));
arg=CommandLineNext(CmdLine);
if (! arg) printf("Error: No applications given as targets for 'set' command\n");
while (arg)
{
Act=ActionCreate(ACT_SET, arg);
if (Act)
{
LoadAppConfigToAct(Act, SettingsStr);
ListAddItem(Acts, Act);
}
arg=CommandLineNext(CmdLine);
}
}
else PrintUsage();
}
else PrintUsage();
Curr=ListGetNext(Acts);
while (Curr)
{
Act=(TAction *) Curr->Item;
Act->Flags |= Options->Flags;
if (StrValid(Options->URL)) Act->URL=CopyStr(Act->URL, Options->URL);
if (StrValid(Options->Platform)) Act->Platform=CopyStr(Act->Platform, Options->Platform);
if (StrValid(Options->InstallName)) Act->InstallName=CopyStr(Act->InstallName, Options->InstallName);
CopyVars(Act->Vars, Options->Vars);
if (! StrValid(Act->Platform)) Act->Platform=CopyStr(Act->Platform, PlatformDefault());
Curr=ListGetNext(Curr);
}
DestroyString(SettingsStr);
DestroyString(StdDepsPath);
return(Acts);
}