static void version_copyright() { static char *text[] = { "All rights reserved.", "", "The %s program comes with ABSOLUTELY NO WARRANTY;", "for details use the '%s -VERSion License' command.", "The %s program is free software, and you are welcome", "to redistribute it under certain conditions; for", "details use the '%s -VERSion License' command.", }; char **cpp; char *progname; progname = progname_get(); printf("%s version %s\n", progname, version_stamp()); printf("Copyright (C) %s Peter Miller;\n", copyright_years()); for (cpp = text; cpp < ENDOF(text); ++cpp) { printf(*cpp, progname); fputc('\n', stdout); } }
/** * Parse vendor string and fill supplied version structure `vs'. * * @returns OK if we were able to parse correctly. */ bool version_fill(const char *version, version_t *vs) { if (!version_parse(version, vs, NULL)) return FALSE; version_stamp(version, vs); /* Optional, set to 0 if missing */ return TRUE; }
/** * Initialize version string. */ void G_COLD version_init(void) { time_t now; version_string = ostrdup_readonly(version_build_string()); now = tm_time(); { bool ok; const char *end; ok = version_parse(version_string, &our_version, &end); g_assert(ok); ok = version_ext_parse(end, &our_ext_version); g_assert(ok); } g_info("%s", version_string); version_stamp(version_string, &our_version); g_assert(our_version.timestamp != 0); { char buf[128]; str_bprintf(buf, sizeof(buf), "%s/%s%s (%s)", product_name(), product_version(), product_build_full(), product_date()); version_short_string = ostrdup_readonly(buf); } last_rel_version = our_version; /* struct copy */ last_dev_version = our_version; /* struct copy */ our_ext_version.version = our_version; /* struct copy */ /* * The version code is a one-byte encoding of the year/month, since * what matters is not much the version number as to the age of the * servent... The version code is transmitted in pongs via GGEP "VC". */ if (our_version.timestamp) { struct tm *tmp = localtime(&our_version.timestamp); version_code = (((tmp->tm_year + 1900 - 2000) & 0x0f) << 4) | (tmp->tm_mon + 1); } else version_code = 0; /* * The property system is not up when this is called, but we need * to set this variable correctly. */ if ( tok_is_ancient(now) || delta_time(now, our_version.timestamp) > VERSION_ANCIENT_WARN ) { *deconstify_bool(&GNET_PROPERTY(ancient_version)) = TRUE; } }
/** * Check version of servent, and if it's a gtk-gnutella more recent than we * are, record that fact and change the status bar. * * The `addr' is being passed solely for the tok_version_valid() call. * * @returns TRUE if we properly checked the version, FALSE if we got something * looking as gtk-gnutella but which failed the token-based sanity checks. */ bool version_check(const char *str, const char *token, const host_addr_t addr) { version_t their_version; version_ext_t their_version_ext; version_t *target_version; int cmp; const char *version; const char *end; bool extended; if (!version_parse(str, &their_version, &end)) return TRUE; /* Not gtk-gnutella, or unparseable */ /* * Check for extended version information (git commit ID, dirty status). */ ZERO(&their_version_ext); extended = version_ext_parse(end, &their_version_ext); if (!extended) { /* Structure could have been partially filled */ ZERO(&their_version_ext); } /* * Is their version a development one, or a release? */ if (their_version.tag == 'u') target_version = &last_dev_version; else target_version = &last_rel_version; cmp = version_cmp(target_version, &their_version); if (GNET_PROPERTY(version_debug) > 1) version_dump(str, &their_version, cmp == 0 ? "=" : cmp > 0 ? "-" : "+"); /* * Check timestamp. */ version_stamp(str, &their_version); their_version_ext.version = their_version; /* Struct copy */ if (GNET_PROPERTY(version_debug) > 3) g_debug("VERSION time=%d", (int) their_version.timestamp); /* * If version claims something older than TOKEN_START_DATE, then * there must be a token present. */ if (delta_time(their_version.timestamp, 0) >= TOKEN_START_DATE) { tok_error_t error; if (token == NULL) { if (GNET_PROPERTY(version_debug)) { g_debug("got GTKG vendor string \"%s\" without token!", str); } return FALSE; /* Can't be correct */ } error = tok_version_valid(str, token, strlen(token), addr); /* * Unfortunately, if our token has expired, we can no longer * validate the tokens of the remote peers, since they are using * a different set of keys. * * This means an expired GTKG will blindly trust well-formed remote * tokens at face value. But it's their fault, they should not run * an expired version! * --RAM, 2005-12-21 */ if (error == TOK_BAD_KEYS && tok_is_ancient(tm_time())) error = TOK_OK; /* Our keys have expired, cannot validate */ if (error != TOK_OK) { if (GNET_PROPERTY(version_debug)) { g_debug("vendor string \"%s\" [%s] has wrong token " "\"%s\": %s ", str, host_addr_to_string(addr), token, tok_strerror(error)); } return FALSE; } /* * OK, so now we know we can "trust" this version string as being * probably genuine. It makes sense to extract version information * out of it. */ } if (cmp > 0) /* We're more recent */ return TRUE; /* * If timestamp is greater and we were comparing against a stable * release, and cmp == 0, then this means an update in SVN about * a "released" version, probably alpha/beta. */ if ( cmp == 0 && (delta_time(their_version.timestamp, target_version->timestamp) > 0 || their_version.build > target_version->build) && target_version == &last_rel_version ) { if (GNET_PROPERTY(version_debug) > 3) g_debug("VERSION is a SVN update of a release"); if (version_build_cmp(&last_dev_version, &their_version) > 0) { if (GNET_PROPERTY(version_debug) > 3) g_debug("VERSION is less recent than latest dev we know"); return TRUE; } target_version = &last_dev_version; } /* * Their version is more recent, but is unstable -- only continue if * our version is also unstable. */ if (cmp < 0 && their_version.tag == 'u' && our_version.tag != 'u') return TRUE; if ( delta_time(their_version.timestamp, target_version->timestamp) < 0 || their_version.build <= target_version->build ) return TRUE; if ( delta_time(their_version.timestamp, our_version.timestamp) == 0 && their_version.build <= our_version.build ) return TRUE; /* * We found a more recent version than the last version seen. */ if (GNET_PROPERTY(version_debug) > 1) g_debug("more recent %s VERSION \"%s\"", target_version == &last_dev_version ? "dev" : "rel", str); *target_version = their_version; /* struct copy */ /* * Signal new version to user. * * Unless they run a development version, don't signal development * updates to them: they're probably not interested. */ version = version_ext_str(&their_version_ext, FALSE); /* No OS name */ g_message("more recent %s version of gtk-gnutella: %s", target_version == &last_dev_version ? "development" : "released", version); if (target_version == &last_rel_version) version_new_found(version, TRUE); else if (our_version.tag == 'u') version_new_found(version, FALSE); return TRUE; }