nixpkgs mirror (for testing)
github.com/NixOS/nixpkgs
nix
1/* Brgen4 search for configuration under `/etc/opt/brother/scanner/brscan4`. This
2 LD_PRELOAD library intercepts execvp(), open and open64 calls to redirect them to
3 the corresponding location in $out. Also support specifying an alternate
4 file name for `brsanenetdevice4.cfg` which otherwise is invariable
5 created at `/etc/opt/brother/scanner/brscan4`*/
6
7#define _GNU_SOURCE
8#include <stdio.h>
9#include <stdarg.h>
10#include <stdlib.h>
11#include <dlfcn.h>
12#include <sys/types.h>
13#include <sys/stat.h>
14#include <fcntl.h>
15#include <limits.h>
16#include <string.h>
17#include <dirent.h>
18
19char origDir [] = "/etc/opt/brother/scanner/brscan4";
20char realDir [] = OUT "/opt/brother/scanner/brscan4";
21
22char devCfgFileNameEnvVar [] = "BRSANENETDEVICE4_CFG_FILENAME";
23char devCfgFileName [] = "/etc/opt/brother/scanner/brscan4//brsanenetdevice4.cfg";
24
25const char * rewrite(const char * path, char * buf)
26{
27 if (strncmp(path, devCfgFileName, sizeof(devCfgFileName)) == 0) {
28
29 const char* newCfgFileName = getenv(devCfgFileNameEnvVar);
30 if (!newCfgFileName) return path;
31
32 if (snprintf(buf, PATH_MAX, "%s", newCfgFileName) >= PATH_MAX)
33 abort();
34 return buf;
35 }
36
37 if (strncmp(path, origDir, sizeof(origDir) - 1) != 0) return path;
38 if (snprintf(buf, PATH_MAX, "%s%s", realDir, path + sizeof(origDir) - 1) >= PATH_MAX)
39 abort();
40 return buf;
41}
42
43const char* findAndReplaceFirstOccurence(const char* inStr, const char* subStr,
44 const char* replaceStr,
45 char* buf, unsigned maxBuf)
46{
47 const char* foundStr = strstr(inStr, subStr);
48 if (!foundStr)
49 return inStr;
50
51 const unsigned inStrLen = strlen(inStr);
52 const unsigned subStrLen = strlen(subStr);
53 const unsigned replaceStrLen = strlen(replaceStr);
54
55 const unsigned precedingStrLen = foundStr - inStr;
56 if (precedingStrLen + 1 > maxBuf)
57 return NULL;
58
59 const unsigned followingStrPos = precedingStrLen + subStrLen;
60 const unsigned followingStrLen = inStrLen - followingStrPos;
61
62 strncpy(buf, inStr, precedingStrLen);
63 unsigned outLength = precedingStrLen;
64
65 if (outLength + replaceStrLen + 1 > maxBuf)
66 return NULL;
67
68 strncpy(buf + outLength, replaceStr, replaceStrLen);
69 outLength += replaceStrLen;
70
71 if (outLength + followingStrLen + 1 > maxBuf)
72 return NULL;
73
74 strncpy(buf + outLength, inStr + followingStrPos, followingStrLen);
75 outLength += followingStrLen;
76
77 buf[outLength] = '\0';
78
79 return buf;
80}
81
82const char* rewriteSystemCall(const char* command, char* buf, unsigned maxBuf)
83{
84
85 const char* foundStr = strstr(command, devCfgFileName);
86 if (!foundStr)
87 return command;
88
89 const char* replaceStr = getenv(devCfgFileNameEnvVar);
90 if (!replaceStr) return command;
91
92 const char* result =
93 findAndReplaceFirstOccurence(command, devCfgFileName, replaceStr, buf, maxBuf);
94
95 if (!result)
96 abort();
97
98 return result;
99}
100
101int execvp(const char * path, char * const argv[])
102{
103 int (*_execvp) (const char *, char * const argv[]) = dlsym(RTLD_NEXT, "execvp");
104 char buf[PATH_MAX];
105 return _execvp(rewrite(path, buf), argv);
106}
107
108
109int open(const char *path, int flags, ...)
110{
111 char buf[PATH_MAX];
112 int (*_open) (const char *, int, mode_t) = dlsym(RTLD_NEXT, "open");
113 mode_t mode = 0;
114 if (flags & O_CREAT) {
115 va_list ap;
116 va_start(ap, flags);
117 mode = va_arg(ap, mode_t);
118 va_end(ap);
119 }
120 return _open(rewrite(path, buf), flags, mode);
121}
122
123int open64(const char *path, int flags, ...)
124{
125 char buf[PATH_MAX];
126 int (*_open64) (const char *, int, mode_t) = dlsym(RTLD_NEXT, "open64");
127 mode_t mode = 0;
128 if (flags & O_CREAT) {
129 va_list ap;
130 va_start(ap, flags);
131 mode = va_arg(ap, mode_t);
132 va_end(ap);
133 }
134 return _open64(rewrite(path, buf), flags, mode);
135}
136
137FILE* fopen(const char* path, const char* mode)
138{
139 char buf[PATH_MAX];
140 FILE* (*_fopen) (const char*, const char*) = dlsym(RTLD_NEXT, "fopen");
141
142 return _fopen(rewrite(path, buf), mode);
143}
144
145FILE *fopen64(const char *path, const char *mode)
146{
147 char buf[PATH_MAX];
148 FILE* (*_fopen64) (const char*, const char*) = dlsym(RTLD_NEXT, "fopen64");
149
150 return _fopen64(rewrite(path, buf), mode);
151}
152
153DIR* opendir(const char* path)
154{
155 char buf[PATH_MAX];
156 DIR* (*_opendir) (const char*) = dlsym(RTLD_NEXT, "opendir");
157
158 return _opendir(rewrite(path, buf));
159}
160
161#define SYSTEM_CMD_MAX 512
162
163int system(const char *command)
164{
165 char buf[SYSTEM_CMD_MAX];
166 int (*_system) (const char*) = dlsym(RTLD_NEXT, "system");
167
168 const char* newCommand = rewriteSystemCall(command, buf, SYSTEM_CMD_MAX);
169 return _system(newCommand);
170}