1 /*
2  * Read /proc/self/cmdline and /proc/self/exe such that it can be tested
3  * whether Valgrind intercepts the system calls that access these pseudo-files
4  * properly on Linux and whether Valgrind does not modify the behavior of
5  * accessing these files on other operating systems.
6  */
7 
8 #define _ATFILE_SOURCE
9 
10 #include <ctype.h>
11 #include <errno.h>
12 #include <fcntl.h>
13 #include <stdio.h>
14 #include <sys/types.h>
15 #include <sys/stat.h>
16 #include <string.h>
17 #include <unistd.h>
18 #include "../../config.h"
19 
test_cmdline(const char * const cwd,const char * const label,const char * const path)20 static void test_cmdline(const char* const cwd, const char* const label,
21                          const char* const path)
22 {
23   int fd, n;
24   char ch;
25 
26   fprintf(stderr, "%s:\n", label);
27   fd = open(path, 0);
28   if (fd >= 0)
29   {
30     while ((n = read(fd, &ch, 1)) > 0)
31     {
32       if (ch == '\\')
33         fprintf(stderr, "\\\\");
34       else if (ch == 0)
35         fprintf(stderr, "\\0");
36       else if (isprint((unsigned)ch))
37         fprintf(stderr, "%c", ch);
38       else
39         fprintf(stderr, "\\0%o", ch);
40     }
41     fprintf(stderr, "\n");
42     close(fd);
43   }
44   else
45     perror("open()");
46 }
47 
test_readlink(const char * const cwd,const char * const label,const char * const path)48 static void test_readlink(const char* const cwd, const char* const label,
49                           const char* const path)
50 {
51   char buf[512];
52   const char* p;
53   int n;
54 
55   if ((n = readlink(path, buf, sizeof(buf) - 1)) >= 0)
56   {
57     buf[n] = 0;
58     p = buf;
59     if (strncmp(buf, cwd, strlen(cwd)) == 0)
60       p += strlen(cwd);
61     fprintf(stderr, "Result of readlink(\"%s\"): %s\n", label, p);
62   }
63   else
64     perror("readlink");
65 }
66 
test_readlinkat(const char * const cwd,const char * const label,const char * const path)67 static void test_readlinkat(const char* const cwd, const char* const label,
68                             const char* const path)
69 {
70 #if HAVE_READLINKAT
71   char buf[512];
72   const char* p;
73   int n;
74 
75   if ((n = readlinkat(AT_FDCWD, path, buf, sizeof(buf) - 1)) >= 0)
76   {
77     buf[n] = 0;
78     p = buf;
79     if (strncmp(buf, cwd, strlen(cwd)) == 0)
80       p += strlen(cwd);
81     fprintf(stderr, "Result of readlinkat(\"%s\"): %s\n", label, p);
82   }
83   else
84     perror("readlinkat");
85 #else
86   errno = ENOSYS;
87   perror("readlinkat");
88 #endif
89 }
90 
main(int argc,char ** argv)91 int main(int argc, char** argv)
92 {
93   char cwd[512];
94   char path[512];
95 
96   cwd[0] = 0;
97   if (! getcwd(cwd, sizeof(cwd)))
98     perror("getcwd");
99   strcat(cwd, "/");
100 
101   snprintf(path, sizeof(path), "/proc/%ld/cmdline", (long) getpid());
102 
103   test_cmdline(cwd, "/proc/self/cmdline", "/proc/self/cmdline");
104   test_cmdline(cwd, "/proc/<pid>/cmdline", path);
105 
106   snprintf(path, sizeof(path), "/proc/%ld/exe", (long) getpid());
107 
108   test_readlink(cwd, "/proc/self/exe", "/proc/self/exe");
109   test_readlink(cwd, "/proc/<pid>/exe", path);
110 
111   test_readlinkat(cwd, "/proc/self/exe", "/proc/self/exe");
112   test_readlinkat(cwd, "/proc/<pid>/exe", path);
113 
114   return 0;
115 }
116