]> cygwin.com Git - cygwin-apps/cygutils.git/blob - src/mkshortcut/mkshortcut.c
version 1.4.15
[cygwin-apps/cygutils.git] / src / mkshortcut / mkshortcut.c
1 /* mkshortcut.c -- create a Windows shortcut
2 *
3 * Copyright (c) 2002 Joshua Daniel Franklin
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (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
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
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, see <http://www.gnu.org/licenses/>.
17 *
18 * See the COPYING file for full license information.
19 *
20 * Exit values
21 * 1: user error (syntax error)
22 * 2: system error (out of memory, etc.)
23 * 3: windows error (interface failed)
24 *
25 * Compile with: gcc -o prog.exe mkshortcut.c -lpopt -lole32 -luuid
26 * (You'd need to uncomment the moved to common.h lines.)
27 *
28 */
29
30 #if HAVE_CONFIG_H
31 # include "config.h"
32 #endif
33 #include "common.h"
34
35 #define NOCOMATTRIBUTE
36
37 #include <shlobj.h>
38 #include <olectl.h>
39 /* moved to common.h */
40 /*
41 #include <stdio.h>
42 #include <popt.h>
43 */
44 #include <sys/cygwin.h>
45
46 static const char versionID[] = PACKAGE_VERSION;
47 static const char revID[] =
48 "$Id$";
49 static const char copyrightID[] =
50 "Copyright (c) 2002\nJoshua Daniel Franklin. All rights reserved.\nLicensed under GPL v2.0\n";
51
52 typedef struct optvals_s
53 {
54 int icon_flag;
55 int unix_flag;
56 int windows_flag;
57 int allusers_flag;
58 int desktop_flag;
59 int smprograms_flag;
60 int show_flag;
61 int offset;
62 char *name_arg;
63 char *desc_arg;
64 char *dir_name_arg;
65 char *argument_arg;
66 char *target_arg;
67 char *icon_name_arg;
68 } optvals;
69
70 static int mkshortcut (optvals opts);
71 static void printTopDescription (FILE * f, char *name);
72 static void printBottomDescription (FILE * f, char *name);
73 static const char *getVersion ();
74 static void usage (FILE * f, char *name);
75 static void help (FILE * f, char *name);
76 static void version (FILE * f, char *name);
77 static void license (FILE * f, char *name);
78
79 static char *program_name;
80 static poptContext optCon;
81
82 int
83 main (int argc, const char **argv)
84 {
85 const char **rest;
86 int rc;
87 int ec = 0;
88 optvals opts;
89
90 const char *tmp_str;
91 int icon_offset_flag;
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 {"desc", 'd', POPT_ARG_STRING, NULL, 'd',
110 "Text for description/tooltip (defaults to POSIX path of TARGET)",
111 "DESC"},
112 {"icon", 'i', POPT_ARG_STRING, NULL, 'i',
113 "Icon file for link to use", "ICONFILE"},
114 {"iconoffset", 'j', POPT_ARG_INT, &(opts.offset), 'j',
115 "Offset of icon in icon file (default is 0)", NULL},
116 {"name", 'n', POPT_ARG_STRING, NULL, 'n',
117 "Name for link (defaults to TARGET)", "NAME"},
118 {"show", 's', POPT_ARG_STRING, NULL, 's',
119 "Window to show: normal, minimized, maximized", "norm|min|max"},
120 {"workingdir", 'w', POPT_ARG_STRING, NULL, 'w',
121 "Set working directory (defaults to directory path of TARGET)", "PATH"},
122 {"allusers", 'A', POPT_ARG_VAL, &(opts.allusers_flag), 1,
123 "Use 'All Users' instead of current user for -D,-P", NULL},
124 {"desktop", 'D', POPT_ARG_VAL, &(opts.desktop_flag), 1,
125 "Create link relative to 'Desktop' directory", NULL},
126 {"smprograms", 'P', POPT_ARG_VAL, &(opts.smprograms_flag), 1,
127 "Create link relative to Start Menu 'Programs' directory", NULL},
128 {NULL, '\0', 0, NULL, 0, NULL, NULL}
129 };
130
131 struct poptOption opt[] = {
132 {NULL, '\0', POPT_ARG_INCLUDE_TABLE, generalOptionsTable, 0,
133 "General options", NULL},
134 {NULL, '\0', POPT_ARG_INCLUDE_TABLE, helpOptionsTable, 0,
135 "Help options", NULL},
136 {NULL, '\0', 0, NULL, 0, NULL, NULL}
137 };
138
139 tmp_str = strrchr (argv[0], '/');
140 if (tmp_str == NULL)
141 {
142 tmp_str = strrchr (argv[0], '\\');
143 }
144 if (tmp_str == NULL)
145 {
146 tmp_str = argv[0];
147 }
148 else
149 {
150 tmp_str++;
151 }
152 if ((program_name = strdup (tmp_str)) == NULL)
153 {
154 fprintf (stderr, "%s: memory allocation error\n", argv[0]);
155 exit (2);
156 }
157
158 icon_offset_flag = 0;
159
160 opts.offset = 0;
161 opts.icon_flag = 0;
162 opts.unix_flag = 0;
163 opts.windows_flag = 0;
164 opts.allusers_flag = 0;
165 opts.desktop_flag = 0;
166 opts.smprograms_flag = 0;
167 opts.show_flag = SW_SHOWNORMAL;
168 opts.target_arg = NULL;
169 opts.argument_arg = NULL;
170 opts.name_arg = NULL;
171 opts.desc_arg = NULL;
172 opts.dir_name_arg = NULL;
173 opts.icon_name_arg = NULL;
174
175 /* Parse options */
176 optCon = poptGetContext (NULL, argc, argv, opt, 0);
177 poptSetOtherOptionHelp (optCon, "[OPTION]* TARGET");
178 while ((rc = poptGetNextOpt (optCon)) > 0)
179 {
180 switch (rc)
181 {
182 case '?':
183 help (stdout, program_name);
184 goto exit;
185 case 'u':
186 usage (stdout, program_name);
187 goto exit;
188 case 'v':
189 version (stdout, program_name);
190 goto exit;
191 case 'l':
192 license (stdout, program_name);
193 goto exit;
194 case 'd':
195 if (arg = poptGetOptArg (optCon))
196 {
197 if ((opts.desc_arg = strdup (arg)) == NULL)
198 {
199 fprintf (stderr, "%s: memory allocation error\n",
200 program_name);
201 ec = 2;
202 goto exit;
203 }
204 }
205 break;
206 case 'i':
207 opts.icon_flag = 1;
208 if (arg = poptGetOptArg (optCon))
209 {
210 opts.icon_name_arg = (char *) cygwin_create_path(
211 CCP_POSIX_TO_WIN_A, arg);
212 if (opts.icon_name_arg == NULL)
213 {
214 fprintf (stderr, "%s: error converting posix path to win32 (%s)\n",
215 program_name, strerror(errno));
216 ec = 2;
217 goto exit;
218 }
219 }
220 break;
221 case 'j':
222 icon_offset_flag = 1;
223 break;
224 case 'n':
225 if (arg = poptGetOptArg (optCon))
226 {
227 if ((opts.name_arg = strdup (arg)) == NULL)
228 {
229 fprintf (stderr, "%s: memory allocation error\n",
230 program_name);
231 ec = 2;
232 goto exit;
233 }
234 }
235 break;
236 case 's':
237 if (arg = poptGetOptArg (optCon))
238 {
239 if (strcmp (arg, "min") == 0)
240 {
241 opts.show_flag = SW_SHOWMINNOACTIVE;
242 }
243 else if (strcmp (arg, "max") == 0)
244 {
245 opts.show_flag = SW_SHOWMAXIMIZED;
246 }
247 else if (strcmp (arg, "norm") == 0)
248 {
249 opts.show_flag = SW_SHOWNORMAL;
250 }
251 else
252 {
253 fprintf (stderr, "%s: %s not valid for show window\n",
254 program_name, arg);
255 ec = 2;
256 goto exit;
257 }
258 }
259 break;
260 case 'w':
261 if (arg = poptGetOptArg (optCon))
262 {
263 if ((opts.dir_name_arg = strdup (arg)) == NULL)
264 {
265 fprintf (stderr, "%s: memory allocation error\n",
266 program_name);
267 ec = 2;
268 goto exit;
269 }
270 }
271 break;
272 case 'a':
273 if (arg = poptGetOptArg (optCon))
274 {
275 if ((opts.argument_arg = strdup (arg)) == NULL)
276 {
277 fprintf (stderr, "%s: memory allocation error\n",
278 program_name);
279 ec = 2;
280 goto exit;
281 }
282 }
283 break;
284 // case 'A'
285 // case 'D'
286 // case 'P' all handled by popt itself
287 }
288 }
289
290 if (icon_offset_flag & !opts.icon_flag)
291 {
292 fprintf (stderr,
293 "%s: --iconoffset|-j only valid in conjuction with --icon|-i\n",
294 program_name);
295 usage (stderr, program_name);
296 ec = 1;
297 goto exit;
298 }
299
300 if (opts.smprograms_flag && opts.desktop_flag)
301 {
302 fprintf (stderr,
303 "%s: --smprograms|-P not valid in conjuction with --desktop|-D\n",
304 program_name);
305 usage (stderr, program_name);
306 ec = 1;
307 goto exit;
308 }
309
310 if (rc < -1)
311 {
312 fprintf (stderr, "%s: bad argument %s: %s\n",
313 program_name, poptBadOption (optCon, POPT_BADOPTION_NOALIAS),
314 poptStrerror (rc));
315 ec = 1;
316 goto exit;
317 }
318
319 rest = poptGetArgs (optCon);
320
321 if (rest && *rest)
322 {
323 if ((opts.target_arg = strdup (*rest)) == NULL)
324 {
325 fprintf (stderr, "%s: memory allocation error\n", program_name);
326 ec = 2;
327 goto exit;
328 }
329 rest++;
330 if (rest && *rest)
331 {
332 fprintf (stderr, "%s: Too many arguments: ", program_name);
333 while (*rest)
334 fprintf (stderr, "%s ", *rest++);
335 fprintf (stderr, "\n");
336 usage (stderr, program_name);
337 ec = 1;
338 }
339 else
340 {
341 // THE MEAT GOES HERE
342 ec = mkshortcut (opts);
343 }
344 }
345 else
346 {
347 fprintf (stderr, "%s: TARGET not specified\n", program_name);
348 usage (stderr, program_name);
349 ec = 1;
350 }
351
352 exit:
353 poptFreeContext (optCon);
354 if (opts.target_arg)
355 {
356 free (opts.target_arg);
357 }
358 if (opts.name_arg)
359 {
360 free (opts.name_arg);
361 }
362 if (opts.desc_arg)
363 {
364 free (opts.desc_arg);
365 }
366 if (opts.dir_name_arg)
367 {
368 free (opts.dir_name_arg);
369 }
370 if (opts.argument_arg)
371 {
372 free (opts.argument_arg);
373 }
374 if (opts.icon_name_arg)
375 {
376 free (opts.icon_name_arg);
377 }
378 free (program_name);
379 return (ec);
380 }
381
382 static char *
383 xstrndup (const char *string, size_t n)
384 {
385 char *s = strndup (string, n);
386 if (!s)
387 {
388 fprintf (stderr, "%s: out of memory\n", program_name);
389 exit(2);
390 }
391 return s;
392 }
393
394 static char *
395 xstrncat (char **dest, const char *add, size_t n)
396 {
397 size_t len = strlen (*dest) + n + 1;
398 char *s = (char *) realloc (*dest, len * sizeof (char));
399 if (!s)
400 {
401 fprintf (stderr, "%s: out of memory\n", program_name);
402 exit(2);
403 }
404 *dest = s;
405 return strncat (*dest, add, n);
406 }
407
408 int
409 mkshortcut (optvals opts)
410 {
411 char* link_name = NULL;
412 char* exe_name = NULL;
413 char* dir_name = NULL;
414 char* desc = NULL;
415 char *buf_str, *tmp_str, *base_str;
416 int tmp;
417
418 /* For OLE interface */
419 LPITEMIDLIST id;
420 HRESULT hres;
421 IShellLink *shell_link;
422 IPersistFile *persist_file;
423 WCHAR widepath[MAX_PATH];
424 char link_path[MAX_PATH];
425
426 /* If there's a colon in the TARGET, it should be a URL */
427 if (strchr (opts.target_arg, ':') != NULL)
428 {
429 /* Nope, somebody's trying a W32 path */
430 if (opts.target_arg[1] == ':')
431 {
432 fprintf (stderr, "%s: all paths must be in POSIX format\n",
433 program_name);
434 usage (stderr, program_name);
435 return (1);
436 }
437 exe_name = xstrndup (opts.target_arg, strlen(opts.target_arg));
438 dir_name = xstrndup ("", 0); /* No working dir for URL */
439 }
440 /* Convert TARGET to win32 path */
441 else
442 {
443 buf_str = xstrndup (opts.target_arg, strlen(opts.target_arg));
444 exe_name = (char *) cygwin_create_path (CCP_POSIX_TO_WIN_A,
445 opts.target_arg);
446 if (!exe_name)
447 {
448 fprintf (stderr, "%s: error converting posix path to win32 (%s)\n",
449 program_name, strerror(errno));
450 free (buf_str);
451 return 2;
452 }
453
454 /* Get a working dir from 'w' option */
455 if (opts.dir_name_arg != NULL)
456 {
457 if (strchr (opts.dir_name_arg, ':') != NULL)
458 {
459 free (buf_str);
460 free (exe_name);
461 fprintf (stderr, "%s: all paths must be in POSIX format\n",
462 program_name);
463 usage (stderr, program_name);
464 return (1);
465 }
466 dir_name = (char *) cygwin_create_path (CCP_POSIX_TO_WIN_A,
467 opts.dir_name_arg);
468 if (!dir_name)
469 {
470 fprintf (stderr, "%s: error converting posix path to win32 (%s)\n",
471 program_name, strerror(errno));
472 free (buf_str);
473 free (exe_name);
474 return 2;
475 }
476 }
477 /* Get a working dir from the exepath */
478 else
479 {
480 tmp_str = strrchr (exe_name, '\\');
481 tmp = strlen (exe_name) - strlen (tmp_str);
482 dir_name = xstrndup (exe_name, tmp);
483 dir_name[tmp] = '\0';
484 }
485 if (buf_str) free (buf_str);
486 }
487
488 /* Generate a name for the link if not given */
489 if (opts.name_arg == NULL)
490 {
491 /* Strip trailing /'s if any */
492 buf_str = xstrndup (opts.target_arg, strlen(opts.target_arg));
493 base_str = buf_str;
494 tmp_str = buf_str;
495 tmp = strlen (buf_str) - 1;
496 while (strrchr (buf_str, '/') == (buf_str + tmp))
497 {
498 buf_str[tmp] = '\0';
499 tmp--;
500 }
501 /* Get basename */
502 while (*buf_str)
503 {
504 if (*buf_str == '/')
505 tmp_str = buf_str + 1;
506 buf_str++;
507 }
508 link_name = xstrndup (tmp_str, strlen (tmp_str));
509 free (base_str);
510 }
511 /* User specified a name, so check it and convert */
512 else
513 {
514 if (opts.desktop_flag || opts.smprograms_flag)
515 {
516 /* Cannot have absolute path relative to Desktop/SM Programs */
517 if (opts.name_arg[0] == '/')
518 {
519 fprintf (stderr,
520 "%s: absolute pathnames not allowed with -D/-P\n",
521 program_name);
522 usage (stderr, program_name);
523 return (1);
524 }
525 }
526 /* Sigh. Another W32 path */
527 if (strchr (opts.name_arg, ':') != NULL)
528 {
529 fprintf (stderr, "%s: all paths must be in POSIX format\n",
530 program_name);
531 usage (stderr, program_name);
532 return (1);
533 }
534 link_name = (char *) cygwin_create_path (
535 CCP_POSIX_TO_WIN_A | CCP_RELATIVE, opts.name_arg);
536 if (!link_name)
537 {
538 fprintf (stderr, "%s: error converting posix path to win32 (%s)\n",
539 program_name, strerror(errno));
540 return 2;
541 }
542 }
543
544 /* Add suffix to link name if necessary */
545 if (strlen (link_name) > 4)
546 {
547 tmp = strlen (link_name) - 4;
548 if (strncmp (link_name + tmp, ".lnk", 4) != 0)
549 xstrncat (&link_name, ".lnk", 4);
550 }
551 else
552 xstrncat (&link_name, ".lnk", 4);
553
554 /* Prepend relative path if necessary */
555 if (opts.desktop_flag)
556 {
557 char local_buf[MAX_PATH];
558 buf_str = xstrndup (link_name, strlen (link_name));
559
560 if (!opts.allusers_flag)
561 SHGetSpecialFolderLocation (NULL, CSIDL_DESKTOPDIRECTORY, &id);
562 else
563 SHGetSpecialFolderLocation (NULL, CSIDL_COMMON_DESKTOPDIRECTORY, &id);
564 SHGetPathFromIDList (id, local_buf);
565 /* Make sure Win95 without "All Users" has output */
566 if (strlen (local_buf) == 0)
567 {
568 SHGetSpecialFolderLocation (NULL, CSIDL_DESKTOPDIRECTORY, &id);
569 SHGetPathFromIDList (id, local_buf);
570 }
571 free (link_name);
572 link_name = xstrndup (local_buf, strlen (local_buf));
573 xstrncat (&link_name, "\\", 1);
574 xstrncat (&link_name, buf_str, strlen (buf_str));
575 free (buf_str);
576 }
577
578 if (opts.smprograms_flag)
579 {
580 char local_buf[MAX_PATH];
581 buf_str = xstrndup (link_name, strlen (link_name));
582
583 if (!opts.allusers_flag)
584 SHGetSpecialFolderLocation (NULL, CSIDL_PROGRAMS, &id);
585 else
586 SHGetSpecialFolderLocation (NULL, CSIDL_COMMON_PROGRAMS, &id);
587 SHGetPathFromIDList (id, local_buf);
588 /* Make sure Win95 without "All Users" has output */
589 if (strlen (local_buf) == 0)
590 {
591 SHGetSpecialFolderLocation (NULL, CSIDL_PROGRAMS, &id);
592 SHGetPathFromIDList (id, local_buf);
593 }
594 free (link_name);
595 link_name = xstrndup (local_buf, strlen (local_buf));
596 xstrncat (&link_name, "\\", 1);
597 xstrncat (&link_name, buf_str, strlen (buf_str));
598 free (buf_str);
599 }
600
601 /* After Windows 7, saving link to relative path fails; work around that */
602 hres = GetFullPathName (link_name, sizeof (link_path), link_path, 0);
603 if (hres == 0)
604 {
605 fprintf (stderr, "%s: Could not qualify link name\n", program_name);
606 return 2;
607 }
608 free (link_name);
609 link_name = xstrndup (link_path, strlen (link_path));
610
611 /* Setup description text */
612 if (opts.desc_arg != NULL)
613 {
614 desc = xstrndup (opts.desc_arg, strlen (opts.desc_arg));
615 }
616 else
617 {
618 /* Put the POSIX path in the "Description", just to be nice */
619 desc = (char *) cygwin_create_path (CCP_WIN_A_TO_POSIX, exe_name);
620 if (!desc)
621 {
622 fprintf (stderr, "%s: error converting win32 path to posix (%s)\n",
623 program_name, strerror(errno));
624 return 2;
625 }
626 }
627
628 /* Beginning of Windows interface */
629 hres = OleInitialize (NULL);
630 if (hres != S_FALSE && hres != S_OK)
631 {
632 fprintf (stderr, "%s: Could not initialize OLE interface\n",
633 program_name);
634 free (link_name);
635 free (exe_name);
636 free (dir_name);
637 free (desc);
638 return (3);
639 }
640
641 hres =
642 CoCreateInstance (&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
643 &IID_IShellLink, (void **) &shell_link);
644 if (SUCCEEDED (hres))
645 {
646 hres =
647 shell_link->lpVtbl->QueryInterface (shell_link, &IID_IPersistFile,
648 (void **) &persist_file);
649 if (SUCCEEDED (hres))
650 {
651 shell_link->lpVtbl->SetPath (shell_link, exe_name);
652 shell_link->lpVtbl->SetDescription (shell_link, desc);
653 shell_link->lpVtbl->SetWorkingDirectory (shell_link, dir_name);
654 if (opts.argument_arg)
655 shell_link->lpVtbl->SetArguments (shell_link, opts.argument_arg);
656 if (opts.icon_flag)
657 shell_link->lpVtbl->SetIconLocation (shell_link,
658 opts.icon_name_arg,
659 opts.offset);
660 if (opts.show_flag != SW_SHOWNORMAL)
661 shell_link->lpVtbl->SetShowCmd (shell_link, opts.show_flag);
662
663
664 /* Make link name Unicode-compliant */
665 hres =
666 MultiByteToWideChar (CP_ACP, 0, link_name, -1, widepath,
667 MAX_PATH);
668 if (!SUCCEEDED (hres))
669 {
670 fprintf (stderr, "%s: Unicode translation failed%d\n",
671 program_name, hres);
672 free (link_name);
673 free (exe_name);
674 free (dir_name);
675 free (desc);
676 return (3);
677 }
678 hres = persist_file->lpVtbl->Save (persist_file, widepath, TRUE);
679 if (!SUCCEEDED (hres))
680 {
681 fprintf (stderr,
682 "%s: Saving \"%s\" failed; does the target directory exist?\n",
683 program_name, link_name);
684 free (link_name);
685 free (exe_name);
686 free (dir_name);
687 free (desc);
688 return (3);
689 }
690 persist_file->lpVtbl->Release (persist_file);
691 shell_link->lpVtbl->Release (shell_link);
692
693 /* If we are creating shortcut for all users, ensure it is readable by all users */
694 if (opts.allusers_flag)
695 {
696 char *posixpath = (char *) cygwin_create_path (
697 CCP_WIN_W_TO_POSIX | CCP_ABSOLUTE, widepath);
698 if (posixpath && *posixpath)
699 {
700 struct stat statbuf;
701 if (stat(posixpath, &statbuf))
702 {
703 fprintf (stderr,
704 "%s: stat \"%s\" failed\n",
705 program_name, posixpath);
706 }
707 else if (chmod(posixpath, statbuf.st_mode|S_IRUSR|S_IRGRP|S_IROTH))
708 {
709 fprintf (stderr,
710 "%s: chmod \"%s\" failed\n",
711 program_name, posixpath);
712 }
713 }
714 free(posixpath);
715 }
716 free (link_name);
717 free (exe_name);
718 free (dir_name);
719 free (desc);
720 return (0);
721 }
722 else
723 {
724 fprintf (stderr, "%s: QueryInterface failed\n", program_name);
725 free (link_name);
726 free (exe_name);
727 free (dir_name);
728 free (desc);
729 return (3);
730 }
731 }
732 else
733 {
734 fprintf (stderr, "%s: CoCreateInstance failed\n", program_name);
735 free (link_name);
736 free (exe_name);
737 free (dir_name);
738 free (desc);
739 return (3);
740 }
741 }
742
743 static const char *
744 getVersion ()
745 {
746 return versionID;
747 }
748
749 static void
750 printTopDescription (FILE * f, char *name)
751 {
752 char s[20];
753 fprintf (f, "%s is part of cygutils version %s\n", name, getVersion ());
754 fprintf (f, " create a Windows shortcut\n\n");
755 }
756 static void
757 printBottomDescription (FILE * f, char *name)
758 {
759 fprintf (f,
760 "\nNOTE: All filename arguments must be in unix (POSIX) format\n");
761 }
762
763 static
764 printLicense (FILE * f, char *name)
765 {
766 fprintf (f,
767 "This program is free software: you can redistribute it and/or modify\n"
768 "it under the terms of the GNU General Public License as published by\n"
769 "the Free Software Foundation, either version 3 of the License, or\n"
770 "(at your option) any later version.\n\n"
771 "This program is distributed in the hope that it will be useful,\n"
772 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
773 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
774 "GNU General Public License for more details.\n\n"
775 "You should have received a copy of the GNU General Public License\n"
776 "along with this program. If not, see <http://www.gnu.org/licenses/>.\n\n"
777 "See the COPYING file for full license information.\n");
778 }
779
780 static void
781 usage (FILE * f, char *name)
782 {
783 poptPrintUsage (optCon, f, 0);
784 }
785
786 static void
787 help (FILE * f, char *name)
788 {
789 printTopDescription (f, name);
790 poptPrintHelp (optCon, f, 0);
791 printBottomDescription (f, name);
792 }
793
794 static void
795 version (FILE * f, char *name)
796 {
797 printTopDescription (f, name);
798 fprintf (f, copyrightID);
799 }
800
801 static void
802 license (FILE * f, char *name)
803 {
804 printTopDescription (f, name);
805 printLicense (f, name);
806 }
This page took 0.071026 seconds and 6 git commands to generate.