xref: /netbsd-src/external/gpl3/binutils/dist/gprofng/src/Application.cc (revision cb63e24e8d6aae7ddac1859a9015f48b1d8bd90e)
1 /* Copyright (C) 2021-2024 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 
33 Application::ProgressFunc Application::progress_func = NULL;
34 Application *theApplication;
35 
Application(int argc,char * argv[],char * fdhome)36 Application::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 
~Application()69 Application::~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)
80 void
set_name(const char * _name)81 Application::set_name (const char *_name)
82 {
83   prog_name = get_realpath (_name);
84 }
85 
86 char *
get_realpath(const char * _name)87 Application::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) (s - path),
104 				   path, _name);
105 		  exe_name = realpath (nm, NULL);
106 		  free (nm);
107 		  if (exe_name)
108 		    return exe_name;
109 		}
110 	      if (*s == 0)
111 		break;
112 	      path = s + 1;
113 	    }
114     }
115   return strdup (_name);
116 }
117 
118 // Set the directory where all binaries are found
119 void
set_run_dir(char * fdhome)120 Application::set_run_dir (char *fdhome)
121 {
122   run_dir_with_spaces = NULL;
123   if (fdhome)
124     {
125       char *path = dbe_sprintf ("%s/bin", fdhome);
126       struct stat sbuf;
127       if (stat (path, &sbuf) != -1)
128 	run_dir = path;
129       else
130 	{
131 	  free (path);
132 	  run_dir = dbe_strdup (fdhome);
133 	}
134     }
135   else
136     {
137       run_dir = realpath (prog_name, NULL);
138       if (run_dir == NULL)
139 	{
140 	  fprintf (stderr, // I18N won't work here -- not catopen yet.
141 		   GTXT ("Can't find location of %s\n"), prog_name);
142 	  run_dir = dbe_strdup (get_cur_dir ());
143 	}
144       else
145 	{
146 	  char *d = strrchr (run_dir, '/');
147 	  if (d)
148 	    *d = 0;
149 	  // Check if the installation path contains spaces
150 	  if (strchr (run_dir, ' ') != NULL)
151 	    {
152 	      // Create a symbolic link without spaces
153 	      const char *dir = NTXT ("/tmp/.gprofngLinks");
154 	      char *symbolic_link = dbe_create_symlink_to_path (run_dir, dir);
155 	      if (NULL != symbolic_link)
156 		{
157 		  // Save old path to avoid memory leak
158 		  run_dir_with_spaces = run_dir;
159 		  // Use the path through symbolic link
160 		  run_dir = symbolic_link;
161 		}
162 	    }
163 	}
164     }
165 }
166 
167 char *
get_cur_dir()168 Application::get_cur_dir ()
169 {
170   if (cur_dir == NULL)
171     {
172       char cwd[MAXPATHLEN];
173       if (getcwd (cwd, sizeof (cwd)) == NULL)
174 	{
175 	  perror (prog_name);
176 	  exit (1);
177 	}
178       cur_dir = dbe_strdup (canonical_path (cwd));
179     }
180   return cur_dir;
181 }
182 
183 /**
184  * Get number of worker threads
185  * This is used to decide if it is ok to use worker threads for stat()
186  * and other actions that can hang for a long time
187  * @return number_of_worker_threads
188  */
189 int
get_number_of_worker_threads()190 Application::get_number_of_worker_threads ()
191 {
192   return number_of_worker_threads;
193 }
194 
195 int
check_args(int argc,char * argv[])196 Application::check_args (int argc, char *argv[])
197 {
198   int opt;
199   // Parsing the command line
200   opterr = 0;
201   while ((opt = getopt (argc, argv, "V")) != EOF)
202     switch (opt)
203       {
204       case 'V':
205 // Ruud
206 	Application::print_version_info ();
207 /*
208 	printf (NTXT ("GNU %s version %s\n"), get_basename (prog_name), VERSION);
209 */
210 	exit (0);
211       default:
212 	usage ();
213       }
214   return optind;
215 }
216 
217 Emsg *
fetch_comments()218 Application::fetch_comments ()
219 {
220   if (commentq == NULL)
221     return NULL;
222   return commentq->fetch ();
223 }
224 
225 void
queue_comment(Emsg * m)226 Application::queue_comment (Emsg *m)
227 {
228   commentq->append (m);
229 }
230 
231 void
delete_comments()232 Application::delete_comments ()
233 {
234   if (commentq != NULL)
235     {
236       delete commentq;
237       commentq = new Emsgqueue (NTXT ("app_commentq"));
238     }
239 }
240 
241 int
set_progress(int percentage,const char * proc_str)242 Application::set_progress (int percentage, const char *proc_str)
243 {
244   if (progress_func != NULL)
245     return progress_func (percentage, proc_str);
246   return 0;
247 }
248 
249 // Ruud
250 void
print_version_info()251 Application::print_version_info ()
252 {
253   printf ( GTXT (
254     "GNU %s binutils version %s\n"
255     "Copyright (C) 2024 Free Software Foundation, Inc.\n"
256     "License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>.\n"
257     "This is free software: you are free to change and redistribute it.\n"
258     "There is NO WARRANTY, to the extent permitted by law.\n"),
259     get_basename (prog_name), VERSION);
260 }
261