summaryrefslogtreecommitdiff
path: root/scripts/chrpath_linux.c
diff options
context:
space:
mode:
authorclifford <clifford@b57f626f-c46c-0410-a088-ec61d464b74c>2010-01-30 05:43:13 (GMT)
committerclifford <clifford@b57f626f-c46c-0410-a088-ec61d464b74c>2010-01-30 05:43:13 (GMT)
commitb67fc38872af0d99da3558739b945109dc88bcb9 (patch)
tree8263d352ee4153302fb73f7b554f206cc8be57cc /scripts/chrpath_linux.c
parent9ade1afb07c705ba4955b325c1d241df5eb63d7d (diff)
Clifford Wolf:
Moved chrpath_linux.c to scripts (it belongs to release_linux) Added svn:ignore prop to objects directory git-svn-id: http://svn.clifford.at/openscad/trunk@371 b57f626f-c46c-0410-a088-ec61d464b74c
Diffstat (limited to 'scripts/chrpath_linux.c')
-rw-r--r--scripts/chrpath_linux.c769
1 files changed, 769 insertions, 0 deletions
diff --git a/scripts/chrpath_linux.c b/scripts/chrpath_linux.c
new file mode 100644
index 0000000..000244a
--- /dev/null
+++ b/scripts/chrpath_linux.c
@@ -0,0 +1,769 @@
+/***************************************************************************
+ * *
+ * This is a pre-configured single file version of chrpath for linux. *
+ * It is used in the binary installer for OpenSCAD on Linux. *
+ * *
+ * This file has been created by running *
+ * cat *.h *.c | sed 's, *# *include *",//&,' > ../chrpath_linux.c *
+ * in the configured chrpath-0.13 source directory (as found in the debian *
+ * package repository as the original download site seams to be down). *
+ * *
+ * chrpath is licensed under the terms of GPLv2: *
+ * *
+ * 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. *
+ * *
+ * The Authors are: *
+ * *
+ * Geoffrey Keating <geoffk@ozemail.com.au> *
+ * Implemented first version of chrpath.c based on first version of *
+ * killrpath. *
+ * Peeter Joot <peeterj@ca.ibm.com> *
+ * Implemented first version of killrpath.c. *
+ * Petter Reinholdtsen <pere@hungry.com> *
+ * Collected both implementations and made userfriendly wrapper. *
+ * *
+ * With patches from: *
+ * *
+ * Darren Salt <linux@youmustbejoking.demon.co.uk> *
+ * David Hull <hull@paracel.com> *
+ * Bradford W. Johnson <bradford@math.umn.edu> *
+ * Thomas Anders <anders@hmi.de> *
+ * Tollef Fog Heen <tollef@add.no> *
+ * *
+ ***************************************************************************/
+
+
+/* config.h. Generated by configure. */
+/* config.h.in. Generated from configure.ac by autoheader. */
+
+/* Define to 1 if you have the <elf.h> header file. */
+#define HAVE_ELF_H 1
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#define HAVE_FCNTL_H 1
+
+/* Define to 1 if you have the <getopt.h> header file. */
+#define HAVE_GETOPT_H 1
+
+/* Define to 1 if you have the `getopt_long' function. */
+#define HAVE_GETOPT_LONG 1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the <link.h> header file. */
+#define HAVE_LINK_H 1
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the <sys/link.h> header file. */
+/* #undef HAVE_SYS_LINK_H */
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Name of package */
+#define PACKAGE "chrpath"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "pere@hungry.com"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME ""chrpath""
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING ""chrpath" "0.13""
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "-chrpath-"
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION ""0.13""
+
+/* The size of a `void *', as computed by sizeof. */
+#define SIZEOF_VOID_P 4
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Version number of package */
+#define VERSION "0.13"
+
+/* Define to 1 if your processor stores words with the most significant byte
+ first (like Motorola and SPARC, unlike Intel and VAX). */
+/* #undef WORDS_BIGENDIAN */
+
+/* Define to empty if `const' does not conform to ANSI C. */
+/* #undef const */
+#ifndef PROTOS_H
+#define PROTOS_H
+
+#include <elf.h>
+//#include "config.h"
+
+#ifdef WORDS_BIGENDIAN
+#define ELFDATA2 ELFDATA2MSB
+#else
+#define ELFDATA2 ELFDATA2LSB
+#endif
+#if SIZEOF_VOID_P == 8
+#define Elf_Ehdr Elf64_Ehdr
+#define ELFCLASS ELFCLASS64
+#define Elf_Phdr Elf64_Phdr
+#define Elf_Shdr Elf64_Shdr
+#define Elf_Dyn Elf64_Dyn
+#elif SIZEOF_VOID_P == 4
+#define Elf_Ehdr Elf32_Ehdr
+#define ELFCLASS ELFCLASS32
+#define Elf_Phdr Elf32_Phdr
+#define Elf_Shdr Elf32_Shdr
+#define Elf_Dyn Elf32_Dyn
+#else
+#error "Unknown word size (SIZEOF_VOID_P)!"
+#endif
+
+int killrpath(const char *filename);
+int chrpath(const char *filename, const char *newpath, int convert);
+
+int elf_open(const char *filename, int flags, Elf_Ehdr *ehdr);
+void elf_close(int fd);
+int elf_find_dynamic_section(int fd, Elf_Ehdr *ehdr, Elf_Phdr *phdr);
+const char *elf_tagname(int tag);
+int elf_dynpath_tag(int tag);
+
+#endif /* PROTOS_H */
+/*
+<URL:http://gcc.gnu.org/ml/gcc/1999-04n/msg01105.html>
+
+Re: changing embedded RPATH in existing executables.
+
+ To: geoffk@ozemail.com.au
+ Subject: Re: changing embedded RPATH in existing executables.
+ From: <peeter_joot@VNET.IBM.COM> (peeter joot)
+ Date: Fri, 30 Apr 1999 16:14:44 -0400 (EDT)
+ Cc: peeterj@ca.ibm.com, egcs@cygnus.com, libc-hacker@cygnus.com, linux-gcc@vger.rutgers.edu
+ Reply-To: <peeter_joot@VNET.IBM.COM>
+
+> _Changing_ is a little tricky, but the attached program strips rpaths
+> from executables (I find it essential for debugging the binutils).
+> It's endian-dependent, if you want this for x86 you can just change
+> the occurrences of 'MSB' to 'LSB' and compile (I should really fix
+> that).
+
+Hi Geoff,
+
+With your program as a guide (and some peeks into libbfd, elf.h, a bit
+of the glibc dynamic loader code, objdump, and a hex-editor) I was able to
+figure out enough to find and change the rpath string. That was fun!
+
+This program assumes (unlike your original program) that there is only
+one DT_RPATH tag in the dynamic section as even with multiple '-Wl,-rpath,'
+commands in the link this seems to occur (they all get concatonated into
+a : separated path).
+
+Thanks for your help. If you want to use this on non-x86 you have to change
+the occurances of LSB back to MSB:)
+
+Peeter
+--
+*/
+
+#ifdef HAVE_CONFIG_H
+//# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <elf.h>
+#if defined(HAVE_LINK_H)
+# include <link.h>
+#endif /* HAVE_LINK_H */
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+//#include "protos.h"
+
+/**
+ * Reads an ELF file, and reads or alters the RPATH setting.
+ *
+ * TODO:
+ * modify to add RPATH setting if none exists.
+ */
+
+
+int
+chrpath(const char *filename, const char *newpath, int convert)
+{
+ int fd;
+ Elf_Ehdr ehdr;
+ int i;
+ Elf_Phdr phdr;
+ Elf_Shdr shdr;
+ Elf_Dyn *dyns;
+ int rpathoff;
+ char * strtab;
+ char * rpath;
+ unsigned int rpathlen;
+ int oflags;
+ int rpath_dyns_index;
+
+ if (NULL == newpath && 0 == convert)
+ oflags = O_RDONLY;
+ else
+ oflags = O_RDWR;
+
+ fd = elf_open(filename, oflags, &ehdr);
+ if (fd == -1)
+ {
+ perror ("elf_open");
+ return 1;
+ }
+
+ if (0 != elf_find_dynamic_section(fd, &ehdr, &phdr))
+ {
+ perror("found no dynamic section");
+ return 1;
+ }
+
+ dyns = malloc(phdr.p_filesz);
+ if (dyns == NULL)
+ {
+ perror ("allocating memory for dynamic section");
+ return 1;
+ }
+ memset(dyns, 0, phdr.p_filesz);
+ if (lseek(fd, phdr.p_offset, SEEK_SET) == -1
+ || read(fd, dyns, phdr.p_filesz) != (int)phdr.p_filesz)
+ {
+ perror ("reading dynamic section");
+ free(dyns);
+ return 1;
+ }
+
+ rpathoff = -1;
+ for ( rpath_dyns_index = 0; dyns[rpath_dyns_index].d_tag != DT_NULL;
+ ++rpath_dyns_index )
+ {
+ if ( elf_dynpath_tag(dyns[rpath_dyns_index].d_tag) )
+ {
+ rpathoff = dyns[rpath_dyns_index].d_un.d_ptr;
+ break;
+ }
+ }
+ if (rpathoff == -1)
+ {
+ printf("%s: no rpath or runpath tag found.\n", filename);
+ free(dyns);
+ return 2;
+ }
+
+ if (lseek(fd, ehdr.e_shoff, SEEK_SET) == -1)
+ {
+ perror ("positioning for sections");
+ free(dyns);
+ return 1;
+ }
+
+ for (i = 0; i < ehdr.e_shnum; i++)
+ {
+ if (read(fd, &shdr, sizeof(shdr)) != sizeof(shdr))
+ {
+ perror ("reading section header");
+ free(dyns);
+ return 1;
+ }
+ if (shdr.sh_type == SHT_STRTAB)
+ break;
+ }
+ if (i == ehdr.e_shnum)
+ {
+ fprintf (stderr, "No string table found.\n");
+ free(dyns);
+ return 2;
+ }
+ strtab = (char *)malloc(shdr.sh_size);
+ if (strtab == NULL)
+ {
+ perror ("allocating memory for string table");
+ free(dyns);
+ return 1;
+ }
+ memset(strtab, 0, shdr.sh_size);
+
+ if (lseek(fd, shdr.sh_offset, SEEK_SET) == -1)
+ {
+ perror ("positioning for string table");
+ free(strtab);
+ free(dyns);
+ return 1;
+ }
+ if (read(fd, strtab, shdr.sh_size) != (int)shdr.sh_size)
+ {
+ perror ("reading string table");
+ free(strtab);
+ free(dyns);
+ return 1;
+ }
+
+ if ((int)shdr.sh_size < rpathoff)
+ {
+ fprintf(stderr, "%s string offset not contained in string table",
+ elf_tagname(dyns[rpath_dyns_index].d_tag));
+ free(strtab);
+ free(dyns);
+ return 5;
+ }
+ rpath = strtab+rpathoff;
+
+#if defined(DT_RUNPATH)
+ if (convert && dyns[rpath_dyns_index].d_tag == DT_RPATH)
+ {
+ dyns[rpath_dyns_index].d_tag = DT_RUNPATH;
+ if (lseek(fd, phdr.p_offset, SEEK_SET) == -1
+ || write(fd, dyns, phdr.p_filesz) != (int)phdr.p_filesz)
+ {
+ perror ("converting RPATH to RUNPATH");
+ return 1;
+ }
+ printf("%s: RPATH converted to RUNPATH\n", filename);
+ }
+#endif /* DT_RUNPATH */
+
+ printf("%s: %s=%s\n", filename, elf_tagname(dyns[rpath_dyns_index].d_tag),
+ rpath);
+
+ if (NULL == newpath)
+ {
+ free(dyns);
+ free(strtab);
+ return 0;
+ }
+
+ rpathlen = strlen(rpath);
+
+ /*
+ * Calculate the maximum rpath length (will be equal to rpathlen unless
+ * we have previously truncated it).
+ */
+ for ( i = rpathoff + rpathlen ; (i < (int)shdr.sh_size
+ && strtab[i] == '\0') ; i++ )
+ ;
+ i--;
+
+ if (i > (int)(rpathoff + rpathlen))
+ rpathlen = i - rpathoff;
+
+ if (strlen(newpath) > rpathlen)
+ {
+ fprintf(stderr, "new rpath '%s' too large; maximum length %i\n",
+ newpath, rpathlen);
+ free(dyns);
+ free(strtab);
+ return 7;
+ }
+
+ memset(rpath, 0, rpathlen);
+ strcpy(rpath, newpath);
+
+ if (lseek(fd, shdr.sh_offset+rpathoff, SEEK_SET) == -1)
+ {
+ perror ("positioning for RPATH");
+ free(dyns);
+ free(strtab);
+ return 1;
+ }
+ if (write(fd, rpath, rpathlen) != (int)rpathlen)
+ {
+ perror ("writing RPATH");
+ free(dyns);
+ free(strtab);
+ return 1;
+ }
+ printf("%s: new %s: %s\n", filename,
+ elf_tagname(dyns[rpath_dyns_index].d_tag), rpath);
+
+ elf_close(fd);
+
+ free(dyns);
+ dyns = NULL;
+
+ free(strtab);
+
+ return 0;
+}
+
+#ifdef HAVE_CONFIG_H
+//# include "config.h"
+#endif
+
+#include <elf.h>
+#if defined(HAVE_SYS_LINK_H)
+# include <sys/link.h> /* Find DT_RPATH on Solaris 2.6 */
+#endif /* HAVE_SYS_LINK_H */
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <fcntl.h>
+//#include "protos.h"
+
+int
+elf_open(const char *filename, int flags, Elf_Ehdr *ehdr)
+{
+ int fd;
+
+ fd = open(filename, flags);
+ if (fd == -1)
+ {
+ perror ("open");
+ return -1;
+ }
+
+ if (read(fd, ehdr, sizeof(*ehdr)) != sizeof(*ehdr))
+ {
+ perror ("reading header");
+ close(fd);
+ return -1;
+ }
+
+ if (0 != memcmp(ehdr->e_ident, ELFMAG, SELFMAG) ||
+ ehdr->e_ident[EI_CLASS] != ELFCLASS ||
+ ehdr->e_ident[EI_DATA] != ELFDATA2 ||
+ ehdr->e_ident[EI_VERSION] != EV_CURRENT)
+ {
+ fprintf(stderr,
+#ifdef WORDS_BIGENDIAN
+ "`%s' probably isn't a %d-bit MSB-first ELF file.\n",
+#else /* not WORD_BIGENDIAN */
+ "`%s' probably isn't a %d-bit LSB-first ELF file.\n",
+#endif /* not WORD_BIGENDIAN */
+ filename, SIZEOF_VOID_P * 8);
+ close(fd);
+ errno = ENOEXEC; /* Hm, is this the best errno code to use? */
+ return -1;
+ }
+
+ if (ehdr->e_phentsize != sizeof(Elf_Phdr))
+ {
+ fprintf(stderr, "section size was read as %d, not %d!\n",
+ ehdr->e_phentsize, sizeof(Elf_Phdr));
+ close(fd);
+ return -1;
+ }
+ return fd;
+}
+
+int
+elf_find_dynamic_section(int fd, Elf_Ehdr *ehdr, Elf_Phdr *phdr)
+{
+ int i;
+ if (lseek(fd, ehdr->e_phoff, SEEK_SET) == -1)
+ {
+ perror ("positioning for sections");
+ return 1;
+ }
+
+ for (i = 0; i < ehdr->e_phnum; i++)
+ {
+ if (read(fd, phdr, sizeof(*phdr)) != sizeof(*phdr))
+ {
+ perror ("reading section header");
+ return 1;
+ }
+ if (phdr->p_type == PT_DYNAMIC)
+ break;
+ }
+ if (i == ehdr->e_phnum)
+ {
+ fprintf (stderr, "No dynamic section found.\n");
+ return 2;
+ }
+
+ if (0 == phdr->p_filesz)
+ {
+ fprintf (stderr, "Length of dynamic section is zero.\n");
+ return 3;
+ }
+
+ return 0;
+}
+
+void
+elf_close(int fd)
+{
+ close(fd);
+}
+
+const char *
+elf_tagname(int tag)
+{
+ switch (tag) {
+ case DT_RPATH:
+ return "RPATH";
+ break;
+#if defined(DT_RUNPATH)
+ case DT_RUNPATH:
+ return "RUNPATH";
+ break;
+#endif /* DT_RUNPATH */
+ }
+ return "UNKNOWN";
+}
+
+int
+elf_dynpath_tag(int tag)
+{
+ return ( tag == DT_RPATH
+#if defined(DT_RUNPATH)
+ || tag == DT_RUNPATH
+#endif /* DT_RUNPATH */
+ );
+}
+/*
+Taken from another list:
+
+_Changing_ is a little tricky, but the attached program strips rpaths
+from executables (I find it essential for debugging the binutils).
+It's endian-dependent, if you want this for x86 you can just change
+the occurrences of 'MSB' to 'LSB' and compile (I should really fix
+that).
+
+--
+Geoffrey Keating <geoffk@ozemail.com.au>
+*/
+
+#ifdef HAVE_CONFIG_H
+//# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <elf.h>
+#if defined(HAVE_LINK_H)
+# include <link.h>
+#endif /* HAVE_LINK_H */
+#include <stdlib.h>
+//#include "protos.h"
+#include <string.h>
+
+/* Reads an ELF file, nukes all the RPATH entries. */
+
+int
+killrpath(const char *filename)
+{
+ int fd;
+ Elf_Ehdr ehdr;
+ int i;
+ Elf_Phdr phdr;
+ Elf_Dyn *dyns;
+ int dynpos;
+
+ fd = elf_open(filename, O_RDWR, &ehdr);
+
+ if (fd == -1)
+ {
+ perror ("elf_open");
+ return 1;
+ }
+
+ if (0 != elf_find_dynamic_section(fd, &ehdr, &phdr))
+ {
+ perror("found no dynamic section");
+ return 1;
+ }
+
+ dyns = malloc(phdr.p_memsz);
+ if (dyns == NULL)
+ {
+ perror ("allocating memory for dynamic section");
+ return 1;
+ }
+ memset(dyns, 0, phdr.p_memsz);
+ if (lseek(fd, phdr.p_offset, SEEK_SET) == -1
+ || read(fd, dyns, phdr.p_filesz) != (int)phdr.p_filesz)
+ {
+ perror ("reading dynamic section");
+ return 1;
+ }
+
+ dynpos = 0;
+ for (i = 0; dyns[i].d_tag != DT_NULL; i++)
+ {
+ dyns[dynpos] = dyns[i];
+ if ( ! elf_dynpath_tag(dyns[i].d_tag) )
+ dynpos++;
+ }
+ for (; dynpos < i; dynpos++)
+ dyns[dynpos].d_tag = DT_NULL;
+
+ if (lseek(fd, phdr.p_offset, SEEK_SET) == -1
+ || write(fd, dyns, phdr.p_filesz) != (int)phdr.p_filesz)
+ {
+ perror ("writing dynamic section");
+ return 1;
+ }
+
+ elf_close(fd);
+
+ return 0;
+}
+/*
+ * Author: Petter Reinholdtsen <pere@hungry.com>
+ * date: 2001-01-20
+ *
+ * Alter ELF rpath information (insert, modify, remove).
+ *
+ * Based on source from Peeter Joot <peeterj@ca.ibm.com> and Geoffrey
+ * Keating <geoffk@ozemail.com.au>.
+ */
+
+#ifdef HAVE_CONFIG_H
+//# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#ifdef HAVE_GETOPT_H
+#include <getopt.h>
+#endif
+//#include "protos.h"
+
+#ifdef HAVE_GETOPT_LONG
+# define GETOPT_LONG getopt_long
+
+static struct option long_options[] =
+{
+ {"convert", 0, 0, 'c'},
+ {"delete", 0, 0, 'd'},
+ {"help", 0, 0, 'h'},
+ {"keepgoing", 0, 0, 'k'},
+ {"list", 0, 0, 'l'},
+ {"replace", 1, 0, 'r'},
+ {"version", 0, 0, 'v'}
+};
+
+#else /* not HAVE_GETOPT_LONG */
+# define GETOPT_LONG(argc,argv,optstr,lopts,lidx) getopt(argc,argv,optstr)
+#endif /* not HAVE_GETOPT_LONG */
+
+static void
+usage(char *progname)
+{
+ printf("Usage: %s [-v|-d|-c|-r <path>] <program> [<program> ...]\n\n",
+ progname);
+ printf(" -v|--version Display program version number\n");
+ printf(" -d|--delete Delete current rpath/runpath setting\n");
+#if defined(DT_RUNPATH)
+ printf(" -c|--convert Convert rpath to runpath\n");
+#endif /* DT_RUNPATH */
+ printf(" -r <path>|--replace <path> Replace current rpath/runpath setting\n");
+ printf(" with the path given\n");
+ printf(" -l|--list List the current rpath/runpath (default)\n");
+ printf(" -h|--help Show this usage information.\n");
+#ifndef HAVE_GETOPT_LONG
+ printf("\n *** The long options are not available on this platform");
+#endif /* not HAVE_GETOPT_LONG */
+#if !defined(DT_RUNPATH)
+ printf("\n *** There is no support for runpath on this platform");
+#endif /* DT_RUNPATH */
+ printf("\n");
+}
+
+int
+main(int argc, char * const argv[])
+{
+ int retval = 0;
+ int convert = 0; /* convert to given type */
+ int remove = 0; /* remove or not */
+ int keep_going = 0; /* Break on first error, or keep going? */
+ char *newpath = NULL; /* insert this path */
+ int opt;
+#ifdef HAVE_GETOPT_LONG
+ int option_index = 0;
+#endif /* HAVE_GETOPT_LONG */
+
+ if (argc < 2)
+ {
+ usage(argv[0]);
+ return 1;
+ }
+
+ do {
+ opt = GETOPT_LONG(argc, argv, "cdhklr:v", long_options, &option_index);
+ switch (opt)
+ {
+#if defined(DT_RUNPATH)
+ case 'c':
+ convert = 1;
+ break;
+#endif /* DT_RUNPATH */
+ case 'd':
+ remove = 1;
+ break;
+ case 'k':
+ keep_going = 1;
+ break;
+ case 'r':
+ newpath = optarg;
+ break;
+ case 'v':
+ printf("%s version %s\n", PACKAGE, VERSION);
+ exit(0);
+ break;
+ case 'l': /* This is the default action */
+ newpath = NULL;
+ break;
+ case -1:
+ break;
+ default:
+ printf("Invalid argument '%c'\n", opt);
+ case 'h':
+ usage(argv[0]);
+ exit(0);
+ break;
+ }
+ } while (-1 != opt);
+
+ while (optind < argc && (!retval || keep_going))
+ {
+ if (remove)
+ retval |= killrpath(argv[optind++]);
+ else
+ /* list by default, replace if path is set */
+ retval |= chrpath(argv[optind++], newpath, convert);
+ }
+
+ return retval;
+}
contact: Jan Huwald // Impressum