1 |
|
2 |
#define _GNU_SOURCE |
3 |
#include <stdio.h> |
4 |
#include <stdlib.h> |
5 |
#include <string.h> |
6 |
#include <unistd.h> |
7 |
#include <sys/types.h> |
8 |
#include <sys/wait.h> |
9 |
#include "common.h" |
10 |
|
11 |
char *table_name_to_file(const char *name) { |
12 |
|
13 |
char *share_path = getenv("SHARE_PATH"); |
14 |
char *fname; |
15 |
if (!share_path || !*share_path) share_path = "/usr/share"; |
16 |
|
17 |
asprintf(&fname, "%s/ldetect-lst/%s", share_path, name); |
18 |
|
19 |
return fname; |
20 |
} |
21 |
|
22 |
fh fh_open(const char *name) { |
23 |
fh ret; |
24 |
char *fname = table_name_to_file(name); |
25 |
|
26 |
if (access(fname, R_OK) == 0) { |
27 |
/* prefer gzip type when not compressed, more direct than zlib access */ |
28 |
ret.gztype = GZIP; |
29 |
ret.u.gzip_fh.f = fopen(fname, "r"); |
30 |
ret.u.gzip_fh.pid = 0; |
31 |
} else { |
32 |
char *fname_gz; |
33 |
asprintf(&fname_gz, "%s.gz", fname); |
34 |
if (access(GZIP_BIN, R_OK) == 0) { |
35 |
int fdno[2]; |
36 |
ret.gztype = GZIP; |
37 |
if (access(fname_gz, R_OK) != 0) { |
38 |
fprintf(stderr, "Missing %s (should be %s)\n", name, fname); |
39 |
exit(1); |
40 |
} |
41 |
if (pipe(fdno)) { |
42 |
perror("pciusb"); |
43 |
exit(1); |
44 |
} |
45 |
|
46 |
if ((ret.u.gzip_fh.pid = fork()) != 0) { |
47 |
ret.u.gzip_fh.f = fdopen(fdno[0], "r"); |
48 |
close(fdno[1]); |
49 |
} else { |
50 |
char* cmd[5]; |
51 |
int ip = 0; |
52 |
char *ld_loader = getenv("LD_LOADER"); |
53 |
|
54 |
if (ld_loader && *ld_loader) |
55 |
cmd[ip++] = ld_loader; |
56 |
|
57 |
cmd[ip++] = GZIP_BIN; |
58 |
cmd[ip++] = "-cd"; |
59 |
cmd[ip++] = fname_gz; |
60 |
cmd[ip++] = NULL; |
61 |
|
62 |
dup2(fdno[1], STDOUT_FILENO); |
63 |
close(fdno[0]); |
64 |
close(fdno[1]); |
65 |
execvp(cmd[0], cmd); |
66 |
perror("pciusb"); |
67 |
exit(2); |
68 |
} |
69 |
} else { |
70 |
ret.gztype = ZLIB; |
71 |
ret.u.zlib_fh = gzopen(fname_gz, "r"); |
72 |
if (!ret.u.zlib_fh) { |
73 |
perror("pciusb"); |
74 |
exit(3); |
75 |
} |
76 |
} |
77 |
free(fname_gz); |
78 |
} |
79 |
|
80 |
free(fname); |
81 |
return ret; |
82 |
} |
83 |
|
84 |
char* fh_gets(char *line, int size, fh *f) { |
85 |
char *ret = NULL; |
86 |
switch (f->gztype) { |
87 |
case ZLIB: |
88 |
ret = gzgets(f->u.zlib_fh, line, size); |
89 |
break; |
90 |
case GZIP: |
91 |
ret = fgets(line, size, f->u.gzip_fh.f); |
92 |
break; |
93 |
} |
94 |
return ret; |
95 |
} |
96 |
|
97 |
int fh_close(fh *f) { |
98 |
int ret = EOF; |
99 |
switch (f->gztype) { |
100 |
case ZLIB: |
101 |
ret = gzclose(f->u.zlib_fh); |
102 |
break; |
103 |
case GZIP: |
104 |
ret = fclose(f->u.gzip_fh.f); |
105 |
if (f->u.gzip_fh.pid > 0) |
106 |
waitpid(f->u.gzip_fh.pid, NULL, 0); |
107 |
break; |
108 |
} |
109 |
return ret; |
110 |
} |