1b73f3b8aSAxel Dörfler/*
2b73f3b8aSAxel Dörfler * Copyright 2002-2007, Haiku, Inc. All rights reserved.
3b73f3b8aSAxel Dörfler * Distributed under the terms of the MIT License.
4b73f3b8aSAxel Dörfler *
5b73f3b8aSAxel Dörfler * Authors:
6b73f3b8aSAxel Dörfler *		Ryan Fleet
7b73f3b8aSAxel Dörfler *		Vasilis Kaoutsis
8b73f3b8aSAxel Dörfler */
96b2bd871SFrançois Revol
10b73f3b8aSAxel Dörfler
11b73f3b8aSAxel Dörfler#include <Application.h>
126b2bd871SFrançois Revol#include <AppFileInfo.h>
136b2bd871SFrançois Revol
14b73f3b8aSAxel Dörfler#include <stdio.h>
15b73f3b8aSAxel Dörfler#include <string.h>
16b73f3b8aSAxel Dörfler
176b2bd871SFrançois Revol
18b73f3b8aSAxel Dörflervoid
19b73f3b8aSAxel Dörflerusage()
206b2bd871SFrançois Revol{
21b73f3b8aSAxel Dörfler	printf("usage: version [OPTION] FILENAME [FILENAME2, ...]\n"
22b73f3b8aSAxel Dörfler		"Returns the version of a file.\n\n"
23b73f3b8aSAxel Dörfler		"        -h, --help              this usage message\n"
24b73f3b8aSAxel Dörfler		"        -l, --long              print long version information of FILENAME\n"
25b73f3b8aSAxel Dörfler		"        -n, --numerical         print in numerical mode\n"
26b73f3b8aSAxel Dörfler		"                                (Major miDdle miNor Variety Internal)\n"
27b73f3b8aSAxel Dörfler		"        -s, --system            print system version instead of app version\n"
28b73f3b8aSAxel Dörfler		"        --version               print version information for this command\n");
296b2bd871SFrançois Revol}
306b2bd871SFrançois Revol
316b2bd871SFrançois Revol
32b73f3b8aSAxel Dörflerstatus_t
33b73f3b8aSAxel Dörflerget_version(const char *filename, version_kind kind, bool longFlag, bool numericalFlag)
346b2bd871SFrançois Revol{
356b2bd871SFrançois Revol	BFile file(filename, O_RDONLY);
36b73f3b8aSAxel Dörfler	if (file.InitCheck() != B_OK) {
376b2bd871SFrançois Revol		printf("Couldn't get file info!\n");
38b73f3b8aSAxel Dörfler		return B_FILE_ERROR;
396b2bd871SFrançois Revol	}
40b73f3b8aSAxel Dörfler
416b2bd871SFrançois Revol	BAppFileInfo info(&file);
42b73f3b8aSAxel Dörfler	if (info.InitCheck() != B_OK) {
436b2bd871SFrançois Revol		printf("Couldn't get file info!\n");
44b73f3b8aSAxel Dörfler		return B_FILE_ERROR;
456b2bd871SFrançois Revol	}
46b73f3b8aSAxel Dörfler
476b2bd871SFrançois Revol	version_info version;
48b73f3b8aSAxel Dörfler	if (info.GetVersionInfo(&version, kind) != B_OK) {
496b2bd871SFrançois Revol		printf("Version unknown!\n");
50b73f3b8aSAxel Dörfler		return B_ERROR;
516b2bd871SFrançois Revol	}
52b73f3b8aSAxel Dörfler
53b73f3b8aSAxel Dörfler	if (longFlag) {
546b2bd871SFrançois Revol		printf("%s\n", version.long_info);
55b73f3b8aSAxel Dörfler		return B_OK;
566b2bd871SFrançois Revol	}
57b73f3b8aSAxel Dörfler
58b73f3b8aSAxel Dörfler	if (numericalFlag) {
59312640b1SMurai Takashi		printf("%" B_PRIu32 " ", version.major);
60312640b1SMurai Takashi		printf("%" B_PRIu32 " ", version.middle);
61312640b1SMurai Takashi		printf("%" B_PRIu32 " ", version.minor);
62b73f3b8aSAxel Dörfler
63b73f3b8aSAxel Dörfler		switch (version.variety) {
64b73f3b8aSAxel Dörfler			case B_DEVELOPMENT_VERSION:
65b73f3b8aSAxel Dörfler				printf("d ");
66b73f3b8aSAxel Dörfler				break;
67b73f3b8aSAxel Dörfler
68b73f3b8aSAxel Dörfler			case B_ALPHA_VERSION:
69b73f3b8aSAxel Dörfler				printf("a ");
70b73f3b8aSAxel Dörfler				break;
71b73f3b8aSAxel Dörfler
72b73f3b8aSAxel Dörfler			case B_BETA_VERSION:
73b73f3b8aSAxel Dörfler				printf("b ");
74b73f3b8aSAxel Dörfler				break;
75b73f3b8aSAxel Dörfler
76b73f3b8aSAxel Dörfler			case B_GAMMA_VERSION:
77b73f3b8aSAxel Dörfler				printf("g ");
78b73f3b8aSAxel Dörfler				break;
79b73f3b8aSAxel Dörfler
80b73f3b8aSAxel Dörfler			case B_GOLDEN_MASTER_VERSION:
81b73f3b8aSAxel Dörfler				printf("gm ");
82b73f3b8aSAxel Dörfler				break;
83b73f3b8aSAxel Dörfler
84b73f3b8aSAxel Dörfler			case B_FINAL_VERSION:
85b73f3b8aSAxel Dörfler				printf("f ");
86b73f3b8aSAxel Dörfler				break;
87b73f3b8aSAxel Dörfler		}
88b73f3b8aSAxel Dörfler
89312640b1SMurai Takashi		printf("%" B_PRIu32 "\n", version.internal);
90b73f3b8aSAxel Dörfler		return B_OK;
916b2bd871SFrançois Revol	}
92b73f3b8aSAxel Dörfler
936b2bd871SFrançois Revol	printf("%s\n", version.short_info);
94b73f3b8aSAxel Dörfler	return B_OK;
956b2bd871SFrançois Revol}
966b2bd871SFrançois Revol
976b2bd871SFrançois Revol
98b73f3b8aSAxel Dörfler/*!
99b73f3b8aSAxel Dörfler	determines whether  \a string1 contains at least one or more of the characters
100b73f3b8aSAxel Dörfler	of \a string2 but none of which \a string2 doesn't contain.
101b73f3b8aSAxel Dörfler
102b73f3b8aSAxel Dörfler	examples:
1036b2bd871SFrançois Revol	true == ("hel" == "help"); true == ("help" == "help"); true == ("h" == "help");
1046b2bd871SFrançois Revol	false == ("held" == "help"); false == ("helped" == "help");
1056b2bd871SFrançois Revol*/
106b73f3b8aSAxel Dörflerbool
107b73f3b8aSAxel Dörflerstr_less_equal(const char *str1, const char *str2)
1086b2bd871SFrançois Revol{
1096b2bd871SFrançois Revol	char *ptr1 = const_cast<char*>(str1);
1106b2bd871SFrançois Revol	char *ptr2 = const_cast<char*>(str2);
111b73f3b8aSAxel Dörfler
112b73f3b8aSAxel Dörfler	while (*ptr1 != '\0') {
113b73f3b8aSAxel Dörfler		if (*ptr1 != *ptr2)
1146b2bd871SFrançois Revol			return false;
1156b2bd871SFrançois Revol		++ptr1;
1166b2bd871SFrançois Revol		++ptr2;
1176b2bd871SFrançois Revol	}
1186b2bd871SFrançois Revol	return true;
1196b2bd871SFrançois Revol}
1206b2bd871SFrançois Revol
1216b2bd871SFrançois Revol
122b73f3b8aSAxel Dörflerint
123b73f3b8aSAxel Dörflermain(int argc, char *argv[])
1246b2bd871SFrançois Revol{
125b73f3b8aSAxel Dörfler	BApplication app("application/x.vnd.Haiku-version");
1266b2bd871SFrançois Revol	version_kind kind = B_APP_VERSION_KIND;
127b73f3b8aSAxel Dörfler	bool longFlag = false;
128b73f3b8aSAxel Dörfler	bool numericalFlag = false;
1296b2bd871SFrançois Revol	int i;
130b73f3b8aSAxel Dörfler
131b73f3b8aSAxel Dörfler	if (argc < 2) {
132b73f3b8aSAxel Dörfler		usage();
1336b2bd871SFrançois Revol		return 0;
134b73f3b8aSAxel Dörfler	}
1356b2bd871SFrançois Revol
136b73f3b8aSAxel Dörfler	for (i = 1; i < argc; ++i) {
137b73f3b8aSAxel Dörfler		if (argv[i][0] == '-') {
1386b2bd871SFrançois Revol			char *ptr = argv[i];
1396b2bd871SFrançois Revol			++ptr;
140b73f3b8aSAxel Dörfler
141b73f3b8aSAxel Dörfler			if (*ptr == '-') {
142b73f3b8aSAxel Dörfler				bool lessEqual = false;
1436b2bd871SFrançois Revol				++ptr;
144b73f3b8aSAxel Dörfler
145b73f3b8aSAxel Dörfler				if (*ptr == 'h') {
146b73f3b8aSAxel Dörfler					lessEqual = str_less_equal(ptr, "help");
147b73f3b8aSAxel Dörfler					if (lessEqual) {
148b73f3b8aSAxel Dörfler						usage();
1496b2bd871SFrançois Revol						return 0;
1506b2bd871SFrançois Revol					}
151b73f3b8aSAxel Dörfler				} else if (*ptr == 'l') {
152b73f3b8aSAxel Dörfler					lessEqual = str_less_equal(ptr, "long");
153b73f3b8aSAxel Dörfler					if (lessEqual)
154b73f3b8aSAxel Dörfler						longFlag = true;
155b73f3b8aSAxel Dörfler				} else if (*ptr == 'n') {
156b73f3b8aSAxel Dörfler					lessEqual = str_less_equal(ptr, "numerical");
157b73f3b8aSAxel Dörfler					if (lessEqual)
158b73f3b8aSAxel Dörfler						numericalFlag = true;
159b73f3b8aSAxel Dörfler				} else if (*ptr == 's') {
160b73f3b8aSAxel Dörfler					lessEqual = str_less_equal(ptr, "system");
161b73f3b8aSAxel Dörfler					if (lessEqual)
1626b2bd871SFrançois Revol						kind = B_SYSTEM_VERSION_KIND;
163b73f3b8aSAxel Dörfler				} else if (*ptr == 'v') {
164b73f3b8aSAxel Dörfler					lessEqual = str_less_equal(ptr, "version");
165b73f3b8aSAxel Dörfler					if (lessEqual) {
166b73f3b8aSAxel Dörfler						get_version(argv[0], B_APP_VERSION_KIND, false, false);
1676b2bd871SFrançois Revol						return 0;
1686b2bd871SFrançois Revol					}
1696b2bd871SFrançois Revol				}
170b73f3b8aSAxel Dörfler
171b73f3b8aSAxel Dörfler				if (!lessEqual)
1726b2bd871SFrançois Revol					printf("%s unrecognized option `%s'\n", argv[0], argv[i]);
173b73f3b8aSAxel Dörfler			} else {
174b73f3b8aSAxel Dörfler				while (*ptr != '\0') {
175b73f3b8aSAxel Dörfler					if (*ptr == 'h') {
176b73f3b8aSAxel Dörfler						usage();
177b73f3b8aSAxel Dörfler						return 0;
178b73f3b8aSAxel Dörfler					} else if (*ptr == 's')
179b73f3b8aSAxel Dörfler						kind = B_SYSTEM_VERSION_KIND;
180b73f3b8aSAxel Dörfler					else if (*ptr == 'l')
181b73f3b8aSAxel Dörfler						longFlag = true;
182b73f3b8aSAxel Dörfler					else if (*ptr == 'n')
183b73f3b8aSAxel Dörfler						numericalFlag = true;
184b73f3b8aSAxel Dörfler					else {
185b73f3b8aSAxel Dörfler						printf("%s: invalid option -- %c\n", argv[0], *ptr);
186b73f3b8aSAxel Dörfler						return 1;
187b73f3b8aSAxel Dörfler					}
188b73f3b8aSAxel Dörfler
189b73f3b8aSAxel Dörfler					if (argc < 3) {
190b73f3b8aSAxel Dörfler						printf("%s: missing FILENAME(S) \n", argv[0]);
191b73f3b8aSAxel Dörfler						return 1;
192b73f3b8aSAxel Dörfler					}
193b73f3b8aSAxel Dörfler
194b73f3b8aSAxel Dörfler					++ptr;
1956b2bd871SFrançois Revol				}
1966b2bd871SFrançois Revol			}
1976b2bd871SFrançois Revol		}
1986b2bd871SFrançois Revol	}
199b73f3b8aSAxel Dörfler
200b73f3b8aSAxel Dörfler	for (i = 1; i < argc; ++i) {
201b73f3b8aSAxel Dörfler		if (argv[i][0] != '-'
202b73f3b8aSAxel Dörfler			&& get_version(argv[i], kind, longFlag, numericalFlag) != B_OK)
203b73f3b8aSAxel Dörfler			return 1;
2046b2bd871SFrançois Revol	}
2056b2bd871SFrançois Revol
206b73f3b8aSAxel Dörfler	return 0;
2076b2bd871SFrançois Revol}