3
* Copyright (C) 2008 Till Kamppeter <till.kamppeter@gmail.com>
4
* Copyright (C) 2008 Lars Uebernickel <larsuebernickel@gmx.de>
6
* This file is part of foomatic-rip.
8
* Foomatic-rip is free software; you can redistribute it and/or modify
9
* it under the terms of the GNU General Public License as published by
10
* the Free Software Foundation; either version 2 of the License, or
11
* (at your option) any later version.
13
* Foomatic-rip is distributed in the hope that it will be useful, but
14
* WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16
* General Public License for more details.
18
* You should have received a copy of the GNU Lesser General Public
19
* License along with this library; if not, write to the
20
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21
* Boston, MA 02111-1307, USA.
25
#include "foomaticrip.h"
34
const char* shellescapes = "|<>&!$\'\"#*?()[]{}";
36
const char * temp_dir()
38
static const char *tmpdir = NULL;
42
const char *dirs[] = { getenv("TMPDIR"), P_tmpdir, "/tmp", NULL };
45
for (dir = dirs; *dir; dir++)
46
if (access(*dir, W_OK) == 0) {
52
_log("Storing temporary files in %s\n", tmpdir);
53
setenv("TMPDIR", tmpdir, 1); /* for child processes */
56
rip_die(EXIT_PRNERR_NORETRY_BAD_SETTINGS,
57
"Cannot find a writable temp dir.");
63
int prefixcmp(const char *str, const char *prefix)
65
return strncmp(str, prefix, strlen(prefix));
68
int prefixcasecmp(const char *str, const char *prefix)
70
return strncasecmp(str, prefix, strlen(prefix));
73
int startswith(const char *str, const char *prefix)
75
return str ? (strncmp(str, prefix, strlen(prefix)) == 0) : 0;
78
int endswith(const char *str, const char *postfix)
80
int slen = strlen(str);
81
int plen = strlen(postfix);
87
pstr = &str[slen - plen];
88
return strcmp(str, postfix) == 0;
91
const char * skip_whitespace(const char *str)
93
while (*str && isspace(*str))
98
void strlower(char *dest, size_t destlen, const char *src)
101
const char *psrc = src;
102
while (*psrc && --destlen > 0)
104
*pdest = tolower(*psrc);
111
int isempty(const char *string)
113
return !string || string[0] == '\0';
116
const char * strncpy_omit(char* dest, const char* src, size_t n, int (*omit_func)(int))
118
const char* psrc = src;
124
while (*psrc != 0 && cnt > 0) {
125
if (!omit_func(*psrc)) {
136
int omit_unprintables(int c) { return c>= '\x00' && c <= '\x1f'; }
137
int omit_shellescapes(int c) { return strchr(shellescapes, c) != NULL; }
138
int omit_specialchars(int c) { return omit_unprintables(c) || omit_shellescapes(c); }
139
int omit_whitespace(int c) { return c == ' ' || c == '\t'; }
140
int omit_whitespace_newline(int c) { return omit_whitespace(c) || c == '\n'; }
142
#ifndef HAVE_STRCASESTR
144
strcasestr (const char *haystack, const char *needle)
146
char *p, *startn = 0, *np = 0;
148
for (p = haystack; *p; p++) {
150
if (toupper(*p) == toupper(*np)) {
155
} else if (toupper(*p) == toupper(*needle)) {
165
size_t strlcpy(char *dest, const char *src, size_t size)
168
const char *psrc = src;
176
while (--size && (*pdest++ = *psrc++) != '\0');
181
return (psrc - src -1);
184
size_t strlcat(char *dest, const char *src, size_t size)
187
const char *psrc = src;
191
while (--i && *pdest)
196
return strlen(src) + len;
202
return len + (psrc - src);
205
void strrepl(char *str, const char *chars, char repl)
210
if (strchr(chars, *p))
216
void strrepl_nodups(char *str, const char *chars, char repl)
223
if (strchr(chars, *pstr) || *pstr == repl) {
240
void strclr(char *str)
248
char * strnchr(const char *str, int c, size_t n)
250
char *p = (char*)str;
252
while (*p && --n > 0) {
260
void escapechars(char *dest, size_t size, const char *src, const char *esc_chars)
262
const char *psrc = src;
264
while (*psrc && --size > 0) {
265
if (strchr(esc_chars, *psrc))
271
const char * strncpy_tochar(char *dest, const char *src, size_t max, const char *stopchars)
273
const char *psrc = src;
278
while (*psrc && --max > 0 && !strchr(stopchars, *psrc)) {
287
int find_in_path(const char *progname, const char *paths, char *found_in)
291
char filepath[PATH_MAX];
293
if (access(progname, X_OK) == 0)
296
pathscopy = strdup(paths);
297
for (path = strtok(pathscopy, ":"); path; path = strtok(NULL, ":")) {
298
strlcpy(filepath, path, PATH_MAX);
299
strlcat(filepath, "/", PATH_MAX);
300
strlcat(filepath, progname, PATH_MAX);
302
if (access(filepath, X_OK) == 0) {
304
strlcpy(found_in, path, PATH_MAX);
316
void file_basename(char *dest, const char *path, size_t dest_size)
318
const char *p = strrchr(path, '/');
326
while (*p != 0 && *p != '.' && --dest_size > 0) {
332
void make_absolute_path(char *path, int len)
336
if (path[0] != '/') {
337
tmp = malloc(len +1);
338
strlcpy(tmp, path, len);
342
strlcpy(path, cwd, len);
343
strlcat(path, "/", len);
344
strlcat(path, tmp, len);
351
int is_true_string(const char *str)
353
return str && (!strcmp(str, "1") || !strcasecmp(str, "Yes") ||
354
!strcasecmp(str, "On") || !strcasecmp(str, "True"));
357
int is_false_string(const char *str)
359
return str && (!strcmp(str, "0") || !strcasecmp(str, "No") ||
360
!strcasecmp(str, "Off") || !strcasecmp(str, "False") ||
361
!strcasecmp(str, "None"));
366
if (c >= '0' && c <= '9')
367
return (int)c - (int)'0';
371
static const char * next_token(const char *string, const char *separators)
376
while (*string && !strchr(separators, *string))
379
while (*string && strchr(separators, *string))
385
static unsigned count_separators(const char *string, const char *separators)
393
for (p = string; *p; p = next_token(p, separators))
400
* Returns a zero terminated array of strings
402
char ** argv_split(const char *string, const char *separators, int *cntp)
411
if ((cnt = count_separators(string, separators)) == 0)
414
argv = malloc((cnt +1) * sizeof(char *));
417
for (i = 0; i < cnt; i++)
419
size_t len = strcspn(string, separators);
422
strncpy(s, string, len);
425
string = next_token(string, separators);
433
size_t argv_count(char **argv)
446
void argv_free(char **argv)
453
for (p = argv; *p; p++)
459
int line_count(const char *str)
470
int line_start(const char *str, int line_number)
473
while (*p && line_number > 0) {
481
void unhexify(char *dest, size_t size, const char *src)
484
const char *psrc = src;
489
while (*psrc && pdest - dest < size -1) {
495
if (!isxdigit(cstr[0]) || !isxdigit(cstr[1])) {
496
printf("Error replacing hex notation in %s!\n", src);
499
*pdest++ = (char)strtol(cstr, NULL, 16);
500
} while (*psrc != '>');
509
void extract_command(size_t *start, size_t *end, const char *cmdline, const char *cmd)
511
char *copy = strdup(cmdline);
513
const char *delim = "|;";
516
for (tok = strtok(copy, delim); tok; tok = strtok(NULL, delim)) {
517
while (*tok && isspace(*tok))
519
if (startswith(tok, cmd)) {
521
*end = tok + strlen(tok) - copy;
529
int contains_command(const char *cmdline, const char *cmd)
531
size_t start = 0, end = 0;
533
extract_command(&start, &end, cmdline, cmd);
534
if (start == 0 && end == 0)
543
dstr_t * create_dstr()
545
dstr_t *ds = malloc(sizeof(dstr_t));
548
ds->data = malloc(ds->alloc);
553
void free_dstr(dstr_t *ds)
559
void dstrclear(dstr_t *ds)
565
void dstrassure(dstr_t *ds, size_t alloc)
567
if (ds->alloc < alloc) {
569
ds->data = realloc(ds->data, ds->alloc);
573
void dstrcpy(dstr_t *ds, const char *src)
583
srclen = strlen(src);
585
if (srclen >= ds->alloc) {
588
} while (srclen >= ds->alloc);
589
ds->data = realloc(ds->data, ds->alloc);
592
strcpy(ds->data, src);
596
void dstrncpy(dstr_t *ds, const char *src, size_t n)
598
if (n >= ds->alloc) {
601
} while (n >= ds->alloc);
602
ds->data = realloc(ds->data, ds->alloc);
605
strncpy(ds->data, src, n);
607
ds->data[ds->len] = '\0';
610
void dstrncat(dstr_t *ds, const char *src, size_t n)
612
size_t needed = ds->len + n;
614
if (needed >= ds->alloc) {
617
} while (needed >= ds->alloc);
618
ds->data = realloc(ds->data, ds->alloc);
621
strncpy(&ds->data[ds->len], src, n);
623
ds->data[ds->len] = '\0';
626
void dstrcpyf(dstr_t *ds, const char *src, ...)
632
srclen = vsnprintf(ds->data, ds->alloc, src, ap);
635
if (srclen >= ds->alloc) {
638
} while (srclen >= ds->alloc);
639
ds->data = realloc(ds->data, ds->alloc);
642
vsnprintf(ds->data, ds->alloc, src, ap);
649
void dstrputc(dstr_t *ds, int c)
651
if (ds->len +1 >= ds->alloc) {
653
ds->data = realloc(ds->data, ds->alloc);
655
ds->data[ds->len++] = c;
656
ds->data[ds->len] = '\0';
659
void dstrcat(dstr_t *ds, const char *src)
661
size_t srclen = strlen(src);
662
size_t newlen = ds->len + srclen;
664
if (newlen >= ds->alloc) {
667
} while (newlen >= ds->alloc);
668
ds->data = realloc(ds->data, ds->alloc);
671
memcpy(&ds->data[ds->len], src, srclen +1);
675
void dstrcatf(dstr_t *ds, const char *src, ...)
678
size_t restlen = ds->alloc - ds->len;
682
srclen = vsnprintf(&ds->data[ds->len], restlen, src, ap);
685
if (srclen >= restlen) {
688
restlen = ds->alloc - ds->len;
689
} while (srclen >= restlen);
690
ds->data = realloc(ds->data, ds->alloc);
693
srclen = vsnprintf(&ds->data[ds->len], restlen, src, ap);
700
size_t fgetdstr(dstr_t *ds, FILE *stream)
706
if (ds->alloc == 0) {
708
ds->data = malloc(ds->alloc);
711
while ((c = fgetc(stream)) != EOF) {
712
if (ds->len +1 == ds->alloc) {
714
ds->data = realloc(ds->data, ds->alloc);
716
ds->data[ds->len++] = (char)c;
721
ds->data[ds->len] = '\0';
726
* Replace the first occurrence of 'find' after the index 'start' with 'repl'
727
* Returns the position right after the replaced string
729
int dstrreplace(dstr_t *ds, const char *find, const char *repl, int start)
732
dstr_t *copy = create_dstr();
735
dstrcpy(copy, ds->data);
737
if ((p = strstr(©->data[start], find)))
739
dstrncpy(ds, copy->data, p - copy->data);
740
dstrcatf(ds, "%s", repl);
742
dstrcatf(ds, "%s", p + strlen(find));
749
void dstrprepend(dstr_t *ds, const char *str)
751
dstr_t *copy = create_dstr();
752
dstrcpy(copy, ds->data);
754
dstrcatf(ds, "%s", copy->data);
758
void dstrinsert(dstr_t *ds, int idx, const char *str)
760
char * copy = strdup(ds->data);
761
size_t len = strlen(str);
768
if (ds->len + len >= ds->alloc) {
771
} while (ds->len + len >= ds->alloc);
773
ds->data = malloc(ds->alloc);
776
strncpy(ds->data, copy, idx);
777
ds->data[idx] = '\0';
778
strcat(ds->data, str);
779
strcat(ds->data, ©[idx]);
784
void dstrinsertf(dstr_t *ds, int idx, const char *str, ...)
791
len = vsnprintf(NULL, 0, str, ap);
794
strf = malloc(len +1);
796
vsnprintf(strf, len +1, str, ap);
799
dstrinsert(ds, idx, strf);
804
void dstrremove(dstr_t *ds, int idx, size_t count)
808
if (idx + count >= ds->len)
812
p2 = &ds->data[idx + count];
822
static inline int isnewline(int c)
824
return c == '\n' || c == '\r';
827
void dstrcatline(dstr_t *ds, const char *str)
829
size_t eol = strcspn(str, "\n\r");
830
if (isnewline(str[eol]))
832
dstrncat(ds, str, eol);
835
int dstrendswith(dstr_t *ds, const char *str)
837
int len = strlen(str);
842
pstr = &ds->data[ds->len - len];
843
return strcmp(pstr, str) == 0;
847
void dstrfixnewlines(dstr_t *ds)
849
if (ds->data[ds->len -1] == '\r') {
850
ds->data[ds->len -1] = '\n';
852
else if (ds->data[ds->len -2] == '\r') {
853
ds->data[ds->len -1] = '\n';
854
ds->data[ds->len -2] = '\0';
859
void dstrremovenewline(dstr_t *ds)
864
if (ds->data[ds->len -1] == '\r' || ds->data[ds->len -1] == '\n') {
865
ds->data[ds->len -1] = '\0';
872
if (ds->data[ds->len -2] == '\r') {
873
ds->data[ds->len -2] = '\0';
878
void dstrtrim(dstr_t *ds)
882
while (pos < ds->len && isspace(ds->data[pos]))
887
memmove(ds->data, &ds->data[pos], ds->len +1);
891
void dstrtrim_right(dstr_t *ds)
896
while (isspace(ds->data[ds->len -1]))
898
ds->data[ds->len] = '\0';
907
list_t * list_create()
909
list_t *l = malloc(sizeof(list_t));
915
list_t * list_create_from_array(int count, void ** data)
918
list_t *l = list_create();
920
for (i = 0; i < count; i++)
921
list_append(l, data[i]);
926
void list_free(list_t *list)
928
listitem_t *i = list->first, *tmp;
936
size_t list_item_count(list_t *list)
940
for (i = list->first; i; i = i->next)
945
list_t * list_copy(list_t *list)
947
list_t *l = list_create();
950
for (i = list->first; i; i = i->next)
951
list_append(l, i->data);
955
void list_prepend(list_t *list, void *data)
961
item = malloc(sizeof(listitem_t));
966
item->next = list->first;
967
list->first->next = item;
977
void list_append(list_t *list, void *data)
983
item = malloc(sizeof(listitem_t));
988
item->prev = list->last;
989
list->last->next = item;
999
void list_remove(list_t *list, listitem_t *item)
1004
item->prev->next = item->next;
1006
item->next->prev = item->prev;
1007
if (item == list->first)
1008
list->first = item->next;
1009
if (item == list->last)
1010
list->last = item->prev;
1015
listitem_t * list_get(list_t *list, int idx)
1018
for (i = list->first; i && idx; i = i->next)
1023
listitem_t * arglist_find(list_t *list, const char *name)
1026
for (i = list->first; i; i = i->next) {
1027
if (!strcmp((const char*)i->data, name))
1033
listitem_t * arglist_find_prefix(list_t *list, const char *name)
1036
for (i = list->first; i; i= i->next) {
1037
if (!prefixcmp((const char*)i->data, name))
1044
char * arglist_get_value(list_t *list, const char *name)
1049
for (i = list->first; i; i = i->next) {
1050
if (i->next && !strcmp(name, (char*)i->data))
1051
return (char*)i->next->data;
1052
else if (!prefixcmp((char*)i->data, name)) {
1053
p = &((char*)i->data)[strlen(name)];
1054
return *p == '=' ? p +1 : p;
1060
char * arglist_get(list_t *list, int idx)
1062
listitem_t *i = list_get(list, idx);
1063
return i ? (char*)i->data : NULL;
1066
int arglist_remove(list_t *list, const char *name)
1071
for (i = list->first; i; i = i->next) {
1072
i_name = (char*)i->data;
1073
if (i->next && !strcmp(name, i_name)) {
1074
list_remove(list, i->next);
1075
list_remove(list, i);
1078
else if (!prefixcmp(i_name, name)) {
1079
list_remove(list, i);
1086
int arglist_remove_flag(list_t *list, const char *name)
1088
listitem_t *i = arglist_find(list, name);
1090
list_remove(list, i);
1096
int copy_file(FILE *dest,
1098
const char *alreadyread,
1099
size_t alreadyread_len)
1104
if (alreadyread && alreadyread_len)
1106
if (fwrite(alreadyread, 1, alreadyread_len, dest) < alreadyread_len)
1108
_log("Could not write to temp file\n");
1113
while ((bytes = fread(buf, 1, 8192, src)))
1114
fwrite(buf, 1, bytes, dest);
1116
return !ferror(src) && !ferror(dest);