Code example

In the introduction to this chapter, we mentioned a requirement: from within a GUI frontend, to display the content of a system-generated PDF document. Lets do this here.

To do so, we would require a PDF reader application; we can assume we have one. Indeed, on many Linux distributions, the evince application is a good PDF reader application, usually preinstalled (true on Ubuntu and Fedora, among others).

Well, here, we shall not bother with a GUI frontend application, we shall use plain old C to write a CLI app that, given a PDF document pathname, executes the evince PDF reader application. What PDF document do we display? Ah, that's a surprise! (take a look):

For readability, only the relevant parts of the code are displayed as follows; to view and run it, the entire source code is available here:
https://github.com/PacktPublishing/Hands-on-System-Programming-with-Linux.
const char *pdf_reader_app="/usr/bin/evince";
static int exec_pdf_reader_app(char *pdfdoc)
{
char * const pdf_argv[] = {"evince", pdfdoc, 0};

if (execv(pdf_reader_app, pdf_argv) < 0) {
WARN("execv failed");
return -1;
}
return 0; /* never reached */
}

We invoke the preceding function from main() as follows:

   if (exec_pdf_reader_app(argv[1]) < 0)
FATAL("exec pdf function failed ");

We build it, then perform a sample run:

$ ./pdfrdr_exec
Usage: ./pdfrdr_exec {pathname_of_doc.pdf}
$ ./pdfrdr_exec The_C_Programming_Language_K&R_2ed.pdf 2>/dev/null
$

Here is a screenshot of the action!

What if we are running Linux on the console only (no GUI)? Then, of course, the preceding app will not work (and evince is unlikely to even be installed). Here is an example of this case:

$ ./pdfrdr_exec ~/Seawolf_MinDev_User_Guide.pdf 
!WARNING! pdfrdr_exec.c:exec_pdf_reader_app:33: execv failed
perror says: No such file or directory
FATAL:pdfrdr_exec.c:main:48: exec pdf function failed
perror says: No such file or directory
$

In this case, why not try modifying the above app to use a CLI PDF toolset instead; one such toolset is from the Poppler project (see the following note). Within it, one of the interesting utilities it provides is pdftohtml. Why not use it to generate HTML from a PDF document? We leave it as an exercise for the reader (see the Questions section on the GitHub repository).

These useful PDF utilities are provided by an open source project called Poppler. You can easily install these PDF utilities, on an Ubuntu box: sudo apt install poppler-utils

We can quite easily trace what happens in the pdfrdr_exec program; here, we use the ltrace(1) to see the library calls issued:

$ ltrace ./pdfrdr_exec The_C_Programming_Language_K&R_2ed.pdf 
execv("/usr/bin/evince", 0x7ffcd861fc00 <no return ...>
--- Called exec() ---
g_static_resource_init(0x5575a5aff400, 0x7ffc5970f888, 0x7ffc5970f8a0, 32) = 0
ev_get_locale_dir(2, 0x7ffc5970f888, 0x7ffc5970f8a0, 32) = 0x7fe1ad083ab9
[...]

The key call: the execv of course is seen; interestingly, ltrace then helpfully tells us that there's no return ... from it. We then see the library APIs of the evince software itself.

What if we use strace(1) to see the system calls issued?

$ strace ./pdfrdr_exec The_C_Programming_Language_K&R_2ed.pdf 
execve("./pdfrdr_exec", ["./pdfrdr_exec", "The_C_Programming_Language_K&R_2"...], 0x7fff7f7720f8 /* 56 vars */) = 0
brk(NULL) = 0x16c0000
access("/etc/ld.so.preload", R_OK) = 0
openat(AT_FDCWD, "/etc/ld.so.preload", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=0, ...}) = 0
[...]

Yes, the very first one is the execve(2), proving that the execv(3) library API invokes the execve(2) system call. The rest of the output, of course, is the system calls issued by the evince process as it executes.

 

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.117.217.186