]>
Commit | Line | Data |
---|---|---|
c4453a3d | 1 | /* mkshortcut.c -- create a Windows shortcut |
0bb67178 | 2 | * |
0bb67178 CW |
3 | * Copyright (c) 2002 Joshua Daniel Franklin |
4 | * | |
5 | * This program is free software; you can redistribute it and/or | |
6 | * modify it under the terms of the GNU General Public License | |
7 | * as published by the Free Software Foundation; either version 2 | |
8 | * of the License, or (at your option) any later version. | |
9 | * | |
10 | * This program is distributed in the hope that it will be useful, | |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
c4453a3d | 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
0bb67178 CW |
13 | * GNU General Public License for more details. |
14 | * | |
15 | * You should have received a copy of the GNU General Public License | |
16 | * along with this program; if not, write to the Free Software | |
17 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |
18 | * | |
19 | * See the COPYING file for license information. | |
20 | * | |
21 | * Exit values | |
22 | * 1: user error (syntax error) | |
23 | * 2: system error (out of memory, etc.) | |
24 | * 3: windows error (interface failed) | |
c4453a3d CW |
25 | * |
26 | * Compile with: gcc -o prog.exe mkshortcut.c -lpopt -lole32 -luuid | |
7ab0751f | 27 | * (You'd need to uncomment the moved to common.h lines.) |
0bb67178 CW |
28 | * |
29 | */ | |
c4453a3d | 30 | |
0bb67178 CW |
31 | #if HAVE_CONFIG_H |
32 | # include "config.h" | |
c4453a3d | 33 | #endif |
0bb67178 | 34 | #include "common.h" |
5f56ef9c CW |
35 | |
36 | #define NOCOMATTRIBUTE | |
37 | ||
38 | #include <shlobj.h> | |
39 | #include <olectlid.h> | |
0bb67178 CW |
40 | /* moved to common.h */ |
41 | /* | |
5f56ef9c | 42 | #include <stdio.h> |
c4453a3d | 43 | #include <popt.h> |
0bb67178 CW |
44 | */ |
45 | ||
c4453a3d CW |
46 | static const char versionStr[] = "$Revision$"; |
47 | static const char versionID[] = "1.02.0"; | |
0bb67178 CW |
48 | /* for CVS */ |
49 | static const char revID[] = | |
7ab0751f | 50 | "$Id$"; |
0bb67178 | 51 | static const char copyrightID[] = |
7ab0751f | 52 | "Copyright (c) 2002\nJoshua Daniel Franklin. All rights reserved.\nLicensed under GPL v2.0\n"; |
5f56ef9c | 53 | |
c4453a3d CW |
54 | typedef struct optvals_s { |
55 | int icon_flag; | |
56 | int unix_flag; | |
57 | int windows_flag; | |
58 | int allusers_flag; | |
59 | int desktop_flag; | |
60 | int smprograms_flag; | |
61 | int offset; | |
62 | char * name_arg; | |
b2682e03 | 63 | char * dir_name_arg; |
c4453a3d CW |
64 | char * argument_arg; |
65 | char * target_arg; | |
66 | char * icon_name_arg; | |
67 | } optvals; | |
5f56ef9c | 68 | |
c4453a3d CW |
69 | static int mkshortcut(optvals opts, poptContext optCon); |
70 | static void printTopDescription(FILE * f, char * name); | |
71 | static void printBottomDescription(FILE * f, char * name); | |
72 | static char * getVersion(char * s, int slen); | |
73 | static void usage(poptContext optCon, FILE * f, char * name); | |
74 | static void help(poptContext optCon, FILE * f, char * name); | |
75 | static void version(poptContext optCon, FILE * f, char * name); | |
76 | static void license(poptContext optCon, FILE * f, char * name); | |
77 | ||
78 | static char *program_name; | |
79 | ||
80 | int | |
81 | main (int argc, const char **argv) | |
7ab0751f | 82 | { |
c4453a3d CW |
83 | poptContext optCon; |
84 | const char ** rest; | |
85 | int rc; | |
86 | int ec = 0; | |
87 | optvals opts; | |
88 | ||
89 | const char *tmp_str; | |
90 | int icon_offset_flag; | |
91 | char icon_name[MAX_PATH]; | |
92 | const char * arg; | |
93 | ||
94 | struct poptOption helpOptionsTable[] = { | |
95 | { "help", 'h', POPT_ARG_NONE, NULL, '?', \ | |
96 | "Show this help message", NULL}, | |
97 | { "usage", '\0', POPT_ARG_NONE, NULL, 'u', \ | |
98 | "Display brief usage message", NULL}, | |
99 | { "version", 'v', POPT_ARG_NONE, NULL, 'v', \ | |
100 | "Display version information", NULL}, | |
101 | { "license", '\0', POPT_ARG_NONE, NULL, 'l', \ | |
102 | "Display licensing information", NULL}, | |
103 | { NULL, '\0', 0, NULL, 0, NULL, NULL } | |
104 | }; | |
105 | ||
106 | struct poptOption generalOptionsTable[] = { | |
107 | { "arguments", 'a', POPT_ARG_STRING, NULL, 'a', \ | |
108 | "Use arguments ARGS", "ARGS"}, | |
109 | { "icon", 'i', POPT_ARG_STRING, NULL, 'i', \ | |
110 | "icon file for link to use", "iconfile"}, | |
111 | { "iconoffset", 'j', POPT_ARG_INT, &(opts.offset), 'j', \ | |
112 | "offset of icon in icon file (default is 0)", NULL}, | |
113 | { "name", 'n', POPT_ARG_STRING, NULL, 'n', \ | |
114 | "name for link (defaults to TARGET)", "NAME"}, | |
b2682e03 CW |
115 | { "workingdir", 'w', POPT_ARG_STRING, NULL, 'w', \ |
116 | "set working directory (defaults to directory path of TARGET)", "PATH"}, | |
c4453a3d CW |
117 | { "allusers", 'A', POPT_ARG_VAL, &(opts.allusers_flag), 1, \ |
118 | "use 'All Users' instead of current user for -D,-P", NULL}, | |
119 | { "desktop", 'D', POPT_ARG_VAL, &(opts.desktop_flag), 1, \ | |
120 | "create link relative to 'Desktop' directory", NULL}, | |
121 | { "smprograms", 'P', POPT_ARG_VAL, &(opts.smprograms_flag), 1, \ | |
122 | "create link relative to Start Menu 'Programs' directory", NULL}, | |
123 | { NULL, '\0', 0, NULL, 0, NULL, NULL } | |
124 | }; | |
125 | ||
126 | struct poptOption opt[] = { | |
127 | { NULL, '\0', POPT_ARG_INCLUDE_TABLE, generalOptionsTable, 0, \ | |
128 | "General options", NULL }, | |
129 | { NULL, '\0', POPT_ARG_INCLUDE_TABLE, helpOptionsTable, 0, \ | |
130 | "Help options", NULL }, | |
131 | { NULL, '\0', 0, NULL, 0, NULL, NULL } | |
132 | }; | |
133 | ||
134 | tmp_str = strrchr (argv[0], '/'); | |
135 | if (tmp_str == NULL) { | |
136 | tmp_str = strrchr (argv[0], '\\'); | |
137 | } | |
138 | if (tmp_str == NULL) { | |
139 | tmp_str = argv[0]; | |
140 | } else { | |
141 | tmp_str++; | |
142 | } | |
143 | if ((program_name = strdup(tmp_str)) == NULL ) { | |
144 | fprintf(stderr, "%s: memory allocation error\n", argv[0]); | |
145 | exit(2); | |
146 | } | |
147 | ||
148 | icon_offset_flag = 0; | |
149 | ||
150 | opts.offset = 0; | |
151 | opts.icon_flag = 0; | |
152 | opts.unix_flag = 0; | |
153 | opts.windows_flag = 0; | |
154 | opts.allusers_flag = 0; | |
155 | opts.desktop_flag = 0; | |
156 | opts.smprograms_flag = 0; | |
157 | opts.target_arg = NULL; | |
158 | opts.argument_arg = NULL; | |
159 | opts.name_arg = NULL; | |
b2682e03 | 160 | opts.dir_name_arg = NULL; |
c4453a3d CW |
161 | opts.icon_name_arg = NULL; |
162 | ||
163 | /* Parse options */ | |
164 | optCon = poptGetContext(NULL, argc, argv, opt, 0); | |
165 | poptSetOtherOptionHelp(optCon, "[OPTION]* TARGET"); | |
166 | while ((rc = poptGetNextOpt(optCon)) > 0) { | |
167 | switch (rc) { | |
168 | case '?': help(optCon, stderr, program_name); | |
169 | goto exit; | |
170 | case 'u': usage(optCon, stderr, program_name); | |
171 | goto exit; | |
172 | case 'v': version(optCon, stderr, program_name); | |
173 | goto exit; | |
174 | case 'l': license(optCon, stderr, program_name); | |
175 | goto exit; | |
176 | case 'i': opts.icon_flag = 1; | |
177 | if (arg = poptGetOptArg(optCon)) { | |
178 | cygwin_conv_to_full_win32_path (arg, icon_name); | |
179 | if ((opts.icon_name_arg = strdup(icon_name)) == NULL ) { | |
180 | fprintf(stderr, "%s: memory allocation error\n", program_name); | |
181 | ec=2; | |
182 | goto exit; | |
183 | } | |
184 | } | |
185 | break; | |
186 | case 'j': icon_offset_flag = 1; | |
187 | break; | |
188 | case 'n': if (arg = poptGetOptArg(optCon)) { | |
189 | if ((opts.name_arg = strdup(arg)) == NULL ) { | |
190 | fprintf(stderr, "%s: memory allocation error\n", program_name); | |
191 | ec=2; | |
192 | goto exit; | |
193 | } | |
194 | } | |
195 | break; | |
b2682e03 CW |
196 | case 'w': if (arg = poptGetOptArg(optCon)) { |
197 | if ((opts.dir_name_arg = strdup(arg)) == NULL ) { | |
198 | fprintf(stderr, "%s: memory allocation error\n", program_name); | |
199 | ec=2; | |
200 | goto exit; | |
201 | } | |
202 | } | |
203 | break; | |
c4453a3d CW |
204 | case 'a': if (arg = poptGetOptArg(optCon)) { |
205 | if ((opts.argument_arg = strdup(arg)) == NULL ) { | |
206 | fprintf(stderr, "%s: memory allocation error\n", program_name); | |
207 | ec=2; | |
208 | goto exit; | |
209 | } | |
210 | } | |
211 | break; | |
212 | // case 'A' | |
213 | // case 'D' | |
214 | // case 'P' all handled by popt itself | |
215 | } | |
216 | } | |
217 | ||
218 | if (icon_offset_flag & !opts.icon_flag) { | |
219 | fprintf(stderr, | |
220 | "%s: --iconoffset|-j only valid in conjuction with --icon|-i\n", | |
221 | program_name); | |
222 | usage(optCon, stderr, program_name); | |
223 | ec=1; | |
224 | goto exit; | |
225 | } | |
226 | ||
227 | if (opts.smprograms_flag && opts.desktop_flag) { | |
228 | fprintf(stderr, | |
229 | "%s: --smprograms|-P not valid in conjuction with --desktop|-D\n", | |
230 | program_name); | |
231 | usage(optCon, stderr, program_name); | |
232 | ec=1; | |
233 | goto exit; | |
234 | } | |
235 | ||
236 | if (rc < -1 ) { | |
237 | fprintf(stderr, "%s: bad argument %s: %s\n", | |
238 | program_name, poptBadOption(optCon, POPT_BADOPTION_NOALIAS), | |
239 | poptStrerror(rc)); | |
240 | ec = 1; | |
241 | goto exit; | |
242 | } | |
243 | ||
244 | rest = poptGetArgs(optCon); | |
245 | ||
246 | if (rest && *rest) { | |
247 | if ((opts.target_arg = strdup(*rest)) == NULL) { | |
248 | fprintf(stderr, "%s: memory allocation error\n", program_name); | |
249 | ec=2; | |
250 | goto exit; | |
7ab0751f | 251 | } |
c4453a3d CW |
252 | rest++; |
253 | if (rest && *rest) { | |
254 | fprintf(stderr, "%s: Too many arguments: ", program_name); | |
255 | while (*rest) | |
256 | fprintf(stderr, "%s ", *rest++); | |
257 | fprintf(stderr, "\n"); | |
258 | usage(optCon, stderr, program_name); | |
259 | ec=1; | |
260 | } else { | |
261 | // THE MEAT GOES HERE | |
262 | ec = mkshortcut(opts, optCon); | |
263 | } | |
264 | } else { | |
265 | fprintf(stderr, "%s: TARGET not specified\n", program_name); | |
266 | usage(optCon, stderr, program_name); | |
267 | ec=1; | |
268 | } | |
269 | ||
270 | exit: | |
271 | poptFreeContext(optCon); | |
272 | if (opts.target_arg) { free(opts.target_arg); } | |
273 | if (opts.name_arg) { free(opts.name_arg); } | |
b2682e03 | 274 | if (opts.dir_name_arg) { free(opts.dir_name_arg); } |
c4453a3d CW |
275 | if (opts.argument_arg) { free(opts.argument_arg); } |
276 | if (opts.icon_name_arg) { free(opts.icon_name_arg); } | |
277 | free(program_name); | |
278 | return(ec); | |
7ab0751f CW |
279 | } |
280 | ||
c4453a3d | 281 | int mkshortcut(optvals opts, poptContext optCon) |
5f56ef9c | 282 | { |
7ab0751f CW |
283 | char link_name[MAX_PATH]; |
284 | char exe_name[MAX_PATH]; | |
285 | char dir_name[MAX_PATH]; | |
c4453a3d CW |
286 | char *buf_str, *tmp_str; |
287 | int tmp; | |
7ab0751f CW |
288 | |
289 | /* For OLE interface */ | |
5f56ef9c CW |
290 | LPITEMIDLIST id; |
291 | HRESULT hres; | |
7ab0751f CW |
292 | IShellLink *shell_link; |
293 | IPersistFile *persist_file; | |
5f56ef9c CW |
294 | WCHAR widepath[MAX_PATH]; |
295 | ||
7ab0751f | 296 | buf_str = (char *) malloc (PATH_MAX); |
c4453a3d CW |
297 | if (buf_str == NULL) { |
298 | fprintf (stderr, "%s: out of memory\n", program_name); | |
299 | return(2); | |
300 | } | |
5f56ef9c | 301 | |
7ab0751f | 302 | /* If there's a colon in the TARGET, it should be a URL */ |
c4453a3d | 303 | if (strchr (opts.target_arg, ':') != NULL) |
7ab0751f CW |
304 | { |
305 | /* Nope, somebody's trying a W32 path */ | |
c4453a3d CW |
306 | if (opts.target_arg[1] == ':') { |
307 | fprintf(stderr, "%s: all paths must be in POSIX format\n", | |
308 | program_name); | |
309 | usage (optCon, stderr, program_name); | |
310 | return(1); | |
311 | } | |
312 | strcpy (exe_name, opts.target_arg); | |
7ab0751f CW |
313 | dir_name[0] = '\0'; /* No working dir for URL */ |
314 | } | |
315 | /* Convert TARGET to win32 path */ | |
5f56ef9c | 316 | else |
7ab0751f | 317 | { |
c4453a3d | 318 | strcpy (buf_str, opts.target_arg); |
7ab0751f | 319 | cygwin_conv_to_full_win32_path (buf_str, exe_name); |
5f56ef9c | 320 | |
b2682e03 CW |
321 | /* Get a working dir from 'w' option */ |
322 | if (opts.dir_name_arg != NULL) | |
323 | { | |
324 | if (strchr (opts.dir_name_arg, ':') != NULL) | |
325 | { | |
326 | fprintf(stderr, "%s: all paths must be in POSIX format\n", | |
327 | program_name); | |
328 | usage (optCon, stderr, program_name); | |
329 | return(1); | |
330 | } | |
331 | cygwin_conv_to_win32_path (opts.dir_name_arg, dir_name); | |
332 | } | |
7ab0751f | 333 | /* Get a working dir from the exepath */ |
b2682e03 CW |
334 | else |
335 | { | |
336 | tmp_str = strrchr (exe_name, '\\'); | |
337 | tmp = strlen (exe_name) - strlen (tmp_str); | |
338 | strncpy (dir_name, exe_name, tmp); | |
339 | dir_name[tmp] = '\0'; | |
340 | } | |
7ab0751f | 341 | } |
5f56ef9c | 342 | |
7ab0751f | 343 | /* Generate a name for the link if not given */ |
c4453a3d | 344 | if (opts.name_arg == NULL) |
5f56ef9c | 345 | { |
7ab0751f | 346 | /* Strip trailing /'s if any */ |
c4453a3d | 347 | strcpy (buf_str, opts.target_arg); |
7ab0751f CW |
348 | tmp_str = buf_str; |
349 | tmp = strlen (buf_str) - 1; | |
350 | while (strrchr (buf_str, '/') == (buf_str + tmp)) | |
351 | { | |
352 | buf_str[tmp] = '\0'; | |
353 | tmp--; | |
354 | } | |
355 | /* Get basename */ | |
356 | while (*buf_str) | |
357 | { | |
358 | if (*buf_str == '/') | |
359 | tmp_str = buf_str + 1; | |
360 | buf_str++; | |
361 | } | |
362 | strcpy (link_name, tmp_str); | |
c4453a3d | 363 | } |
7ab0751f CW |
364 | /* User specified a name, so check it and convert */ |
365 | else | |
5f56ef9c | 366 | { |
c4453a3d | 367 | if (opts.desktop_flag || opts.smprograms_flag) |
7ab0751f CW |
368 | { |
369 | /* Cannot have absolute path relative to Desktop/SM Programs */ | |
c4453a3d CW |
370 | if (opts.name_arg[0] == '/') { |
371 | fprintf(stderr, "%s: absolute pathnames not allowed with -D/-P\n", | |
372 | program_name); | |
373 | usage (optCon, stderr, program_name); | |
374 | return(1); | |
375 | } | |
7ab0751f CW |
376 | } |
377 | /* Sigh. Another W32 path */ | |
c4453a3d CW |
378 | if (strchr (opts.name_arg, ':') != NULL) { |
379 | fprintf(stderr, "%s: all paths must be in POSIX format\n", | |
380 | program_name); | |
381 | usage (optCon, stderr, program_name); | |
382 | return(1); | |
383 | } | |
384 | cygwin_conv_to_win32_path (opts.name_arg, link_name); | |
385 | } | |
7ab0751f CW |
386 | |
387 | /* Add suffix to link name if necessary */ | |
388 | if (strlen (link_name) > 4) | |
5f56ef9c | 389 | { |
7ab0751f CW |
390 | tmp = strlen (link_name) - 4; |
391 | if (strncmp (link_name + tmp, ".lnk", 4) != 0) | |
392 | strcat (link_name, ".lnk"); | |
5f56ef9c | 393 | } |
7ab0751f CW |
394 | else |
395 | strcat (link_name, ".lnk"); | |
5f56ef9c | 396 | |
7ab0751f | 397 | /* Prepend relative path if necessary */ |
c4453a3d | 398 | if (opts.desktop_flag) |
7ab0751f CW |
399 | { |
400 | strcpy (buf_str, link_name); | |
c4453a3d | 401 | if (!opts.allusers_flag) |
7ab0751f CW |
402 | SHGetSpecialFolderLocation (NULL, CSIDL_DESKTOPDIRECTORY, &id); |
403 | else | |
404 | SHGetSpecialFolderLocation (NULL, CSIDL_COMMON_DESKTOPDIRECTORY, &id); | |
405 | SHGetPathFromIDList (id, link_name); | |
406 | /* Make sure Win95 without "All Users" has output */ | |
407 | if (strlen (link_name) == 0) | |
408 | { | |
409 | SHGetSpecialFolderLocation (NULL, CSIDL_DESKTOPDIRECTORY, &id); | |
410 | SHGetPathFromIDList (id, link_name); | |
411 | } | |
412 | strcat (link_name, "\\"); | |
413 | strcat (link_name, buf_str); | |
5f56ef9c | 414 | } |
5f56ef9c | 415 | |
c4453a3d | 416 | if (opts.smprograms_flag) |
7ab0751f CW |
417 | { |
418 | strcpy (buf_str, link_name); | |
c4453a3d | 419 | if (!opts.allusers_flag) |
7ab0751f CW |
420 | SHGetSpecialFolderLocation (NULL, CSIDL_PROGRAMS, &id); |
421 | else | |
422 | SHGetSpecialFolderLocation (NULL, CSIDL_COMMON_PROGRAMS, &id); | |
423 | SHGetPathFromIDList (id, link_name); | |
424 | /* Make sure Win95 without "All Users" has output */ | |
425 | if (strlen (link_name) == 0) | |
426 | { | |
427 | SHGetSpecialFolderLocation (NULL, CSIDL_PROGRAMS, &id); | |
428 | SHGetPathFromIDList (id, link_name); | |
429 | } | |
430 | strcat (link_name, "\\"); | |
431 | strcat (link_name, buf_str); | |
5f56ef9c | 432 | } |
5f56ef9c | 433 | |
7ab0751f CW |
434 | /* Beginning of Windows interface */ |
435 | hres = OleInitialize (NULL); | |
436 | if (hres != S_FALSE && hres != S_OK) | |
437 | { | |
c4453a3d CW |
438 | fprintf (stderr, "%s: Could not initialize OLE interface\n", |
439 | program_name); | |
440 | return (3); | |
7ab0751f | 441 | } |
5f56ef9c | 442 | |
7ab0751f CW |
443 | hres = |
444 | CoCreateInstance (&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, | |
445 | &IID_IShellLink, (void **) &shell_link); | |
446 | if (SUCCEEDED (hres)) | |
5f56ef9c | 447 | { |
7ab0751f CW |
448 | hres = |
449 | shell_link->lpVtbl->QueryInterface (shell_link, &IID_IPersistFile, | |
450 | (void **) &persist_file); | |
451 | if (SUCCEEDED (hres)) | |
452 | { | |
453 | shell_link->lpVtbl->SetPath (shell_link, exe_name); | |
454 | /* Put the POSIX path in the "Description", just to be nice */ | |
455 | cygwin_conv_to_full_posix_path (exe_name, buf_str); | |
456 | shell_link->lpVtbl->SetDescription (shell_link, buf_str); | |
457 | shell_link->lpVtbl->SetWorkingDirectory (shell_link, dir_name); | |
c4453a3d CW |
458 | if (opts.argument_arg) |
459 | shell_link->lpVtbl->SetArguments (shell_link, opts.argument_arg); | |
460 | if (opts.icon_flag) | |
461 | shell_link->lpVtbl->SetIconLocation (shell_link, opts.icon_name_arg, | |
462 | opts.offset); | |
5f56ef9c | 463 | |
7ab0751f CW |
464 | /* Make link name Unicode-compliant */ |
465 | hres = | |
466 | MultiByteToWideChar (CP_ACP, 0, link_name, -1, widepath, | |
467 | MAX_PATH); | |
468 | if (!SUCCEEDED (hres)) | |
469 | { | |
470 | fprintf (stderr, "%s: Unicode translation failed%d\n", | |
c4453a3d CW |
471 | program_name, hres); |
472 | return (3); | |
7ab0751f CW |
473 | } |
474 | hres = persist_file->lpVtbl->Save (persist_file, widepath, TRUE); | |
475 | if (!SUCCEEDED (hres)) | |
476 | { | |
477 | fprintf (stderr, | |
c4453a3d CW |
478 | "%s: Saving \"%s\" failed; does the target directory exist?\n", |
479 | program_name, link_name); | |
480 | return (3); | |
7ab0751f CW |
481 | } |
482 | persist_file->lpVtbl->Release (persist_file); | |
483 | shell_link->lpVtbl->Release (shell_link); | |
484 | } | |
485 | else | |
486 | { | |
c4453a3d CW |
487 | fprintf (stderr, "%s: QueryInterface failed\n", program_name); |
488 | return (3); | |
7ab0751f | 489 | } |
5f56ef9c | 490 | } |
7ab0751f | 491 | else |
5f56ef9c | 492 | { |
c4453a3d CW |
493 | fprintf (stderr, "%s: CoCreateInstance failed\n", program_name); |
494 | return (3); | |
5f56ef9c | 495 | } |
c4453a3d CW |
496 | } |
497 | ||
498 | static char * getVersion(char * s, int slen) | |
499 | { | |
500 | const char *v = strchr (versionStr, ':'); | |
501 | ||
502 | int len; | |
503 | if (!v) { | |
504 | v = "?"; | |
505 | len = 1; | |
506 | } else { | |
507 | v += 2; | |
508 | len = strchr (v, ' ') - v; | |
509 | } | |
510 | snprintf (s,slen,"%.*s", len, v); | |
511 | return s; | |
512 | } | |
513 | ||
514 | static void printTopDescription(FILE * f, char * name) | |
515 | { | |
516 | char s[20]; | |
517 | fprintf(f, "%s (cygutils) version %s\n", name, getVersion(s, 20)); | |
518 | fprintf(f, " create a Windows shortcut\n\n"); | |
519 | } | |
520 | static void printBottomDescription(FILE * f, char * name) | |
521 | { | |
014ae39c | 522 | fprintf(f, "\nNOTE: All filename arguments must be in unix (POSIX) format\n"); |
c4453a3d CW |
523 | } |
524 | static printLicense(FILE * f, char * name) | |
525 | { | |
526 | fprintf(f, "This program is free software; you can redistribute it and/or\n"); | |
527 | fprintf(f, "modify it under the terms of the GNU General Public License\n"); | |
528 | fprintf(f, "as published by the Free Software Foundation; either version 2\n"); | |
529 | fprintf(f, "of the License, or (at your option) any later version.\n"); | |
530 | fprintf(f, "\n"); | |
531 | fprintf(f, "This program is distributed in the hope that it will be useful,\n"); | |
532 | fprintf(f, "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"); | |
533 | fprintf(f, "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"); | |
534 | fprintf(f, "GNU General Public License for more details.\n"); | |
535 | fprintf(f, "\n"); | |
536 | fprintf(f, "You should have received a copy of the GNU General Public License\n"); | |
537 | fprintf(f, "along with this program; if not, write to the Free Software\n"); | |
538 | fprintf(f, "Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n"); | |
539 | fprintf(f, "\n"); | |
540 | fprintf(f, "See the COPYING file for license information.\n"); | |
541 | } | |
542 | static void usage(poptContext optCon, FILE * f, char * name) | |
543 | { | |
544 | poptPrintUsage(optCon, f, 0); | |
545 | } | |
7ab0751f | 546 | |
c4453a3d CW |
547 | static void help(poptContext optCon, FILE * f, char * name) |
548 | { | |
549 | printTopDescription(f, name); | |
550 | poptPrintHelp(optCon, f, 0); | |
014ae39c | 551 | printBottomDescription(f, name); |
c4453a3d CW |
552 | } |
553 | ||
554 | static void version(poptContext optCon, FILE * f, char * name) | |
555 | { | |
556 | printTopDescription(f, name); | |
557 | fprintf(f, copyrightID); | |
5f56ef9c | 558 | } |
c4453a3d CW |
559 | |
560 | static void license(poptContext optCon, FILE * f, char * name) | |
561 | { | |
562 | printTopDescription(f, name); | |
563 | printLicense(f, name); | |
c4453a3d CW |
564 | } |
565 |