1/* Copyright (C) 2021 Free Software Foundation, Inc. 2 Contributed by Oracle. 3 4 This file is part of GNU Binutils. 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 3, or (at your option) 9 any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program; if not, write to the Free Software 18 Foundation, 51 Franklin Street - Fifth Floor, Boston, 19 MA 02110-1301, USA. */ 20 21#include "config.h" 22#include <stdlib.h> 23#include <strings.h> 24#include <sys/param.h> 25#include <sys/stat.h> 26#include <unistd.h> 27 28#include "Application.h" 29#include "Settings.h" 30#include "i18n.h" 31#include "util.h" 32 33Application::ProgressFunc Application::progress_func = NULL; 34Application *theApplication; 35 36Application::Application (int argc, char *argv[], char *fdhome) 37{ 38 theApplication = this; 39 cur_dir = NULL; 40 prog_version = dbe_strdup (VERSION); 41 set_name (strchr (argv[0], '/') ? argv[0] : NULL); 42 whoami = get_basename (get_name ()); 43 44 // set up a queue for comments 45 commentq = new Emsgqueue (NTXT ("app_commentq")); 46 47 // Locate where the binaries are installed 48 set_run_dir (fdhome); 49 50 // Initialize I18N 51 init_locale (run_dir); 52 53 // Initialize licensing data 54 lic_found = 0; 55 lic_err = NULL; 56 57 // Initialize worker threads 58 number_of_worker_threads = 1; 59#if DEBUG 60 char *use_worker_threads = getenv (NTXT ("SP_USE_WORKER_THREADS")); 61 if ((NULL != use_worker_threads) && (0 == strcasecmp (use_worker_threads, NTXT ("no")))) 62 { 63 number_of_worker_threads = 0; 64 } 65#endif /* DEBUG */ 66 settings = new Settings (this); 67} 68 69Application::~Application () 70{ 71 delete commentq; 72 delete settings; 73 free (prog_version); 74 free (cur_dir); 75 free (prog_name); 76 free (run_dir); 77} 78 79// Set the name of the application (for messages) 80void 81Application::set_name (const char *_name) 82{ 83 prog_name = get_realpath (_name); 84} 85 86char * 87Application::get_realpath (const char *_name) 88{ 89 if (_name == NULL) 90 _name = "/proc/self/exe"; 91 char *exe_name = realpath (_name, NULL); 92 if (exe_name) 93 return exe_name; 94 if (strchr (_name, '/') == NULL) 95 { 96 char *path = getenv ("PATH"); 97 if (path) 98 for (char *s = path;; s++) 99 if (*s == ':' || *s == 0) 100 { 101 if (path != s) 102 { 103 char *nm = dbe_sprintf (NTXT ("%.*s/%s"), (int) (path - s - 1), path, _name); 104 exe_name = realpath (nm, NULL); 105 free (nm); 106 if (exe_name) 107 return exe_name; 108 } 109 if (*s == 0) 110 break; 111 path = s + 1; 112 } 113 } 114 return strdup (_name); 115} 116 117// Set the directory where all binaries are found 118void 119Application::set_run_dir (char *fdhome) 120{ 121 run_dir_with_spaces = NULL; 122 if (fdhome) 123 { 124 char *path = dbe_sprintf ("%s/bin", fdhome); 125 struct stat sbuf; 126 if (stat (path, &sbuf) != -1) 127 run_dir = path; 128 else 129 { 130 free (path); 131 run_dir = dbe_strdup (fdhome); 132 } 133 } 134 else 135 { 136 run_dir = realpath (prog_name, NULL); 137 if (run_dir == NULL) 138 { 139 fprintf (stderr, // I18N won't work here -- not catopen yet. 140 GTXT ("Can't find location of %s\n"), prog_name); 141 run_dir = dbe_strdup (get_cur_dir ()); 142 } 143 else 144 { 145 char *d = strrchr (run_dir, '/'); 146 if (d) 147 *d = 0; 148 // Check if the installation path contains spaces 149 if (strchr (run_dir, ' ') != NULL) 150 { 151 // Create a symbolic link without spaces 152 const char *dir = NTXT ("/tmp/.gprofngLinks"); 153 char *symbolic_link = dbe_create_symlink_to_path (run_dir, dir); 154 if (NULL != symbolic_link) 155 { 156 // Save old path to avoid memory leak 157 run_dir_with_spaces = run_dir; 158 // Use the path through symbolic link 159 run_dir = symbolic_link; 160 } 161 } 162 } 163 } 164} 165 166char * 167Application::get_cur_dir () 168{ 169 if (cur_dir == NULL) 170 { 171 char cwd[MAXPATHLEN]; 172 if (getcwd (cwd, sizeof (cwd)) == NULL) 173 { 174 perror (prog_name); 175 exit (1); 176 } 177 cur_dir = dbe_strdup (canonical_path (cwd)); 178 } 179 return cur_dir; 180} 181 182/** 183 * Get number of worker threads 184 * This is used to decide if it is ok to use worker threads for stat() 185 * and other actions that can hang for a long time 186 * @return number_of_worker_threads 187 */ 188int 189Application::get_number_of_worker_threads () 190{ 191 return number_of_worker_threads; 192} 193 194int 195Application::check_args (int argc, char *argv[]) 196{ 197 int opt; 198 // Parsing the command line 199 opterr = 0; 200 while ((opt = getopt (argc, argv, "V")) != EOF) 201 switch (opt) 202 { 203 case 'V': 204// Ruud 205 Application::print_version_info (); 206/* 207 printf (NTXT ("GNU %s version %s\n"), get_basename (prog_name), VERSION); 208*/ 209 exit (0); 210 default: 211 usage (); 212 } 213 return optind; 214} 215 216Emsg * 217Application::fetch_comments () 218{ 219 if (commentq == NULL) 220 return NULL; 221 return commentq->fetch (); 222} 223 224void 225Application::queue_comment (Emsg *m) 226{ 227 commentq->append (m); 228} 229 230void 231Application::delete_comments () 232{ 233 if (commentq != NULL) 234 { 235 delete commentq; 236 commentq = new Emsgqueue (NTXT ("app_commentq")); 237 } 238} 239 240int 241Application::set_progress (int percentage, const char *proc_str) 242{ 243 if (progress_func != NULL) 244 return progress_func (percentage, proc_str); 245 return 0; 246} 247 248// Ruud 249void 250Application::print_version_info () 251{ 252 printf ( GTXT ( 253 "GNU %s binutils version %s\n" 254 "Copyright (C) 2021 Free Software Foundation, Inc.\n" 255 "License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>.\n" 256 "This is free software: you are free to change and redistribute it.\n" 257 "There is NO WARRANTY, to the extent permitted by law.\n"), 258 get_basename (prog_name), VERSION); 259} 260