1bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly// Copyright (c) 2006, Google Inc. 2bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly// All rights reserved. 3bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly// 4bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly// Redistribution and use in source and binary forms, with or without 5bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly// modification, are permitted provided that the following conditions are 6bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly// met: 7bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly// 8bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly// * Redistributions of source code must retain the above copyright 9bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly// notice, this list of conditions and the following disclaimer. 10bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly// * Redistributions in binary form must reproduce the above 11bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly// copyright notice, this list of conditions and the following disclaimer 12bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly// in the documentation and/or other materials provided with the 13bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly// distribution. 14bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly// * Neither the name of Google Inc. nor the names of its 15bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly// contributors may be used to endorse or promote products derived from 16bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly// this software without specific prior written permission. 17bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly// 18bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly 30bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly// symupload.cc: Upload a symbol file to a HTTP server. The upload is sent as 31bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly// a multipart/form-data POST request with the following parameters: 32bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly// code_file: the basename of the module, e.g. "app" 33bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly// debug_file: the basename of the debugging file, e.g. "app" 34bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly// debug_identifier: the debug file's identifier, usually consisting of 35bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly// the guid and age embedded in the pdb, e.g. 36bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly// "11111111BBBB3333DDDD555555555555F" 37bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly// version: the file version of the module, e.g. "1.2.3.4" 38bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly// os: the operating system that the module was built for 39bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly// cpu: the CPU that the module was built for 40bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly// symbol_file: the contents of the breakpad-format symbol file 41bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly 42e1930985430ce289f4fe8525f51050e5d78cc44eted.mielczarek#include <assert.h> 43e1930985430ce289f4fe8525f51050e5d78cc44eted.mielczarek#include <stdio.h> 44c0ec51afe09c266c49dfeb2dd079ca6c50f119d2mmentovai#include <stdlib.h> 45e1930985430ce289f4fe8525f51050e5d78cc44eted.mielczarek#include <unistd.h> 46bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly 47bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly#include <functional> 48bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly#include <iostream> 49bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly#include <string> 50bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly#include <vector> 51bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly 52bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly#include "common/linux/http_upload.h" 53f254f8ef6a06ae1dba7c3b275a61a6d54c34accdivan.penkov@gmail.com#include "common/using_std_string.h" 54bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly 55bcd46f007919b5063164c8c5c6c2bd4dfb62681elulyusing google_breakpad::HTTPUpload; 56bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly 57bcd46f007919b5063164c8c5c6c2bd4dfb62681elulytypedef struct { 58f254f8ef6a06ae1dba7c3b275a61a6d54c34accdivan.penkov@gmail.com string symbolsPath; 59f254f8ef6a06ae1dba7c3b275a61a6d54c34accdivan.penkov@gmail.com string uploadURLStr; 60f254f8ef6a06ae1dba7c3b275a61a6d54c34accdivan.penkov@gmail.com string proxy; 61f254f8ef6a06ae1dba7c3b275a61a6d54c34accdivan.penkov@gmail.com string proxy_user_pwd; 62f254f8ef6a06ae1dba7c3b275a61a6d54c34accdivan.penkov@gmail.com string version; 63bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly bool success; 64bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly} Options; 65bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly 66f254f8ef6a06ae1dba7c3b275a61a6d54c34accdivan.penkov@gmail.comstatic void TokenizeByChar(const string &source_string, 67f254f8ef6a06ae1dba7c3b275a61a6d54c34accdivan.penkov@gmail.com int c, std::vector<string> *results) { 68bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly assert(results); 69f254f8ef6a06ae1dba7c3b275a61a6d54c34accdivan.penkov@gmail.com string::size_type cur_pos = 0, next_pos = 0; 70f254f8ef6a06ae1dba7c3b275a61a6d54c34accdivan.penkov@gmail.com while ((next_pos = source_string.find(c, cur_pos)) != string::npos) { 71bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly if (next_pos != cur_pos) 72bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly results->push_back(source_string.substr(cur_pos, next_pos - cur_pos)); 73bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly cur_pos = next_pos + 1; 74bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly } 75bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly if (cur_pos < source_string.size() && next_pos != cur_pos) 76bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly results->push_back(source_string.substr(cur_pos)); 77bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly} 78bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly 79bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly//============================================================================= 80825840253b5839c43a0d28cbc45e15e4de65b910luly// Parse out the module line which have 5 parts. 81825840253b5839c43a0d28cbc45e15e4de65b910luly// MODULE <os> <cpu> <uuid> <module-name> 82f254f8ef6a06ae1dba7c3b275a61a6d54c34accdivan.penkov@gmail.comstatic bool ModuleDataForSymbolFile(const string &file, 83f254f8ef6a06ae1dba7c3b275a61a6d54c34accdivan.penkov@gmail.com std::vector<string> *module_parts) { 84bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly assert(module_parts); 85825840253b5839c43a0d28cbc45e15e4de65b910luly const size_t kModulePartNumber = 5; 86f254f8ef6a06ae1dba7c3b275a61a6d54c34accdivan.penkov@gmail.com FILE* fp = fopen(file.c_str(), "r"); 87bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly if (fp) { 88bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly char buffer[1024]; 89bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly if (fgets(buffer, sizeof(buffer), fp)) { 90f254f8ef6a06ae1dba7c3b275a61a6d54c34accdivan.penkov@gmail.com string line(buffer); 91f254f8ef6a06ae1dba7c3b275a61a6d54c34accdivan.penkov@gmail.com string::size_type line_break_pos = line.find_first_of('\n'); 92f254f8ef6a06ae1dba7c3b275a61a6d54c34accdivan.penkov@gmail.com if (line_break_pos == string::npos) { 93486229ba5044ee2e7f49d2f6000e6535f2fca46cqsr@chromium.org assert(0 && "The file is invalid!"); 94bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly fclose(fp); 95bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly return false; 96bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly } 97bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly line.resize(line_break_pos); 98bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly const char kDelimiter = ' '; 99bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly TokenizeByChar(line, kDelimiter, module_parts); 100bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly if (module_parts->size() != kModulePartNumber) 101bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly module_parts->clear(); 102bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly } 103bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly fclose(fp); 104bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly } 105bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly 106bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly return module_parts->size() == kModulePartNumber; 107bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly} 108bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly 109bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly//============================================================================= 110f254f8ef6a06ae1dba7c3b275a61a6d54c34accdivan.penkov@gmail.comstatic string CompactIdentifier(const string &uuid) { 111f254f8ef6a06ae1dba7c3b275a61a6d54c34accdivan.penkov@gmail.com std::vector<string> components; 112bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly TokenizeByChar(uuid, '-', &components); 113f254f8ef6a06ae1dba7c3b275a61a6d54c34accdivan.penkov@gmail.com string result; 114bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly for (size_t i = 0; i < components.size(); ++i) 115bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly result += components[i]; 116bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly return result; 117bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly} 118bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly 119bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly//============================================================================= 120bcd46f007919b5063164c8c5c6c2bd4dfb62681elulystatic void Start(Options *options) { 121f254f8ef6a06ae1dba7c3b275a61a6d54c34accdivan.penkov@gmail.com std::map<string, string> parameters; 122bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly options->success = false; 123f254f8ef6a06ae1dba7c3b275a61a6d54c34accdivan.penkov@gmail.com std::vector<string> module_parts; 124bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly if (!ModuleDataForSymbolFile(options->symbolsPath, &module_parts)) { 125bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly fprintf(stderr, "Failed to parse symbol file!\n"); 126bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly return; 127bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly } 128bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly 129f254f8ef6a06ae1dba7c3b275a61a6d54c34accdivan.penkov@gmail.com string compacted_id = CompactIdentifier(module_parts[3]); 130bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly 131bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly // Add parameters 132bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly if (!options->version.empty()) 133bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly parameters["version"] = options->version; 134bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly 135825840253b5839c43a0d28cbc45e15e4de65b910luly // MODULE <os> <cpu> <uuid> <module-name> 136825840253b5839c43a0d28cbc45e15e4de65b910luly // 0 1 2 3 4 137bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly parameters["os"] = module_parts[1]; 138bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly parameters["cpu"] = module_parts[2]; 139825840253b5839c43a0d28cbc45e15e4de65b910luly parameters["debug_file"] = module_parts[4]; 140825840253b5839c43a0d28cbc45e15e4de65b910luly parameters["code_file"] = module_parts[4]; 141bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly parameters["debug_identifier"] = compacted_id; 142f254f8ef6a06ae1dba7c3b275a61a6d54c34accdivan.penkov@gmail.com string response, error; 143e1c94520b617f04213655d1e344f770a4b4eb1b9mkrebs@chromium.org long response_code; 144bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly bool success = HTTPUpload::SendRequest(options->uploadURLStr, 145bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly parameters, 146bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly options->symbolsPath, 147bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly "symbol_file", 148bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly options->proxy, 149bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly options->proxy_user_pwd, 15039edd96373aaca98df3f02c51aaa364f6242d266ted.mielczarek "", 151f0a07749af99d249ed1f0dba151bb9d81e885e11ted.mielczarek &response, 152e1c94520b617f04213655d1e344f770a4b4eb1b9mkrebs@chromium.org &response_code, 153f0a07749af99d249ed1f0dba151bb9d81e885e11ted.mielczarek &error); 154bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly 155e1c94520b617f04213655d1e344f770a4b4eb1b9mkrebs@chromium.org if (!success) { 156f0a07749af99d249ed1f0dba151bb9d81e885e11ted.mielczarek printf("Failed to send symbol file: %s\n", error.c_str()); 15756bbcbb35a2e58cd93de7d3b7d5b4327ea66e676mattdr.breakpad@gmail.com printf("Response code: %ld\n", response_code); 158bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly printf("Response:\n"); 159bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly printf("%s\n", response.c_str()); 160e1c94520b617f04213655d1e344f770a4b4eb1b9mkrebs@chromium.org } else if (response_code == 0) { 161e1c94520b617f04213655d1e344f770a4b4eb1b9mkrebs@chromium.org printf("Failed to send symbol file: No response code\n"); 162e1c94520b617f04213655d1e344f770a4b4eb1b9mkrebs@chromium.org } else if (response_code != 200) { 163e1c94520b617f04213655d1e344f770a4b4eb1b9mkrebs@chromium.org printf("Failed to send symbol file: Response code %ld\n", response_code); 164e1c94520b617f04213655d1e344f770a4b4eb1b9mkrebs@chromium.org printf("Response:\n"); 165e1c94520b617f04213655d1e344f770a4b4eb1b9mkrebs@chromium.org printf("%s\n", response.c_str()); 166e1c94520b617f04213655d1e344f770a4b4eb1b9mkrebs@chromium.org } else { 167e1c94520b617f04213655d1e344f770a4b4eb1b9mkrebs@chromium.org printf("Successfully sent the symbol file.\n"); 168bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly } 169bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly options->success = success; 170bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly} 171bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly 172bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly//============================================================================= 173bcd46f007919b5063164c8c5c6c2bd4dfb62681elulystatic void 174bcd46f007919b5063164c8c5c6c2bd4dfb62681elulyUsage(int argc, const char *argv[]) { 175bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly fprintf(stderr, "Submit symbol information.\n"); 176bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly fprintf(stderr, "Usage: %s [options...] <symbols> <upload-URL>\n", argv[0]); 177bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly fprintf(stderr, "Options:\n"); 178bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly fprintf(stderr, "<symbols> should be created by using the dump_syms tool.\n"); 179bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly fprintf(stderr, "<upload-URL> is the destination for the upload\n"); 180bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly fprintf(stderr, "-v:\t Version information (e.g., 1.2.3.4)\n"); 181bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly fprintf(stderr, "-x:\t <host[:port]> Use HTTP proxy on given port\n"); 182bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly fprintf(stderr, "-u:\t <user[:password]> Set proxy user and password\n"); 183bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly fprintf(stderr, "-h:\t Usage\n"); 184bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly fprintf(stderr, "-?:\t Usage\n"); 185bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly} 186bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly 187bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly//============================================================================= 188bcd46f007919b5063164c8c5c6c2bd4dfb62681elulystatic void 189bcd46f007919b5063164c8c5c6c2bd4dfb62681elulySetupOptions(int argc, const char *argv[], Options *options) { 190bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly extern int optind; 191f254f8ef6a06ae1dba7c3b275a61a6d54c34accdivan.penkov@gmail.com int ch; 192bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly 193bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly while ((ch = getopt(argc, (char * const *)argv, "u:v:x:h?")) != -1) { 194bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly switch (ch) { 195bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly case 'u': 196bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly options->proxy_user_pwd = optarg; 197bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly break; 198bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly case 'v': 199bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly options->version = optarg; 200bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly break; 201bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly case 'x': 202bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly options->proxy = optarg; 203bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly break; 204bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly 205bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly default: 206f254f8ef6a06ae1dba7c3b275a61a6d54c34accdivan.penkov@gmail.com fprintf(stderr, "Invalid option '%c'\n", ch); 207bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly Usage(argc, argv); 208f254f8ef6a06ae1dba7c3b275a61a6d54c34accdivan.penkov@gmail.com exit(1); 209bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly break; 210bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly } 211bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly } 212bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly 213bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly if ((argc - optind) != 2) { 214bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly fprintf(stderr, "%s: Missing symbols file and/or upload-URL\n", argv[0]); 215bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly Usage(argc, argv); 216bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly exit(1); 217bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly } 218bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly 219bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly options->symbolsPath = argv[optind]; 220bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly options->uploadURLStr = argv[optind + 1]; 221bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly} 222bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly 223bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly//============================================================================= 224f254f8ef6a06ae1dba7c3b275a61a6d54c34accdivan.penkov@gmail.comint main(int argc, const char* argv[]) { 225bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly Options options; 226bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly SetupOptions(argc, argv, &options); 227bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly Start(&options); 228bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly return options.success ? 0 : 1; 229bcd46f007919b5063164c8c5c6c2bd4dfb62681eluly} 230