Implement @MAIN, @/path/name -e selectors, make former default for now

- the default might become "*" in future, but keep things more or less
  the same as they always were for now
diff --git a/breakpoints.c b/breakpoints.c
index 87e65d7..20044fa 100644
--- a/breakpoints.c
+++ b/breakpoints.c
@@ -362,8 +362,6 @@
 		}
 
 		proc_add_library(proc, lib);
-		fprintf(stderr, "note: symbols in %s were not filtered.\n",
-			lib->name);
 
 		entry_bp = malloc(sizeof(*entry_bp));
 		if (entry_bp == NULL
diff --git a/filter.c b/filter.c
index 74a158f..8aa5881 100644
--- a/filter.c
+++ b/filter.c
@@ -18,15 +18,13 @@
  * 02110-1301 USA
  */
 
-#include <stddef.h>
+#include <stdlib.h>
 #include <error.h>
 #include <assert.h>
 
 #include "filter.h"
 #include "library.h"
 
-void abort(void); //xxx
-
 void
 filter_init(struct filter *filt)
 {
@@ -71,10 +69,19 @@
 
 void
 filter_lib_matcher_name_init(struct filter_lib_matcher *matcher,
+			     enum filter_lib_matcher_type type,
 			     regex_t libname_re)
 {
-	matcher->type = FLM_NAME;
-	matcher->libname_re = libname_re;
+	switch (type) {
+	case FLM_MAIN:
+		assert(type != type);
+		abort();
+
+	case FLM_SONAME:
+	case FLM_PATHNAME:
+		matcher->type = type;
+		matcher->libname_re = libname_re;
+	}
 }
 
 void
@@ -87,7 +94,8 @@
 filter_lib_matcher_destroy(struct filter_lib_matcher *matcher)
 {
 	switch (matcher->type) {
-	case FLM_NAME:
+	case FLM_SONAME:
+	case FLM_PATHNAME:
 		regfree(&matcher->libname_re);
 		break;
 	case FLM_MAIN:
@@ -115,12 +123,14 @@
 matcher_matches_library(struct filter_lib_matcher *matcher, struct library *lib)
 {
 	switch (matcher->type) {
-	case FLM_NAME:
-		return re_match_or_error(&matcher->libname_re, lib->name,
-					 "library name");
+	case FLM_SONAME:
+		return re_match_or_error(&matcher->libname_re, lib->soname,
+					 "library soname");
+	case FLM_PATHNAME:
+		return re_match_or_error(&matcher->libname_re, lib->pathname,
+					 "library pathname");
 	case FLM_MAIN:
-		assert(!"FLM_MAIN not implemented yet!");
-		abort();
+		return lib->next == NULL;
 	}
 	assert(matcher->type != matcher->type);
 	abort();
diff --git a/filter.h b/filter.h
index 23ca382..0320036 100644
--- a/filter.h
+++ b/filter.h
@@ -31,8 +31,10 @@
 struct library_symbol;
 
 enum filter_lib_matcher_type {
-	/* Match by name.  */
-	FLM_NAME,
+	/* Match by soname.  */
+	FLM_SONAME,
+	/* Match by path name.  */
+	FLM_PATHNAME,
 	/* Match main binary.  */
 	FLM_MAIN,
 };
@@ -72,10 +74,12 @@
 /* RULE is added to FILT and owned and destroyed by it.  */
 void filter_add_rule(struct filter *filt, struct filter_rule *rule);
 
-/* Create a matcher that matches based on LIBNAME_RE is owned and
- * destroyed by MATCHER.  */
+/* Create a matcher that matches library name.  RE is owned and
+ * destroyed by MATCHER.  TYPE shall be FLM_SONAME or
+ * FLM_PATHNAME.  */
 void filter_lib_matcher_name_init(struct filter_lib_matcher *matcher,
-				  regex_t libname_re);
+				  enum filter_lib_matcher_type type,
+				  regex_t re);
 
 /* Create a matcher that matches main binary.  */
 void filter_lib_matcher_main_init(struct filter_lib_matcher *matcher);
diff --git a/handle_event.c b/handle_event.c
index cfb2ad0..28992d4 100644
--- a/handle_event.c
+++ b/handle_event.c
@@ -426,7 +426,8 @@
 		free(syscall);
 		return NULL;
 	}
-	library_init(syscalls, "SYS", 0);
+	library_init(syscalls);
+	library_set_soname(syscalls, "SYS", 0);
 	library_symbol_init(syscall, 0, name, 0, LS_TOPLT_NONE);
 	library_add_symbol(syscalls, syscall);
 	return syscall;
diff --git a/library.c b/library.c
index 07bbb7f..27c0f2b 100644
--- a/library.c
+++ b/library.c
@@ -100,22 +100,32 @@
 }
 
 void
-library_init(struct library *lib, const char *name, int own_name)
+library_init(struct library *lib)
 {
 	lib->next = NULL;
-	lib->name = name;
-	lib->own_name = own_name;
+	lib->soname = NULL;
+	lib->own_soname = 0;
+	lib->pathname = NULL;
+	lib->own_pathname = 0;
 	lib->symbols = NULL;
 }
 
 int
 library_clone(struct library *retp, struct library *lib)
 {
-	const char *name;
-	if (strdup_if_owned(&name, lib->name, lib->own_name) < 0)
+	const char *soname = NULL;
+	const char *pathname;
+	if (strdup_if_owned(&soname, lib->soname, lib->own_soname) < 0
+	     || strdup_if_owned(&pathname,
+				lib->pathname, lib->own_pathname) < 0) {
+		if (lib->own_soname)
+			free((char *)soname);
 		return -1;
+	}
 
-	library_init(retp, lib->name, lib->own_name);
+	library_init(retp);
+	library_set_soname(lib, soname, lib->own_soname);
+	library_set_soname(lib, pathname, lib->own_pathname);
 
 	struct library_symbol *it;
 	struct library_symbol **nsymp = &retp->symbols;
@@ -139,7 +149,8 @@
 {
 	if (lib == NULL)
 		return;
-	library_set_name(lib, NULL, 0);
+	library_set_soname(lib, NULL, 0);
+	library_set_pathname(lib, NULL, 0);
 
 	struct library_symbol *sym;
 	for (sym = lib->symbols; sym != NULL; ) {
@@ -151,12 +162,21 @@
 }
 
 void
-library_set_name(struct library *lib, const char *new_name, int own_name)
+library_set_soname(struct library *lib, const char *new_name, int own_name)
 {
-	if (lib->own_name)
-		free((char *)lib->name);
-	lib->name = new_name;
-	lib->own_name = own_name;
+	if (lib->own_soname)
+		free((char *)lib->soname);
+	lib->soname = new_name;
+	lib->own_soname = own_name;
+}
+
+void
+library_set_pathname(struct library *lib, const char *new_name, int own_name)
+{
+	if (lib->own_pathname)
+		free((char *)lib->pathname);
+	lib->pathname = new_name;
+	lib->own_pathname = own_name;
 }
 
 struct library_symbol *
@@ -205,8 +225,8 @@
 enum callback_status
 library_named_cb(struct Process *proc, struct library *lib, void *name)
 {
-	if (name == lib->name
-	    || strcmp(lib->name, (char *)name) == 0)
+	if (name == lib->soname
+	    || strcmp(lib->soname, (char *)name) == 0)
 		return CBS_STOP;
 	else
 		return CBS_CONT;
diff --git a/library.h b/library.h
index dbccb08..a517666 100644
--- a/library.h
+++ b/library.h
@@ -102,13 +102,16 @@
 
 	/* Symbols associated with the library.  */
 	struct library_symbol *symbols;
-	const char *name;
-	char own_name;
+
+	const char *soname;
+	const char *pathname;
+
+	char own_soname : 1;
+	char own_pathname : 1;
 };
 
-/* Init LIB.  NAME will be freed when LIB is destroyed if
- * OWN_NAME.  */
-void library_init(struct library *lib, const char *name, int own_name);
+/* Init LIB.  */
+void library_init(struct library *lib);
 
 /* Initialize RETP to a library identical to LIB.  Symbols are not
  * shared, but copied over.  Returns 0 on success and a negative value
@@ -118,8 +121,13 @@
 /* Destroy library.  Doesn't free LIB itself.  */
 void library_destroy(struct library *lib);
 
-/* Set library name.  Frees the old name if necessary.  */
-void library_set_name(struct library *lib, const char *new_name, int own_name);
+/* Set library soname.  Frees the old name if necessary.  */
+void library_set_soname(struct library *lib,
+			const char *new_name, int own_name);
+
+/* Set library pathname.  Frees the old name if necessary.  */
+void library_set_pathname(struct library *lib,
+			  const char *new_name, int own_name);
 
 /* Iterate through list of symbols of library LIB.  Restarts are
  * supported via START_AFTER (see each_process for details of
diff --git a/ltrace-elf.c b/ltrace-elf.c
index b20ea7c..6aa468e 100644
--- a/ltrace-elf.c
+++ b/ltrace-elf.c
@@ -465,28 +465,34 @@
 	proc->e_machine = lte.ehdr.e_machine;
 
 	struct library *lib = malloc(sizeof(*lib));
-	char *libname = NULL;
+	char *soname = NULL;
 	if (lib == NULL) {
 	fail:
-		free(libname);
+		free(soname);
 		library_destroy(lib);
 		free(lib);
 		lib = NULL;
 		goto done;
 	}
 
-	if (lte.soname != NULL)
-		libname = strdup(lte.soname);
-	else
-		libname = strdup(filename);
-	if (libname == NULL)
+	int own_soname;
+	if (lte.soname != NULL) {
+		soname = strdup(lte.soname);
+		own_soname = 1;
+	} else {
+		soname = rindex(filename, '/') + 1;
+		own_soname = 0;
+	}
+	if (soname == NULL)
 		goto fail;
 
 	target_address_t entry = (target_address_t)lte.entry_addr;
 	if (arch_translate_address(proc, entry + lte.bias, &entry) < 0)
 		goto fail;
 
-	library_init(lib, libname, 1);
+	library_init(lib);
+	library_set_soname(lib, soname, own_soname);
+	library_set_pathname(lib, filename, 1);
 	lib->base = (target_address_t)lte.base_addr;
 	lib->entry = entry;
 	lib->dyn_addr = (target_address_t)lte.dyn_addr;
@@ -541,7 +547,9 @@
 	fprintf(stderr, "ltelf_read_main_binary %d %s\n", proc->pid, path);
 	char *fname = pid2name(proc->pid);
 	struct library *lib = ltelf_read_library(proc, fname, 0);
-	if (lib != NULL)
-		library_set_name(lib, path, 0);
+	if (lib != NULL) {
+		library_set_pathname(lib, path, 0);
+		library_set_soname(lib, rindex(path, '/') + 1, 0);
+	}
 	return lib;
 }
diff --git a/options.c b/options.c
index 4f026ea..193b650 100644
--- a/options.c
+++ b/options.c
@@ -207,18 +207,26 @@
 		goto fail;
 	}
 
-	regex_t lib_re;
-	status = (lib_re_p ? regcomp : globcomp)(&lib_re, lib, 0);
-	if (status != 0) {
-		char buf[100];
-		regerror(status, &lib_re, buf, sizeof buf);
-		error(0, 0, "rule near '%s' will be ignored: %s", expr, buf);
+	if (strcmp(lib, "MAIN") == 0) {
+		filter_lib_matcher_main_init(matcher);
+	} else {
+		enum filter_lib_matcher_type type
+			= lib[0] == '/' ? FLM_PATHNAME : FLM_SONAME;
 
-		regfree(&symbol_re);
-		goto fail;
+		regex_t lib_re;
+		status = (lib_re_p ? regcomp : globcomp)(&lib_re, lib, 0);
+		if (status != 0) {
+			char buf[100];
+			regerror(status, &lib_re, buf, sizeof buf);
+			error(0, 0, "rule near '%s' will be ignored: %s",
+			      expr, buf);
+
+			regfree(&symbol_re);
+			goto fail;
+		}
+		filter_lib_matcher_name_init(matcher, type, lib_re);
 	}
 
-	filter_lib_matcher_name_init(matcher, lib_re);
 	filter_rule_init(rule, type, matcher, symbol_re);
 	filter_add_rule(filt, rule);
 }
@@ -628,8 +636,11 @@
 		opt_F = egg;
 	}
 
+	/* Set default filter.  Use @MAIN for now, as that's what
+	 * ltrace used to have in the past.  XXX Maybe we should make
+	 * this "*" instead.  */
 	if (options.filter == NULL)
-		parse_filter_chain(&options, "*");
+		parse_filter_chain(&options, "@MAIN");
 
 	if (!opt_p && argc < 1) {
 		fprintf(stderr, "%s: too few arguments\n", progname);
diff --git a/output.c b/output.c
index 10bfaf8..0f59e2e 100644
--- a/output.c
+++ b/output.c
@@ -176,7 +176,7 @@
 	begin_of_line(type, proc);
 #ifdef USE_DEMANGLE
 	current_column +=
-		fprintf(options.output, "%s->%s(", libsym->lib->name,
+		fprintf(options.output, "%s->%s(", libsym->lib->soname,
 			(options.demangle
 			 ? my_demangle(function_name) : function_name));
 #else
diff --git a/proc.c b/proc.c
index 8fc4cae..8c42c4a 100644
--- a/proc.c
+++ b/proc.c
@@ -500,8 +500,8 @@
 	assert(lib->next == NULL);
 	lib->next = proc->libraries;
 	proc->libraries = lib;
-	fprintf(stderr, "=== Added library %s@%p to %d:\n",
-		lib->name, lib->base, proc->pid);
+	fprintf(stderr, "=== Added library %s@%p (%s) to %d:\n",
+		lib->soname, lib->base, lib->pathname, proc->pid);
 
 	if (!filter_matches_library(options.filter, lib))
 		return;