/* * This file is part of the KDE libraries * Copyright (c) 2001 Michael Goffioul * Copyright (c) 2014 Timothy Pearson * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License version 2 as published by the Free Software Foundation. * * This library 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. **/ #include #ifndef _GNU_SOURCE #define _GNU_SOURCE /* Needed for getline */ #endif #include #include #include #include #include #include #include #include #include #include #include extern "C" { #include "driverparse.h" } #define PROCESS_PPD_FILE_CONTENTS \ memset(value,0,256); \ c1 = strchr(line,':'); \ if (c1) \ { \ c2 = strchr(c1,'"'); \ if (c2) \ { \ c2++; \ c1 = strchr(c2,'"'); \ if (c1) strlcpy(value,c2,c1-c2+1); \ } \ else \ { \ c1++; \ while (*c1 && isspace(*c1)) \ c1++; \ if (!*c1) \ continue; \ c2 = line+strlen(line)-1; /* point to \n */ \ while (*c2 && isspace(*c2)) \ c2--; \ strlcpy(value,c1,c2-c1+2); \ } \ } \ count++; \ if (strncmp(line,"*Manufacturer:",14) == 0) fprintf(output_file,"MANUFACTURER=%s\n",value); \ else if (strncmp(line,"*ShortNickName:",15) == 0) fprintf(output_file,"MODEL=%s\n",value); \ else if (strncmp(line,"*ModelName:",11) == 0) fprintf(output_file,"MODELNAME=%s\n",value); \ else if (strncmp(line,"*NickName:",10) == 0) strncat(desc,value,255-strlen(desc)); \ else if (strncmp(line,"*pnpManufacturer:",17) == 0) fprintf(output_file,"PNPMANUFACTURER=%s\n",value); \ else if (strncmp(line,"*pnpModel:",10) == 0) fprintf(output_file,"PNPMODEL=%s\n",value); \ else if (strncmp(line,"*LanguageVersion:",17) == 0) strncat(langver,value,63-strlen(langver)); \ else count--; \ /* Either we got everything we needed, or we encountered an "OpenUI" directive \ * and it's reasonable to assume that there's no needed info further in the file, \ * just stop here */ \ if (count >= 7 || strncmp(line, "*OpenUI", 7) == 0) \ { \ if (strlen(langver) > 0) \ { \ strncat(desc, " [", 255-strlen(desc)); \ strncat(desc, langver, 255-strlen(desc)); \ strncat(desc, "]", 255-strlen(desc)); \ } \ if (strlen(desc) > 0) \ fprintf(output_file, "DESCRIPTION=%s\n", desc); \ break; \ } void initPpd(const char *dirname) { struct stat stat_res; if (stat(dirname, &stat_res) == -1) { fprintf(stderr, "Can't open drivers directory : %s\n", dirname); return; } if (S_ISDIR(stat_res.st_mode)) { DIR *dir = opendir(dirname); struct dirent *entry; char buffer[4096] = {0}; char drFile[256]; int len = strlen(dirname); if (dir == NULL) { fprintf(stderr, "Can't open drivers directory : %s\n", dirname); return; } while ((entry=readdir(dir)) != NULL) { if (strcmp(entry->d_name,".") == 0 || strcmp(entry->d_name,"..") == 0) { continue; } if (len+strlen(entry->d_name)+1 < 4096) { struct stat st; strcpy(buffer,dirname); strcat(buffer,"/"); strcat(buffer,entry->d_name); if (stat(buffer,&st) == 0) { if (S_ISDIR(st.st_mode)) { initPpd(buffer); } else if (S_ISREG(st.st_mode)) { char *c = strrchr(buffer,'.'); snprintf(drFile, 255, "ppd:%s", buffer); if (c && strncmp(c,".ppd",4) == 0) { addFile(drFile, "", ""); } else if (c && strncmp(c, ".gz", 3) == 0) { /* keep also compressed driver files */ while (c != buffer) { if (*(--c) == '.') break; } if (*c == '.' && strncmp(c, ".ppd",4) == 0) { addFile(drFile, "", ""); } } } } } } closedir(dir); } else if (access(dirname, X_OK) != -1) { char *filename; int n = strlen(dirname)+strlen(" list"); filename = (char*)malloc(n*sizeof(char)+1); memset(filename,0,n); strcat(filename, dirname); strcat(filename, " list"); FILE* file = popen(filename, "r"); if (file) { char * line = NULL; size_t len = 0; ssize_t read; while ((read = getline(&line, &len, file)) != -1) { char * pos1 = strstr(line, "\""); if (pos1 != NULL) { char * pos2 = strstr(pos1 + 1, "\""); if (pos2 != NULL) { *pos2 = 0; char * pos3 = strstr(pos1 + 1, ":"); if (pos3 != NULL) { char *ppduri; int n2 = strlen("compressed-ppd:")+strlen(pos3+1); ppduri = (char*)malloc(n2*sizeof(char)+1); memset(ppduri,0,n2); strcat(ppduri, "compressed-ppd:"); strcat(ppduri, pos3+1); addFile(ppduri, dirname, pos2+1); free(ppduri); ppduri = NULL; } } } } if (line) { free(line); } pclose(file); } else { fprintf(stderr, "Can't execute compressed driver handler : %s\n", dirname); } free(filename); filename = NULL; } else { fprintf(stderr, "Can't open drivers directory : %s\n", dirname); return; } } void initCompressedPpd(const char *dirname) { // HACK // The initPpd function actually handles the compressed PPDs as well, so do nothing here // If we were to rerun initPpd here then all drivers would be duplicated! } int parsePpdFile(const char *filename, const char * /*origin*/, const char * /*metadata*/, FILE *output_file) { gzFile ppd_file; char line[4096], value[256], langver[64] = {0}, desc[256] = {0}; char *c1, *c2; int count = 0; ppd_file = gzopen(filename,"r"); if (ppd_file == NULL) { fprintf(stderr, "Can't open driver file : %s\n", filename); return 0; } fprintf(output_file,"FILE=ppd:%s\n",filename); while (gzgets(ppd_file,line,4095) != Z_NULL) { PROCESS_PPD_FILE_CONTENTS } fprintf(output_file,"\n"); gzclose(ppd_file); return 1; } int parseCompressedPpdFile(const char *ppdfilename, const char *origin, const char *metadata, FILE *output_file) { char value[256], langver[64] = {0}, desc[256] = {0}; char *c1, *c2; int count = 0; bool useFallbackExtractionMethod = false; if (strlen(metadata) > 0) { TQString metadataProcessed(metadata); metadataProcessed = metadataProcessed.stripWhiteSpace(); TQStringList metadataList = TQStringList::split(" ", metadataProcessed, TRUE); TQLocale ppdLanguage(metadataList[0]); TQString languageVersion = TQLocale::languageToString(ppdLanguage.language()); metadataList = TQStringList::split("\" \"", metadataProcessed, TRUE); TQString description = metadataList[1]; int pos = metadataProcessed.find("MFG:"); if (pos < 0) { pos = metadataProcessed.find("MANUFACTURER:"); } if (pos >= 0) { TQString manufacturer; TQString model; TQString modelName; TQString pnpManufacturer; TQString pnpModel; TQString driver; TQStringList metadataList = TQStringList::split(";", metadataProcessed.mid(pos), TRUE); for (TQStringList::Iterator it = metadataList.begin(); it != metadataList.end(); ++it) { TQStringList kvPair = TQStringList::split(":", *it, TRUE); if ((kvPair[0].upper() == "MFG") || (kvPair[0].upper() == "MANUFACTURER")) { manufacturer = kvPair[1]; } else if ((kvPair[0].upper() == "MDL") ||(kvPair[0].upper() == "MODEL")) { modelName = kvPair[1]; } // else if (kvPair[0].upper() == "PNPMANUFACTURER") { // pnpManufacturer = kvPair[1]; // } // else if (kvPair[0].upper() == "PNPMODEL") { // pnpModel = kvPair[1]; // } else if ((kvPair[0].upper() == "DRV") || (kvPair[0].upper() == "DRIVER")) { driver = kvPair[1]; } } manufacturer = manufacturer.stripWhiteSpace(); modelName = modelName.stripWhiteSpace(); driver = driver.stripWhiteSpace(); TQStringList driverList = TQStringList::split(",", driver, TRUE); driver = driverList[0]; if (driver.startsWith("D")) { driver = driver.mid(1); driver = driver.stripWhiteSpace(); } model = manufacturer + " " + modelName + " " + driver; description = description + " [" + languageVersion + "]"; fprintf(output_file,"FILE=compressed-ppd:%s:%s\n", origin, ppdfilename); fprintf(output_file,"MANUFACTURER=%s\n",manufacturer.ascii()); fprintf(output_file,"MODELNAME=%s\n",modelName.ascii()); fprintf(output_file,"MODEL=%s\n",model.ascii()); if (pnpManufacturer.length() > 0) { fprintf(output_file,"PNPMANUFACTURER=%s\n",pnpManufacturer.ascii()); } if (pnpModel.length() > 0) { fprintf(output_file,"PNPMODEL=%s\n",pnpModel.ascii()); } if (description.length() > 0) { fprintf(output_file,"DESCRIPTION=%s\n",description.ascii()); } } else { useFallbackExtractionMethod = true; } } if (useFallbackExtractionMethod) { char *filename; int n = strlen(origin)+strlen(" cat ")+strlen(ppdfilename); filename = (char*)malloc(n*sizeof(char)+1); memset(filename,0,n); strcat(filename, origin); strcat(filename, " cat "); strcat(filename, ppdfilename); FILE* file = popen(filename, "r"); if (file) { char * line = NULL; size_t len = 0; ssize_t read; fprintf(output_file,"FILE=compressed-ppd:%s:%s\n", origin, ppdfilename); while ((read = getline(&line, &len, file)) != -1) { PROCESS_PPD_FILE_CONTENTS } if (line) { free(line); } pclose(file); } else { fprintf(stderr, "Can't open driver file : %s\n", ppdfilename); return 0; } free(filename); filename = NULL; } return 1; } int main(int argc, char *argv[]) { registerHandler("ppd:", initPpd, parsePpdFile); registerHandler("compressed-ppd:", initCompressedPpd, parseCompressedPpdFile); initFoomatic(); return execute(argc, argv); }