11 * Read one logical line from a configuration file.
13 * Line endings may be escaped with backslashes, to form one logical line from
14 * several physical lines. No end of line character(s) are included in the
17 * If linenum is not NULL, it is incremented by the number of physical lines
18 * which have been read.
20 char *getline_wrapped(FILE *file
, unsigned int *linenum
)
24 char *buf
= NOFAIL(malloc(size
));
26 int ch
= getc_unlocked(file
);
34 /* else fall through */
40 buf
= NOFAIL(realloc(buf
, size
+ 1));
45 ch
= getc_unlocked(file
);
52 /* else fall through */
59 buf
= NOFAIL(realloc(buf
, size
));
66 * Convert filename to the module name. Works if filename == modname, too.
68 void filename2modname(char *modname
, const char *filename
)
70 const char *afterslash
;
73 afterslash
= my_basename(filename
);
75 /* Convert to underscores, stop at first . */
76 for (i
= 0; afterslash
[i
] && afterslash
[i
] != '.'; i
++) {
77 if (afterslash
[i
] == '-')
80 modname
[i
] = afterslash
[i
];
86 * Replace dashes with underscores.
87 * Dashes inside character range patterns (e.g. [0-9]) are left unchanged.
89 char *underscores(char *string
)
96 for (i
= 0; string
[i
]; i
++) {
103 warn("Unmatched bracket in %s\n", string
);
107 i
+= strcspn(&string
[i
], "]");
109 warn("Unmatched bracket in %s\n", string
);
117 * Get the basename in a pathname.
118 * Unlike the standard implementation, this does not copy the string.
120 char *my_basename(const char *path
)
122 const char *base
= strrchr(path
, '/');
124 return (char *) base
+ 1;
125 return (char *) path
;
129 * Find the next string in an ELF section.
131 const char *next_string(const char *string
, unsigned long *secsize
)
133 /* Skip non-zero chars */
136 if ((*secsize
)-- <= 1)
140 /* Skip any zero padding. */
143 if ((*secsize
)-- <= 1)
150 * Get CPU endianness. 0 = unknown, 1 = ELFDATA2LSB = little, 2 = ELFDATA2MSB = big
152 int __attribute__ ((pure
)) native_endianness()
154 /* Encoding the endianness enums in a string and then reading that
155 * string as a 32-bit int, returns the correct endianness automagically.
157 return (char) *((uint32_t*)("\1\0\0\2"));
161 * Check ELF file header.
163 int elf_ident(void *file
, unsigned long fsize
, int *conv
)
165 /* "\177ELF" <byte> where byte = 001 for 32-bit, 002 for 64 */
166 unsigned char *ident
= file
;
168 if (fsize
< EI_CLASS
|| memcmp(file
, ELFMAG
, SELFMAG
) != 0)
169 return -ENOEXEC
; /* Not an ELF object */
170 if (ident
[EI_DATA
] == 0 || ident
[EI_DATA
] > 2)
171 return -EINVAL
; /* Unknown endianness */
174 *conv
= native_endianness() != ident
[EI_DATA
];
175 return ident
[EI_CLASS
];
178 #define PERBIT(x) x##32
179 #define ElfPERBIT(x) Elf32_##x
180 #define ELFPERBIT(x) ELF32_##x
181 #include "elf_core.c"
186 #define PERBIT(x) x##64
187 #define ElfPERBIT(x) Elf64_##x
188 #define ELFPERBIT(x) ELF64_##x
189 #include "elf_core.c"
191 void *get_section(void *file
, unsigned long filesize
,
192 const char *secname
, unsigned long *secsize
)
196 switch (elf_ident(file
, filesize
, &conv
)) {
198 return get_section32(file
, filesize
, secname
, secsize
, conv
);
200 return get_section64(file
, filesize
, secname
, secsize
, conv
);