]> sourceware.org Git - systemtap.git/blame - csclient.cxx
Update nfsderrno.stp to work with Linux 6.10
[systemtap.git] / csclient.cxx
CommitLineData
2dce8c42
DB
1/*
2 Compile server client functions
73fcca6f 3 Copyright (C) 2010-2018 Red Hat Inc.
2dce8c42
DB
4
5 This file is part of systemtap, and is free software. You can
6 redistribute it and/or modify it under the terms of the GNU General
7 Public License (GPL); either version 2, or (at your option) any
8 later version.
9*/
c4fd15b4
DB
10
11// Completely disable the client if NSS is not available.
2dce8c42
DB
12#include "config.h"
13#include "session.h"
005df4e5 14#include "cscommon.h"
aa4d21c0 15#include "csclient.h"
01fb72a0 16#include "client-nss.h"
eb3896ef 17#ifdef HAVE_HTTP_SUPPORT
01fb72a0 18#include "client-http.h"
eb3896ef 19#endif
2fad97fd 20#include "util.h"
0f5d597d 21#include "stap-probe.h"
2dce8c42 22
6b314d31 23#include <unistd.h>
01fb72a0 24#include <iostream>
79efe7f8
FCE
25
26extern "C" {
01fb72a0 27#include <sys/times.h>
3eee0879 28#include <sys/time.h>
586c8666 29#include <glob.h>
aeb9cc10 30}
2fad97fd 31
aeb9cc10
DB
32using namespace std;
33
eb3896ef
DS
34client_backend *
35nss_get_client_backend (systemtap_session &s)
840e5073 36{
01fb72a0
DS
37 // Use the correct backend.
38#ifdef HAVE_HTTP_SUPPORT
39 if (! s.http_servers.empty())
eb3896ef 40 return new http_client_backend (s);
840e5073 41#endif
01fb72a0 42#if HAVE_NSS
eb3896ef 43 return new nss_client_backend (s);
840e5073 44#endif
eb3896ef
DS
45 return NULL;
46}
47
48int
49compile_server_client::passes_0_4 ()
50{
51 // Use the correct backend.
52 backend = nss_get_client_backend (s);
01fb72a0 53 if (backend == NULL)
840e5073 54 {
01fb72a0
DS
55 clog << _("Using a compile server backend failed.") << endl;
56 return 1;
840e5073
DB
57 }
58
0f5d597d 59 PROBE1(stap, client__start, &s);
2fad97fd 60
aa4d21c0 61 // arguments parsed; get down to business
4e78c716 62 if (s.verbose || ! s.auto_server_msgs.empty ())
a46f9abe 63 clog << _("Using a compile server.") << endl;
aa4d21c0 64
aa4d21c0
DB
65 struct tms tms_before;
66 times (& tms_before);
67 struct timeval tv_before;
68 gettimeofday (&tv_before, NULL);
69
2fad97fd
DB
70 // Create the request package.
71 int rc = initialize ();
e19ebcf7 72 assert_no_interrupts();
985892de 73 if (rc != 0) goto done;
2fad97fd 74 rc = create_request ();
e19ebcf7 75 assert_no_interrupts();
985892de 76 if (rc != 0) goto done;
01fb72a0 77 rc = backend->package_request ();
e19ebcf7 78 assert_no_interrupts();
985892de 79 if (rc != 0) goto done;
2fad97fd
DB
80
81 // Submit it to the server.
01fb72a0 82 rc = backend->find_and_connect_to_server ();
e19ebcf7 83 assert_no_interrupts();
985892de 84 if (rc != 0) goto done;
2fad97fd
DB
85
86 // Unpack and process the response.
01fb72a0 87 rc = backend->unpack_response ();
e19ebcf7 88 assert_no_interrupts();
985892de 89 if (rc != 0) goto done;
586c8666 90 rc = process_response ();
2fad97fd
DB
91
92 done:
aa4d21c0
DB
93 struct tms tms_after;
94 times (& tms_after);
95 unsigned _sc_clk_tck = sysconf (_SC_CLK_TCK);
96 struct timeval tv_after;
97 gettimeofday (&tv_after, NULL);
98
99#define TIMESPRINT "in " << \
100 (tms_after.tms_cutime + tms_after.tms_utime \
101 - tms_before.tms_cutime - tms_before.tms_utime) * 1000 / (_sc_clk_tck) << "usr/" \
102 << (tms_after.tms_cstime + tms_after.tms_stime \
103 - tms_before.tms_cstime - tms_before.tms_stime) * 1000 / (_sc_clk_tck) << "sys/" \
104 << ((tv_after.tv_sec - tv_before.tv_sec) * 1000 + \
105 ((long)tv_after.tv_usec - (long)tv_before.tv_usec) / 1000) << "real ms."
106
da21dc88
DB
107 if (rc == 0)
108 {
109 // Save the module, if necessary.
110 if (s.last_pass == 4)
111 s.save_module = true;
112
113 // Copy module to the current directory.
114 if (! pending_interrupts)
115 {
116 if (s.save_module)
117 {
118 string module_src_path = s.tmpdir + "/" + s.module_filename();
119 string module_dest_path = s.module_filename();
120 copy_file (module_src_path, module_dest_path, s.verbose >= 3);
121 // Also copy the module signature, it it exists.
122 module_src_path += ".sgn";
123 if (file_exists (module_src_path))
124 {
125 module_dest_path += ".sgn";
126 copy_file(module_src_path, module_dest_path, s.verbose >= 3);
127 }
128 }
129 // Print the name of the module
130 if (s.last_pass == 4)
131 {
132 cout << s.module_filename() << endl;
133 }
134 }
135 }
136
aa4d21c0
DB
137 // syntax errors, if any, are already printed
138 if (s.verbose)
139 {
a46f9abe
FCE
140 string ws = s.winning_server;
141 if (ws == "") ws = "?";
142 clog << _("Passes: via server ") << ws << " "
85007c04 143 << getmemusage()
aa4d21c0
DB
144 << TIMESPRINT
145 << endl;
146 }
bba368c5 147 if (rc && !s.dump_mode)
a46f9abe
FCE
148 {
149 clog << _("Passes: via server failed. Try again with another '-v' option.") << endl;
150 }
aa4d21c0 151
0f5d597d 152 PROBE1(stap, client__end, &s);
aa4d21c0
DB
153
154 return rc;
155}
156
2fad97fd
DB
157// Initialize a client/server session.
158int
159compile_server_client::initialize ()
160{
161 int rc = 0;
162
2fad97fd
DB
163 // Create a temporary directory to package things in.
164 client_tmpdir = s.tmpdir + "/client";
165 rc = create_dir (client_tmpdir.c_str ());
166 if (rc != 0)
167 {
168 const char* e = strerror (errno);
aeb9cc10 169 clog << _("ERROR: cannot create temporary directory (\"")
2fad97fd
DB
170 << client_tmpdir << "\"): " << e
171 << endl;
01fb72a0 172 return rc;
2fad97fd 173 }
01fb72a0 174 backend->set_tmpdir(client_tmpdir);
2fad97fd 175
01fb72a0 176 return backend->initialize();
2fad97fd
DB
177}
178
179// Create the request package.
180int
181compile_server_client::create_request ()
182{
cc7c72cd 183 // Add the current protocol version.
01fb72a0 184 int rc = backend->add_protocol_version (CURRENT_CS_PROTOCOL_VERSION);
cc7c72cd
DB
185 if (rc != 0)
186 return rc;
2fad97fd
DB
187
188 // Add the script file or script option
189 if (s.script_file != "")
190 {
191 if (s.script_file == "-")
192 {
193 // Copy the script from stdin
194 string packaged_script_dir = client_tmpdir + "/script";
195 rc = create_dir (packaged_script_dir.c_str ());
196 if (rc != 0)
197 {
198 const char* e = strerror (errno);
aeb9cc10 199 clog << _("ERROR: cannot create temporary directory ")
2fad97fd
DB
200 << packaged_script_dir << ": " << e
201 << endl;
202 return rc;
203 }
896c1b4d
DS
204
205 if (s.stdin_script.str().empty())
206 s.stdin_script << cin.rdbuf();
207 rc = write_to_file(packaged_script_dir + "/-", s.stdin_script.str());
f3fbabf2
DB
208 if (rc != 0)
209 return rc;
2fad97fd 210
01fb72a0
DS
211 // Let the backend know the file is there.
212 rc = backend->add_tmpdir_file ("script/-");
213 if (rc != 0)
214 return rc;
215
216 // Name the script in the stap cmd arguments.
217 rc = backend->add_cmd_arg ("script/-");
f3fbabf2
DB
218 if (rc != 0)
219 return rc;
2fad97fd
DB
220 }
221 else
01fb72a0
DS
222 {
223 // Add the script.
224 rc = backend->include_file_or_directory ("script", s.script_file);
f3fbabf2
DB
225 if (rc != 0)
226 return rc;
2fad97fd
DB
227 }
228 }
229
230 // Add -I paths. Skip the default directory.
231 if (s.include_arg_start != -1)
232 {
233 unsigned limit = s.include_path.size ();
234 for (unsigned i = s.include_arg_start; i < limit; ++i)
235 {
01fb72a0 236 rc = backend->add_cmd_arg ("-I");
f3fbabf2
DB
237 if (rc != 0)
238 return rc;
50436433
DS
239 rc = backend->include_file_or_directory ("tapset",
240 s.include_path[i]);
f3fbabf2
DB
241 if (rc != 0)
242 return rc;
2fad97fd
DB
243 }
244 }
245
246 // Add other options.
01fb72a0 247 rc = add_cmd_args ();
f3fbabf2
DB
248 if (rc != 0)
249 return rc;
2fad97fd 250
01fb72a0
DS
251 // Add the sysinfo.
252 rc = backend->add_sysinfo ();
e4e3d6b7
CM
253 if (rc != 0)
254 return rc;
255
256 // Add localization data
257 rc = add_localization_variables();
2fad97fd 258
01fb72a0 259 // Add the machine owner key (MOK) fingerprints, if needed.
cd1418c7 260 if (! s.mok_fingerprints.empty())
b3367f63
DS
261 {
262 ostringstream fingerprints;
263 vector<string>::const_iterator it;
cd1418c7 264 for (it = s.mok_fingerprints.begin(); it != s.mok_fingerprints.end();
b3367f63 265 it++)
01fb72a0
DS
266 backend->add_mok_fingerprint(*it);
267 rc = backend->finalize_mok_fingerprints();
b3367f63 268 if (rc != 0)
01fb72a0 269 return rc;
b3367f63
DS
270 }
271
2fad97fd
DB
272 return rc;
273}
274
586c8666
DS
275int
276compile_server_client::process_response ()
277{
278 // Pick up the results of running stap on the server.
279 string filename = backend->server_tmpdir + "/rc";
280 int stap_rc;
281 int rc = read_from_file (filename, stap_rc);
282 if (rc != 0)
283 return rc;
284 rc = stap_rc;
285
286 if (s.last_pass >= 4)
287 {
288 // The server should have returned a module.
289 string filespec = s.tmpdir + "/*.ko";
290 if (s.verbose >= 3)
291 clog << _F("Searching \"%s\"\n", filespec.c_str());
292
293 glob_t globbuf;
294 int r = glob(filespec.c_str (), 0, NULL, & globbuf);
295 if (r != GLOB_NOSPACE && r != GLOB_ABORTED && r != GLOB_NOMATCH)
296 {
297 if (globbuf.gl_pathc > 1)
298 clog << _("Incorrect number of modules in server response") << endl;
299 else
300 {
301 assert (globbuf.gl_pathc == 1);
302 string modname = globbuf.gl_pathv[0];
303 if (s.verbose >= 3)
304 clog << _(" found ") << modname << endl;
305
306 // If a module name was not specified by the user, then set it to
307 // be the one generated by the server.
308 if (! s.save_module)
309 {
310 vector<string> components;
311 tokenize (modname, components, "/");
312 s.module_name = components.back ();
313 s.module_name.erase(s.module_name.size() - 3);
314 }
315
316 // If a uprobes.ko module was returned, then make note of it.
317 string uprobes_ko;
318 if (backend->server_version < "1.6")
319 uprobes_ko = s.tmpdir + "/server/uprobes.ko";
320 else
321 uprobes_ko = s.tmpdir + "/uprobes/uprobes.ko";
322
323 if (file_exists (uprobes_ko))
324 {
325 s.need_uprobes = true;
326 s.uprobes_path = uprobes_ko;
327 }
328 }
329 }
330 else if (s.have_script)
331 {
332 if (rc == 0)
333 {
334 clog << _("No module was returned by the server.") << endl;
335 rc = 1;
336 }
337 }
338 globfree (& globbuf);
339 }
340
341 // If the server returned a MOK certificate, copy it to the user's
342 // current directory.
343 string server_MOK_public_cert = backend->server_tmpdir + "/" MOK_PUBLIC_CERT_NAME;
344 if (file_exists (server_MOK_public_cert))
345 {
346 string dst = MOK_PUBLIC_CERT_NAME;
347 copy_file (server_MOK_public_cert, dst, (s.verbose >= 3));
348 }
349
350 // Output stdout and stderr.
586c8666
DS
351 filename = backend->server_tmpdir + "/stdout";
352 flush_to_stream (filename, cout);
353
3b02cd57
FCE
354 filename = backend->server_tmpdir + "/stderr";
355 flush_to_stream (filename, clog);
356
586c8666
DS
357 return rc;
358}
359
2fad97fd
DB
360// Add the arguments specified on the command line to the server request
361// package, as appropriate.
f3fbabf2 362int
01fb72a0 363compile_server_client::add_cmd_args ()
2fad97fd 364{
fd20a70c 365 // stap arguments to be passed to the server.
f3fbabf2 366 int rc = 0;
2fad97fd
DB
367 unsigned limit = s.server_args.size();
368 for (unsigned i = 0; i < limit; ++i)
f3fbabf2 369 {
01fb72a0 370 rc = backend->add_cmd_arg (s.server_args[i]);
f3fbabf2
DB
371 if (rc != 0)
372 return rc;
373 }
fd20a70c
DB
374
375 // Script arguments.
376 limit = s.args.size();
377 if (limit > 0) {
01fb72a0 378 rc = backend->add_cmd_arg ("--");
fd20a70c
DB
379 if (rc != 0)
380 return rc;
381 for (unsigned i = 0; i < limit; ++i)
382 {
01fb72a0 383 rc = backend->add_cmd_arg (s.args[i]);
fd20a70c
DB
384 if (rc != 0)
385 return rc;
386 }
387 }
f3fbabf2 388 return rc;
2fad97fd
DB
389}
390
e4e3d6b7
CM
391// Add the localization variables to the server request
392// package.
393int
394compile_server_client::add_localization_variables()
395{
e4e3d6b7 396 const set<string> &locVars = localization_variables();
e4e3d6b7
CM
397
398 /* Note: We don't have to check for the contents of the environment
399 * variables here, since they will be checked extensively on the
400 * server.
401 */
01fb72a0 402 for (auto it = locVars.begin(); it != locVars.end(); it++)
e4e3d6b7
CM
403 {
404 char* var = getenv((*it).c_str());
405 if (var)
01fb72a0 406 backend->add_localization_variable(*it, var);
e4e3d6b7 407 }
01fb72a0 408 return backend->finalize_localization_variables();
e4e3d6b7
CM
409}
410
2e46c01a 411/* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */
This page took 0.220486 seconds and 5 git commands to generate.