/* * This file is part of firk's window manager for x11 (fwm) * Copyright (C) 2022 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 #include #include #include "fwm-menu.h" #include "xdg_parser.h" static void fix_command(char *s) { size_t j, k; char c; for(j=k=0; c=s[j]; j++) { if(c!='%') { s[k++] = c; continue; } c = s[++j]; if(!c) break; if(c=='%') s[k++] = '%'; } s[k] = 0; } extern int parse_desktop_file(t_desktop_file *rr, int dirfd, char const *name) { int fd; char title[256], command[4096], path[4096]; char buf[4096], c, *b; unsigned int sz, p, p0, ln; int r, skip, in_section, use_term; size_t jj; /* TODO: distinguish between errors and not-shown entry */ while((fd = openat(dirfd, name, O_RDONLY|O_NOCTTY))<0) if(errno!=EINTR) { logprint("can't open file \"%s\"", name); return -1; } sz = 0; r = 1; skip = 0; ln = 1; in_section = 0; use_term = 0; title[0] = command[0] = path[0] = 0; while(r) { if(sz>=sizeof(buf)) break; while((r = read(fd, buf+sz, sizeof(buf)-sz))<0) if(errno!=EINTR) return -1; for(p=sz,p0=0,sz+=r; p=0 && c!=9 && c<32 || c==127)) { logprint("file \"%s\" line %u contains invalid symbols, skipping it", name, ln); skip = 1; } } if(p0) if(sz-=p0) bcopy(buf+p0, buf, sz); } close(fd); if(sz>=sizeof(buf)) logprint("file \"%s\" line %u too long, skipping all below", name, ln); else if(sz) logprint("file \"%s\" line %u (last) non-terminated, skipping it", name, ln); fix_command(command); if(!command[0]) return -1; if(!title[0]) { jj = strlen(name); if(jj<=8 || strcmp(name+(jj-8),".desktop")) return -1; if(jj>=sizeof(title)) jj = sizeof(title)-1; bcopy(name, title, jj); title[jj] = 0; } if(!(rr->title = strdup(title))) { logprint("out of memory"); return -1; } if(!(rr->command = strdup(command))) { free((void*)rr->title); logprint("out of memory"); return -1; } if(*path && !(rr->path = strdup(path))) { free((void*)rr->command); free((void*)rr->title); logprint("out of memory"); return -1; } rr->use_term = use_term; return 0; }