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