/* * pacman * * Copyright (c) 2002 by Judd Vinet * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. */ #include "pacman.h" #include #include #include #include #include #include #include #include #include #include #include #include #include /* borrowed and modifed from Per Liden's pkgutils (http://crux.nu) */ static int gzopen_frontend(char *pathname, int oflags, int mode) { char* gzoflags; int fd; gzFile gzf; switch (oflags & O_ACCMODE) { case O_WRONLY: gzoflags = "w"; break; case O_RDONLY: gzoflags = "r"; break; case O_RDWR: default: errno = EINVAL; return -1; } if((fd = open(pathname, oflags, mode)) == -1) { return -1; } if((oflags & O_CREAT) && fchmod(fd, mode)) { return -1; } if(!(gzf = gzdopen(fd, gzoflags))) { errno = ENOMEM; return -1; } return (int)gzf; } static tartype_t gztype = { (openfunc_t) gzopen_frontend, (closefunc_t)gzclose, (readfunc_t) gzread, (writefunc_t)gzwrite }; /* * GLOBALS * */ FILE* dbfp = NULL; char* dbpath = PKGDB; char* pkgname = NULL; char* pkgver = NULL; char* pmo_root = NULL; unsigned short pmo_verbose = 0; unsigned short pmo_force = 0; unsigned short pmo_upgrade = 0; unsigned short pmo_nosave = 0; unsigned short pmo_nofunc = 0; unsigned short pmo_q_isfile = 0; unsigned short pmo_q_info = 0; unsigned short pmo_q_list = 0; char* pmo_q_owns = NULL; pkginfo_t** packages = NULL; unsigned int pkgcount = 0; int main(int argc, char* argv[]) { pm_opfunc_t op_func; char* funcvar = NULL; int ret = 0; /* default root */ pmo_root = (char*)malloc(2); strcpy(pmo_root, "/"); if(argc < 2) { usage(PM_MAIN, (char*)basename(argv[0])); return(0); } /* determine the requested operation and pass off to */ /* the handler function */ if(!strcmp(argv[1], "-A") || !strcmp(argv[1], "--add")) { op_func = pacman_add; funcvar = parseargs(PM_ADD, argc, argv); } else if(!strcmp(argv[1], "-R") || !strcmp(argv[1], "--remove")) { op_func = pacman_remove; funcvar = parseargs(PM_REMOVE, argc, argv); } else if(!strcmp(argv[1], "-Q") || !strcmp(argv[1], "--query")) { op_func = pacman_query; funcvar = parseargs(PM_QUERY, argc, argv); } else if(!strcmp(argv[1], "-U") || !strcmp(argv[1], "--upgrade")) { op_func = pacman_upgrade; funcvar = parseargs(PM_UPGRADE, argc, argv); } else if(!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) { usage(PM_MAIN, (char*)basename(argv[0])); return(1); } else if(!strcmp(argv[1], "-V") || !strcmp(argv[1], "--version")) { version(); return(1); } else { printf("error: invalid operation\n\n"); usage(PM_MAIN, (char*)basename(argv[0])); return(1); } if(funcvar == NULL && op_func != pacman_query) { return(1); } vprint("Installation Root: %s\n", pmo_root); vprint("Package Name: %s\n", funcvar); /* check for db existence */ if(pmo_root != NULL) { /* trim the trailing '/' if there is one */ if((int)rindex(pmo_root, '/') == ((int)pmo_root)+strlen(pmo_root)-1) { pmo_root[strlen(pmo_root)-1] = '\0'; } free(dbpath); dbpath = (char*)malloc(strlen(pmo_root) + strlen(PKGDB) + 1); strcpy(dbpath, pmo_root); dbpath = (char*)strcat(dbpath, PKGDB); } vprint("Using package DB: %s\n", dbpath); ret = db_open(dbpath); if(ret == 1) { printf("error: Could not open package database file!\n"); printf(" Check to see that %s exists.\n", dbpath); printf(" If not, you may simply create it by \"touch\"-ing it.\n"); return(1); } if(ret == 2) { printf("error: Database is corrupt! You may need to use the backup database.\n"); printf(" I hope you like tweaking... ;-)\n"); return(1); } /* start the requested operation */ if(!pmo_nofunc) { ret = op_func(funcvar); if(ret) { printf("There were errors\n"); } } fclose(dbfp); return(0); } int pacman_add(char* pkgfile) { int i, errors = 0; TAR* tar; char* errmsg = NULL; char* expath = NULL; char* newpath = NULL; fileset_t files = NULL; unsigned int filecount = 0, nb = 0; struct stat buf; /* Populate the file list */ filecount = load_pkg(pkgfile, &files, 0); if(filecount == 0) { return(1); } /* Now check for conflicts in the db */ vprint("Looking for DB conflicts...\n"); if((i = db_find_conflicts(files, filecount)) == 1) { if(pmo_force) { printf("\nInstalling package anyway...\n"); printf(" You might have duplicate entries in your package\n"); printf(" database now. You may want to edit it and remove\n"); printf(" one of the copies.\n\n"); } else { printf("Aborting...\n"); printf(" (use -f to override)\n\n"); return(1); } } else if(i == 2) { return(1); } else { vprint("No DB conflicts found\n"); } /* see if this is an upgrade. if so, remove the old package first */ if(pmo_upgrade) { vprint("Removing old package first...\n"); if(pacman_remove(pkgname)) { printf("\nUpgrade aborted.\n"); return(1); } } /* open the .tar.gz package */ if(tar_open(&tar, pkgfile, &gztype, O_RDONLY, 0, TAR_GNU) == -1) { perror("could not open package"); return(1); } vprint("Extracting files...\n"); for(i = 0; !th_read(tar); i++) { if(!strcmp(th_get_pathname(tar), ".PKGINFO")) { tar_skip_regfile(tar); continue; } /* build the new pathname relative to pmo_root */ expath = (char*)malloc(strlen(th_get_pathname(tar))+strlen(pmo_root)+2); strcpy(expath, pmo_root); strcat(expath, "/"); strcat(expath, th_get_pathname(tar)); /* see if this file should be backed up */ nb = needbackup(expath, files, filecount); vprint(" %s\n", expath); if(!pmo_nosave && nb && !stat(expath, &buf)) { /* backup this file */ newpath = (char*)realloc(newpath, strlen(expath)+6); strcpy(newpath, expath); strcat(newpath, ".save"); rename(expath, newpath); printf("%s renamed to %s\n", expath, newpath); } if(tar_extract_file(tar, expath)) { errmsg = strerror(errno); printf("could not extract %s: %s\n", th_get_pathname(tar), errmsg); errors = 1; } free(expath); } tar_close(tar); vprint("Done.\n"); if(errors) { printf("There were errors. No database update was performed.\n"); } else { vprint("Updating database...\n"); if(db_update(files, filecount)) { printf("error: Could not update database! The database may not\n"); printf(" be in a sane state!\n"); return(1); } vprint("Done.\n"); } return(0); } int pacman_remove(char* pkgfile) { int found = 0, done = 0; int i; char line[255]; fileset_t files = NULL; unsigned int filecount = 0, nb = 0; struct stat buf; char* newpath = NULL; char* file = NULL; if(pkgfile == NULL) { return(0); } /* find the package's filelist in the db */ rewind(dbfp); while(!found && !feof(dbfp)) { fgets(line, 255, dbfp); strcpy(line, trim(line)); if(!strcmp(line, pkgfile)) { /* read the version */ fgets(line, 255, dbfp); found = 1; } } if(!found) { printf("Cannot remove %s: Package was not found.\n", pkgfile); return(1); } while(!done) { fgets(line, 255, dbfp); strcpy(line, trim(line)); if(strlen(line)) { /* add the path to the list */ files = (fileset_t)realloc(files, (++filecount) * sizeof(char*)); files[filecount-1] = (char*)malloc(strlen(line)+1); strcpy(files[filecount-1], line); } else { done = 1; } } /* iterate through the list backwards, unlinking files */ for(i = filecount-1; i >= 0; i--) { file = (char*)realloc(file, strlen(files[i])+strlen(pmo_root)+1); strcpy(file, pmo_root); if(files[i][0] == '*') { nb = 1; strcat(file, (char*)(files[i]+1)); } else { nb = 0; strcat(file, files[i]); } if(lstat(file, &buf)) { vprint("file %s does not exist\n", file); continue; } if(S_ISDIR(buf.st_mode)) { vprint(" removing directory %s\n", file); if(rmdir(file)) { /* this is okay, other packages are probably using it. */ /* perror("cannot remove directory"); */ } } else { /* if the file ends in .conf, back it up */ if(!pmo_nosave && nb) { newpath = (char*)realloc(newpath, strlen(file)+6); strcpy(newpath, file); strcat(newpath, ".save"); rename(file, newpath); printf("%s renamed to %s\n", file, newpath); } else { vprint(" unlinking %s\n", file); if(unlink(file)) { perror("cannot remove file"); } } } } /* now splice this name out of the packages list */ found = 0; for(i = 0; i < pkgcount-1; i++) { if(found) { packages[i] = packages[i+1]; } else { if(!strcmp(packages[i]->name, pkgfile)) { found = 1; if(i < pkgcount-1) { packages[i] = packages[i+1]; } } } } /* drop the last item */ packages = (pkginfo_t**)realloc(packages, (--pkgcount)*sizeof(pkginfo_t*)); /* and commit the db */ return(db_update(NULL, 0)); } int pacman_query(char* pkgfile) { char *str = NULL; char name[255]; char ver[255]; char line[255]; int found = 0; int done = 0; int i; unsigned int filecount = 0; fileset_t files = NULL; /* output info for a .tar.gz package */ if(pmo_q_isfile) { filecount = load_pkg(pkgfile, &files, pmo_q_info); if(pmo_q_list) { for(i = 0; i < filecount; i++) { if(strcmp(files[i], ".PKGINFO")) { if(files[i][0] == '*') { printf("%s\n", (char*)(files[i]+1)); } else { printf("%s\n", files[i]); } } } } else { printf("%s %s\n", pkgname, pkgver); } return(0); } /* determine the owner of a file */ if(pmo_q_owns != NULL) { rewind(dbfp); while(!found && !feof(dbfp)) { fgets(name, 255, dbfp); strcpy(name, trim(name)); fgets(ver, 255, dbfp); strcpy(ver, trim(ver)); strcpy(line, " "); while(strlen(line) && !feof(dbfp)) { fgets(line, 255, dbfp); strcpy(line, trim(line)); str = line; str += strlen(pmo_root); if(!strcmp(line, pmo_q_owns)) { printf("%s %s\n", name, ver); return(0); } } } printf("No package owns this file.\n"); return(0); } /* find packages in the db */ rewind(dbfp); while(!done) { found = 0; while(!found && !feof(dbfp)) { fgets(name, 255, dbfp); strcpy(name, trim(name)); if(pkgfile == NULL || (pkgfile != NULL && !strcmp(name, pkgfile))) { /* read the version */ fgets(ver, 255, dbfp); strcpy(ver, trim(ver)); found = 1; if(pkgfile != NULL) { done = 1; } } } if(feof(dbfp)) { if(pkgfile != NULL && !found) { printf("Package was not found in database.\n"); } break; } found = 0; while(!found) { fgets(line, 255, dbfp); strcpy(line, trim(line)); if(strlen(line)) { if(pmo_q_list) { if(line[0] == '*') { printf("%s%s\n", pmo_root, (char*)(line+1)); } else { printf("%s%s\n", pmo_root, line); } } } else { found = 1; } } if(!pmo_q_list) { printf("%s %s\n", name, ver); } if(feof(dbfp)) { done = 1; } } return(0); } int pacman_upgrade(char* pkgfile) { /* this is basically just a remove,add process. pacman_add() will */ /* handle it */ pmo_upgrade = 1; pacman_add(pkgfile); return(0); } /* * Populate the package file list * pkgfile: filename of package * listptr: this will be set to the new fileset_t * * Returns: the number of filenames read in the package, or 0 on error * */ int load_pkg(char* pkgfile, fileset_t* listptr, unsigned short output) { char* expath; char* descfile; int i; TAR* tar; unsigned int filecount = 0; fileset_t files = NULL; fileset_t backup = NULL; unsigned int bakct = 0; descfile = (char*)malloc(strlen("/tmp/pacman_XXXXXX")+1); strcpy(descfile, "/tmp/pacman_XXXXXX"); if(tar_open(&tar, pkgfile, &gztype, O_RDONLY, 0, TAR_GNU) == -1) { perror("could not open package"); return(0); } vprint("Loading filelist from package...\n"); for(i = 0; !th_read(tar); i++) { if(!strcmp(th_get_pathname(tar), ".PKGINFO")) { /* extract this file into /tmp. it has info for us */ vprint("Found package description file.\n"); mkstemp(descfile); tar_extract_file(tar, descfile); parse_descfile(descfile, output, &backup, &bakct); continue; } /* build the new pathname relative to pmo_root */ if(is_in(th_get_pathname(tar), backup, bakct)) { expath = (char*)malloc(strlen(th_get_pathname(tar))+strlen(pmo_root)+3); // prepend the backup symbol strcpy(expath, "*"); } else { expath = (char*)malloc(strlen(th_get_pathname(tar))+strlen(pmo_root)+2); expath[0] = '\0'; } strcat(expath, pmo_root); strcat(expath, "/"); strcat(expath, th_get_pathname(tar)); /* add the path to the list */ files = (fileset_t)realloc(files, (++filecount) * sizeof(char*)); files[filecount-1] = expath; if(TH_ISREG(tar) && tar_skip_regfile(tar)) { perror("bad package file"); return(1); } expath = NULL; } tar_close(tar); if(pkgname == NULL || pkgver == NULL) { printf("The current version of Pacman requires a .PKGINFO file\n"); printf("present in the .tar.gz archive. This package does not\n"); printf("have one.\n"); return(0); } (*listptr) = files; return(filecount); } /* Open the database file * path: the full pathname of the file */ int db_open(char* path) { char line[255]; pkginfo_t* info; dbfp = fopen(path, "r"); if(dbfp == NULL) { return(1); } while(!feof(dbfp)) { info = (pkginfo_t*)malloc(sizeof(pkginfo_t)); fgets(line, 64, dbfp); if(feof(dbfp)) { break; } strcpy(info->name, trim(line)); fgets(line, 32, dbfp); strcpy(info->version, trim(line)); /* add to the collective */ packages = (pkginfo_t**)realloc(packages, (++pkgcount) * sizeof(pkginfo_t*)); packages[pkgcount-1] = info; for(;;) { fgets(line, 255, dbfp); if(feof(dbfp)) { return(2); } if(strlen(trim(line)) == 0) { break; } } } return(0); } /* Copy the old database file to a backup and build the * new copy in its place. * files: list of files in the new package, can be null * filecount: number of entries in files * * Returns: 0 on success * */ int db_update(fileset_t files, unsigned int filecount) { FILE* olddb; char* newpath = NULL; char* str = NULL; char name[64]; char ver[32]; char line[255]; int i = 0, found = 0, done = 0; /* build the backup pathname */ newpath = (char*)malloc(strlen(dbpath)+5); strcpy(newpath, dbpath); strcat(newpath, ".bak"); /* rename the existing db */ fclose(dbfp); rename(dbpath, newpath); olddb = fopen(newpath, "r"); free(newpath); dbfp = fopen(dbpath, "w"); if(olddb == NULL || dbfp == NULL) { return(1); } rewind(olddb); while(!feof(olddb)) { if(!fgets(name, 64, olddb)) { break; } strcpy(name, trim(name)); fgets(ver, 32, olddb); found = 0; for(i = 0; i < pkgcount && !found; i++) { if(!strcmp(packages[i]->name, name)) { /* it's there... copy the entries over */ found = 1; fputs(name, dbfp); fputc('\n', dbfp); fputs(ver, dbfp); for(done = 0; !done;) { fgets(line, 255, olddb); if(found) { fputs(line, dbfp); } if(strlen(trim(line)) == 0 || feof(olddb)) { done = 1; } } } } if(!found) { /* skip through filelist for this package */ for(done = 0; !done;) { fgets(line, 255, olddb); if(strlen(trim(line)) == 0 || feof(olddb)) { done = 1; } } } } fclose(olddb); /* write the current info */ if(files != NULL) { fputs(pkgname, dbfp); fputc('\n', dbfp); fputs(pkgver, dbfp); fputc('\n', dbfp); for(i = 0; i < filecount; i++) { str = files[i]; str += strlen(pmo_root); if(files[i][0] == '*') { fputc('*', dbfp); str++; } fputs(str, dbfp); fputc('\n', dbfp); } fputs("\n", dbfp); } fclose(dbfp); db_open(dbpath); return(0); } /* Check the database for conflicts * files: list of files in the new package * filecount: number of entries in files * * Returns: 0 if no conflicts were found, 1 otherwise * */ int db_find_conflicts(fileset_t files, unsigned int filecount) { int i; char line[255]; char name[255]; char* dbstr = NULL; char* filestr = NULL; struct stat buf; int conflicts = 0; /* CHECK 1: checking db conflicts */ rewind(dbfp); while(!feof(dbfp)) { fgets(name, 255, dbfp); strcpy(name, trim(name)); if(!pmo_upgrade && !strcmp(name, pkgname)) { printf("error: This package is already installed.\n"); printf(" Maybe you should be using --upgrade.\n"); return(2); } fgets(line, 255, dbfp); while(!feof(dbfp)) { fgets(line, 255, dbfp); strcpy(line, trim(line)); dbstr = line; if(dbstr[0] == '*') { dbstr++; } if(!strlen(dbstr)) { break; } if(index(dbstr, '/') == dbstr && (!pmo_upgrade || strcmp(name,pkgname))) { for(i = 0; i < filecount; i++) { filestr = files[i]; if(filestr[0] == '*') { filestr++; } if(!strcmp(dbstr, filestr)) { if(rindex(files[i], '/') == filestr+strlen(filestr)-1) { /* this filename has a trailing '/', so it's a directory -- skip it. */ continue; } printf("conflict: %s already exists in package \"%s\"\n", dbstr, name); conflicts = 1; } } } } } /* CHECK 2: checking filesystem conflicts */ /* TODO: run filesystem checks for upgrades */ for(i = 0; i < filecount && !pmo_upgrade; i++) { filestr = files[i]; if(filestr[0] == '*') { filestr++; } if(!stat(filestr, &buf) && !S_ISDIR(buf.st_mode)) { printf("conflict: %s already exists in filesystem\n", filestr); conflicts = 1; } } return(conflicts); } /* Parses the package description file for the current package * descfile: the full pathname of the description file * * Returns: 0 on success, 1 on error * */ int parse_descfile(char* descfile, unsigned short output, fileset_t *bakptr, unsigned int* bakct) { FILE* fp; char line[255]; char* ptr = NULL; char* key = NULL; int linenum = 0; fileset_t backup = NULL; unsigned int count = 0; if((fp = fopen(descfile, "r")) == NULL) { perror(descfile); return(1); } while(!feof(fp)) { fgets(line, 255, fp); if(output) { printf("%s", line); } linenum++; strcpy(line, trim(line)); if(index(line, '#') == (char*)line) { continue; } if(strlen(line) == 0) { continue; } ptr = line; key = strsep(&ptr, "="); if(key == NULL || ptr == NULL) { printf("Syntax error in description file line %d\n", linenum); } else { key = trim(key); key = strtoupper(key); ptr = trim(ptr); if(!strcmp(key, "PKGNAME")) { pkgname = (char*)malloc(strlen(ptr)+1); strcpy(pkgname, ptr); } else if(!strcmp(key, "PKGVER")) { pkgver = (char*)malloc(strlen(ptr)+1); strcpy(pkgver, ptr); } else if(!strcmp(key, "PKGDESC")) { /* Not used yet */ } else if(!strcmp(key, "BACKUP")) { backup = (fileset_t)realloc(backup, (++count) * sizeof(char*)); backup[count-1] = (char*)malloc(strlen(ptr)+1); strcpy(backup[count-1], ptr); } else { printf("Syntax error in description file line %d\n", linenum); } } line[0] = '\0'; } fclose(fp); unlink(descfile); if(count > 0) { (*bakptr) = backup; (*bakct) = count; } return(0); } /* Parse command-line arguments for each operation * op: the operation code requested * argc: argc * argv: argv * * Returns: the functional variable for that operation * (eg, the package file name for PM_ADD) */ char* parseargs(int op, int argc, char** argv) { char* pkg = NULL; int i; for(i = 2; i < argc; i++) { if(!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) { pmo_nofunc = 1; usage(op, (char*)basename(argv[0])); return(NULL); } else if(!strcmp(argv[i], "-v") || !strcmp(argv[i], "--verbose")) { pmo_verbose = 1; } else if(!strcmp(argv[i], "-f") || !strcmp(argv[i], "--force")) { pmo_force = 1; } else if(!strcmp(argv[i], "-r") || !strcmp(argv[i], "--root")) { i++; if(i >= argc) { printf("error: missing argument for %s\n", argv[i-1]); return(NULL); } free(pmo_root); pmo_root = (char*)malloc(PATH_MAX); if(realpath(argv[i], pmo_root) == NULL) { perror("bad root path"); return(NULL); } } else if(!strcmp(argv[i], "-n") || !strcmp(argv[i], "--nosave")) { pmo_nosave = 1; } else if(!strcmp(argv[i], "-o") || !strcmp(argv[i], "--owns")) { /* PM_QUERY only */ i++; if(i >= argc) { printf("error: missing argument for %s\n", argv[i-1]); return(NULL); } free(pmo_q_owns); pmo_q_owns = (char*)malloc(PATH_MAX); if(realpath(argv[i], pmo_q_owns) == NULL) { perror("bad path specified for --owns"); pmo_nofunc = 1; return(NULL); } } else if(!strcmp(argv[i], "-l") || !strcmp(argv[i], "--list")) { /* PM_QUERY only */ pmo_q_list = 1; } else if(!strcmp(argv[i], "-p") || !strcmp(argv[i], "--file")) { /* PM_QUERY only */ pmo_q_isfile = 1; } else if(!strcmp(argv[i], "-i") || !strcmp(argv[i], "--info")) { /* PM_QUERY only */ pmo_q_info = 1; } else { pkg = argv[i]; } } if(op != PM_QUERY && pkg == NULL) { printf("error: no package specified\n\n"); usage(op, (char*)basename(argv[0])); return(NULL); } if(op == PM_QUERY && pmo_q_isfile && pkg == NULL) { printf("error: no package file specified\n\n"); return(NULL); } return(pkg); } /* Display usage/syntax for the specified operation. * op: the operation code requested * myname: basename(argv[0]) */ void usage(int op, char* myname) { if(op == PM_MAIN) { printf("usage: %s {-h --help}\n", myname); printf(" %s {-V --version}\n", myname); printf(" %s {-A --add} [options] \n", myname); printf(" %s {-R --remove} [options] \n", myname); printf(" %s {-U --upgrade} [options] \n", myname); printf(" %s {-Q --query} [options] [package]\n", myname); } else if(op == PM_ADD) { printf("usage: %s {-A --add} [options] \n", myname); printf("options:\n"); printf(" -f, --force force install, overwrite conflicting files\n"); printf(" -n, --nosave do not save configuration files\n"); printf(" -v, --verbose be verbose\n"); printf(" -r, --root set an alternative installation root\n"); } else if(op == PM_REMOVE) { printf("usage: %s {-R --remove} [options] \n", myname); printf("options:\n"); printf(" -n, --nosave do not save configuration files\n"); printf(" -v, --verbose be verbose\n"); printf(" -r, --root set an alternative installation root\n"); } else if(op == PM_UPGRADE) { printf("usage: %s {-U --upgrade} [options] \n", myname); printf("options:\n"); printf(" -f, --force force install, overwrite conflicting files\n"); printf(" -n, --nosave do not save configuration files\n"); printf(" -v, --verbose be verbose\n"); printf(" -r, --root set an alternative installation root\n"); } else if(op == PM_QUERY) { printf("usage: %s {-Q --query} [options] [package]\n", myname); printf("options:\n"); printf(" -r, --root set an alternative installation root\n"); printf(" -o, --owns query the package that owns \n"); printf(" -l, --list list the contents of the queried package\n"); printf(" -i, --info output the .PKGINFO file (only used with -p)\n"); printf(" -p, --file if used, then [package] will be the path\n"); printf(" to an (uninstalled) package to query\n"); } } /* Version */ void version(void) { printf("\n"); printf(" .--. Pacman v%s\n", VERSION); printf("/ _.-' .-. .-. .-. Copyright (C) 2002 Judd Vinet \n"); printf("\\ '-. '-' '-' '-' \n"); printf(" '--' This program may be freely redistributed under\n"); printf(" the terms of the GNU GPL\n\n"); } /* Check verbosity option and, if set, print the * string to stdout */ int vprint(char* fmt, ...) { va_list args; if(pmo_verbose) { va_start(args, fmt); vprintf(fmt, args); va_end(args); fflush(stdout); } return(0); } /* See if a file should be backed up or not */ int needbackup(char* file, fileset_t files, unsigned int filect) { int i; for(i = 0; i < filect; i++) { if(files[i][0] == '*' && !strcmp((char*)(files[i]+1), file)) { return(1); } } return(0); } /* Test for existence of a string in a fileset */ int is_in(char* needle, fileset_t haystack, unsigned int hayct) { int i; for(i = 0; i < hayct; i++) { if(!strcmp(haystack[i], needle)) { return(1); } } return(0); } /* Convert a string to uppercase */ char* strtoupper(char* str) { char* ptr = str; while(*ptr) { (*ptr) = toupper(*ptr); ptr++; } return str; } /* Trim whitespace and newlines from a string */ char* trim(char* str) { char* start = str; char* end = str + strlen(str); int mid = 0; char ch; while(mid < 2) { if(!mid) { ch = *start; if(ch == 10 || ch == 13 || ch == 9 || ch == 32) { start++; } else { mid = 1; } } else { end--; ch = *end; if(ch == 10 || ch == 13 || ch == 9 || ch == 32) { *end = '\0'; } else { mid = 2; } } } return(start); } /* vim: set ts=2 noet: */