
This is pretty ugly code, but it works well enough to deliver the right versions for the files in my test MSI. I can polish it later.
142 lines
2.9 KiB
C
142 lines
2.9 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <stdint.h>
|
|
#include <stdbool.h>
|
|
#include <stdarg.h>
|
|
#include <string.h>
|
|
#include <uchar.h>
|
|
#include <err.h>
|
|
|
|
#include <sys/types.h>
|
|
#include <sys/wait.h>
|
|
#include <unistd.h>
|
|
|
|
#include "fake-lib.h"
|
|
|
|
char *ascii(const char16_t *wstr, bool translate_slashes)
|
|
{
|
|
size_t len = 0;
|
|
for (const char16_t *wp = wstr; *wp; wp++)
|
|
len++;
|
|
char *ret = malloc(len + 1);
|
|
char *p = ret;
|
|
for (const char16_t *wp = wstr; *wp; wp++)
|
|
*p++ = (*wp == '\\' && translate_slashes ? '/' :
|
|
*wp < 0x80 ? *wp :
|
|
'?');
|
|
*p = '\0';
|
|
return ret;
|
|
}
|
|
|
|
void system_argv_array(char **args)
|
|
{
|
|
pid_t pid = fork();
|
|
if (pid < 0)
|
|
err(1, "fork");
|
|
|
|
if (pid == 0) {
|
|
execvp(args[0], args);
|
|
warn("execvp");
|
|
_exit(127);
|
|
}
|
|
|
|
int status;
|
|
if (waitpid(pid, &status, 0) != pid)
|
|
err(1, "waitpid");
|
|
if (!(WIFEXITED(status) && WEXITSTATUS(status) == 0))
|
|
errx(1, "subcommand failed");
|
|
}
|
|
|
|
void system_argv(const char *cmd, ...)
|
|
{
|
|
int nargs, nchars;
|
|
const char *word;
|
|
va_list ap;
|
|
|
|
va_start(ap, cmd);
|
|
nargs = 1; /* terminating NULL */
|
|
nchars = 0;
|
|
for (word = cmd; word; word = va_arg(ap, const char *)) {
|
|
nargs++;
|
|
nchars += 1 + strlen(word);
|
|
}
|
|
va_end(ap);
|
|
|
|
char *args[nargs], chars[nchars];
|
|
char **argp = args, *charp = chars;
|
|
va_start(ap, cmd);
|
|
for (word = cmd; word; word = va_arg(ap, const char *)) {
|
|
*argp++ = charp;
|
|
strcpy(charp, word);
|
|
charp += 1 + strlen(word);
|
|
}
|
|
va_end(ap);
|
|
*argp++ = NULL;
|
|
|
|
system_argv_array(args);
|
|
}
|
|
|
|
void c16cpy(char16_t *out, uint32_t *outsize, char *s)
|
|
{
|
|
uint32_t retlen = 0;
|
|
while (retlen < *outsize) {
|
|
char16_t c = (out[retlen] = (unsigned char)*s++);
|
|
if (!c)
|
|
break;
|
|
retlen++;
|
|
}
|
|
*outsize = retlen;
|
|
}
|
|
|
|
void *smalloc(size_t size)
|
|
{
|
|
void *toret = malloc(size);
|
|
if (!toret)
|
|
errx(1, "out of memory");
|
|
return toret;
|
|
}
|
|
|
|
void *srealloc(void *ptr, size_t size)
|
|
{
|
|
void *toret = realloc(ptr, size);
|
|
if (!toret)
|
|
errx(1, "out of memory");
|
|
return toret;
|
|
}
|
|
|
|
char *dupcat(const char *str, ...)
|
|
{
|
|
va_list ap;
|
|
const char *p;
|
|
char *out, *outp;
|
|
size_t len;
|
|
|
|
len = 1;
|
|
va_start(ap, str);
|
|
for (p = str; p; p = va_arg(ap, const char *))
|
|
len += strlen(p);
|
|
va_end(ap);
|
|
|
|
out = snewn(len, char);
|
|
outp = out;
|
|
va_start(ap, str);
|
|
for (p = str; p; p = va_arg(ap, const char *)) {
|
|
strcpy(outp, p);
|
|
outp += strlen(p);
|
|
}
|
|
va_end(ap);
|
|
|
|
return out;
|
|
}
|
|
|
|
unsigned le(const unsigned char *buf, size_t len, size_t off, size_t nbytes)
|
|
{
|
|
unsigned toret = 0;
|
|
off += nbytes;
|
|
while (nbytes-- > 0) {
|
|
toret <<= 8;
|
|
if (--off < len)
|
|
toret |= buf[off];
|
|
}
|
|
return toret;
|
|
}
|