/* * This file is part of firk's window manager for x11 (fwm) * Copyright (C) 2016-2021 firk * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include #include #include "main.h" #include "config.h" #include "cfgparse.h" #define BSZ 16384 static char buf[BSZ]; static size_t p; static int append_str(char const * st) { size_t l; l = strlen(st); if(l>=BSZ-p) { logprint("(cfgparse) resulting string too long"); return -1; } bcopy(st, buf+p, l); p += l; buf[p] = 0; return 0; } static int append_char(char c) { if(1>=BSZ-p) { logprint("(cfgparse) resulting string too long"); return -1; } buf[p++] = c; buf[p] = 0; return 0; } extern char const * parse_str(char const * src, int dir) { char const * e; char c; size_t j; char en[64]; p = 0; if(dir && *src=='~') { if(src[1] && src[1]!='/') { logprint("(cfgparse) unsupported '~' usage"); return NULL; } if((e = getenv("HOME")) && append_str(e)<0 || append_char('/')<0) return NULL; if(!src[1]) return buf; src+=2; } while(c=*src) { if(c=='\\') { c = *(++src); if(!c) { logprint("(cfgparse) got '\\' at the end"); return NULL; } if(append_char(c)<0) return NULL; src++; continue; } if(c!='$') { if(append_char(c)<0) return NULL; src++; continue; } if(src[1]!='{') { for(j=0; ; j++) { if(j>=64) { logprint("(cfgparse) '$name' - name too long"); return NULL; } c = src[1+j]; if(c>='A' && c<='Z' || c>='a' && c<='z' || c>='0' && c<='9' || c=='_') en[j] = c; else { en[j] = 0; break; } } src += j+1; if((e = getenv(en)) && append_str(e)<0) return NULL; } else if(src[2]!='!') { for(j=0; ; j++) { if(j>=64 || !(c=src[2+j])) { logprint("(cfgparse) '${name}' - name too long and/or missing '}'"); return NULL; } if(c=='}') { en[j] = 0; break; } en[j] = c; } src += j+3; if((e = getenv(en)) && append_str(e)<0) return NULL; } else { for(j=0; ; j++) { if(j>=64 || !(c=src[3+j])) { logprint("(cfgparse) '${name}' - name too long and/or missing '}'"); return NULL; } if(c=='}') { en[j] = 0; break; } en[j] = c; } src += j+4; if(!(e = getenv(en))) { logprint("(cfgparse) '${!name}' - missing env var"); return NULL; } if(append_str(e)<0) return NULL; } } return buf; }