From 49e4bd18d29d5ef9c85d106026b09d86de6ff19c Mon Sep 17 00:00:00 2001 From: Mattias Andrée Date: Sat, 3 Apr 2021 02:28:44 +0200 Subject: First commmit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mattias Andrée --- .gitignore | 32 +++++++++++ LICENSE | 15 +++++ Makefile | 132 ++++++++++++++++++++++++++++++++++++++++++++ TODO | 30 ++++++++++ common.h | 4 ++ config.mk | 8 +++ find-contact-by-email.c | 62 +++++++++++++++++++++ find-contact-by-name.c | 74 +++++++++++++++++++++++++ find-contact-by-pgpkey.c | 62 +++++++++++++++++++++ find-contact-by-site.c | 62 +++++++++++++++++++++ get-contact-emails.c | 86 +++++++++++++++++++++++++++++ get-contact-file.c | 34 ++++++++++++ get-contact-gender.c | 57 +++++++++++++++++++ get-contact-name.c | 74 +++++++++++++++++++++++++ get-contact-notes.c | 35 ++++++++++++ get-contact-organisations.c | 86 +++++++++++++++++++++++++++++ get-contact-pgpkeys.c | 86 +++++++++++++++++++++++++++++ get-contact-sites.c | 86 +++++++++++++++++++++++++++++ is-contact-ice.c | 41 ++++++++++++++ list-contacts.c | 84 ++++++++++++++++++++++++++++ set-contact-emails.c | 105 +++++++++++++++++++++++++++++++++++ set-contact-gender.c | 71 ++++++++++++++++++++++++ set-contact-ice.c | 50 +++++++++++++++++ set-contact-name.c | 72 ++++++++++++++++++++++++ set-contact-notes.c | 62 +++++++++++++++++++++ set-contact-organisations.c | 106 +++++++++++++++++++++++++++++++++++ set-contact-pgpkeys.c | 105 +++++++++++++++++++++++++++++++++++ set-contact-sites.c | 105 +++++++++++++++++++++++++++++++++++ 28 files changed, 1826 insertions(+) create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 Makefile create mode 100644 TODO create mode 100644 common.h create mode 100644 config.mk create mode 100644 find-contact-by-email.c create mode 100644 find-contact-by-name.c create mode 100644 find-contact-by-pgpkey.c create mode 100644 find-contact-by-site.c create mode 100644 get-contact-emails.c create mode 100644 get-contact-file.c create mode 100644 get-contact-gender.c create mode 100644 get-contact-name.c create mode 100644 get-contact-notes.c create mode 100644 get-contact-organisations.c create mode 100644 get-contact-pgpkeys.c create mode 100644 get-contact-sites.c create mode 100644 is-contact-ice.c create mode 100644 list-contacts.c create mode 100644 set-contact-emails.c create mode 100644 set-contact-gender.c create mode 100644 set-contact-ice.c create mode 100644 set-contact-name.c create mode 100644 set-contact-notes.c create mode 100644 set-contact-organisations.c create mode 100644 set-contact-pgpkeys.c create mode 100644 set-contact-sites.c diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..fb34b0a --- /dev/null +++ b/.gitignore @@ -0,0 +1,32 @@ +*\#* +*~ +*.o +*.a +*.so +*.so.* +*.su +*.lo +/find-contact-by-email +/find-contact-by-name +/find-contact-by-pgpkey +/find-contact-by-site +/get-contact-emails +/get-contact-file +/get-contact-gender +/get-contact-name +/get-contact-notes +/get-contact-organisations +/get-contact-pgpkeys +/get-contact-sites +/is-contact-ice +/list-contact-organisations +/list-contacts +/list-organisation-contacts +/set-contact-emails +/set-contact-gender +/set-contact-ice +/set-contact-name +/set-contact-notes +/set-contact-organisations +/set-contact-pgpkeys +/set-contact-sites diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..c44b2d9 --- /dev/null +++ b/LICENSE @@ -0,0 +1,15 @@ +ISC License + +© 2021 Mattias Andrée + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..86040fa --- /dev/null +++ b/Makefile @@ -0,0 +1,132 @@ +.POSIX: + +CONFIGFILE = config.mk +include $(CONFIGFILE) + + +BIN =\ + find-contact-by-email\ + find-contact-by-name\ + find-contact-by-pgpkey\ + find-contact-by-site\ + get-contact-emails\ + get-contact-file\ + get-contact-gender\ + get-contact-name\ + get-contact-notes\ + get-contact-organisations\ + get-contact-pgpkeys\ + get-contact-sites\ + is-contact-ice\ + list-contacts\ + set-contact-emails\ + set-contact-gender\ + set-contact-ice\ + set-contact-name\ + set-contact-notes\ + set-contact-organisations\ + set-contact-pgpkeys\ + set-contact-sites + +HDR =\ + common.h + +OBJ = $(BIN:=.o) + + +all: $(BIN) +$(OBJ): $(@:.o=.c) $(HDR) + +libcontacts.a: $(OBJ) + $(AR) rc $@ $(OBJ) + $(AR) -s $@ + +.c.o: + $(CC) -c -o $@ $< $(CFLAGS) $(CPPFLAGS) + +find-contact-by-email: find-contact-by-email.o + $(CC) -o $@ $@.o $(LDFLAGS) + +find-contact-by-name: find-contact-by-name.o + $(CC) -o $@ $@.o $(LDFLAGS) + +find-contact-by-pgpkey: find-contact-by-pgpkey.o + $(CC) -o $@ $@.o $(LDFLAGS) + +find-contact-by-site: find-contact-by-site.o + $(CC) -o $@ $@.o $(LDFLAGS) + +get-contact-emails: get-contact-emails.o + $(CC) -o $@ $@.o $(LDFLAGS) + +get-contact-file: get-contact-file.o + $(CC) -o $@ $@.o $(LDFLAGS) + +get-contact-gender: get-contact-gender.o + $(CC) -o $@ $@.o $(LDFLAGS) + +get-contact-name: get-contact-name.o + $(CC) -o $@ $@.o $(LDFLAGS) + +get-contact-notes: get-contact-notes.o + $(CC) -o $@ $@.o $(LDFLAGS) + +get-contact-organisations: get-contact-organisations.o + $(CC) -o $@ $@.o $(LDFLAGS) + +get-contact-pgpkeys: get-contact-pgpkeys.o + $(CC) -o $@ $@.o $(LDFLAGS) + +get-contact-sites: get-contact-sites.o + $(CC) -o $@ $@.o $(LDFLAGS) + +is-contact-ice: is-contact-ice.o + $(CC) -o $@ $@.o $(LDFLAGS) + +list-contact-organisations: list-contact-organisations.o + $(CC) -o $@ $@.o $(LDFLAGS) + +list-contacts: list-contacts.o + $(CC) -o $@ $@.o $(LDFLAGS) + +list-organisation-contacts: list-organisation-contacts.o + $(CC) -o $@ $@.o $(LDFLAGS) + +set-contact-emails: set-contact-emails.o + $(CC) -o $@ $@.o $(LDFLAGS) + +set-contact-gender: set-contact-gender.o + $(CC) -o $@ $@.o $(LDFLAGS) + +set-contact-ice: set-contact-ice.o + $(CC) -o $@ $@.o $(LDFLAGS) + +set-contact-name: set-contact-name.o + $(CC) -o $@ $@.o $(LDFLAGS) + +set-contact-notes: set-contact-notes.o + $(CC) -o $@ $@.o $(LDFLAGS) + +set-contact-organisations: set-contact-organisations.o + $(CC) -o $@ $@.o $(LDFLAGS) + +set-contact-pgpkeys: set-contact-pgpkeys.o + $(CC) -o $@ $@.o $(LDFLAGS) + +set-contact-sites: set-contact-sites.o + $(CC) -o $@ $@.o $(LDFLAGS) + +install: $(BIN) + mkdir -p -- "$(DESTDIR)$(PREFIX)/bin" + cp -- $(BIN) "$(DESTDIR)$(PREFIX)/bin/" + +uninstall: + -cd -- "$(DESTDIR)$(PREFIX)/bin" && rm -f -- $(BIN) + +clean: + -rm -f -- *.o *.a *.lo *.so *.su $(BIN) + +.SUFFIXES: +.SUFFIXES: .c .o + +.PHONY: all install uninstall clean diff --git a/TODO b/TODO new file mode 100644 index 0000000..33d0025 --- /dev/null +++ b/TODO @@ -0,0 +1,30 @@ +list-contact-organisations +list-organisation-contacts + +Add tools for .photos +Add tools for .groups +Add tools for .blocks +Add tools for .numbers +Add tools for .addresses +Add tools for .chats +Add tools for .birthday +Test find-contact-by-email +Test find-contact-by-name +Test find-contact-by-pgpkey +Test find-contact-by-site +Test get-contact-emails +Test get-contact-name +Test get-contact-organisations +Test get-contact-pgpkeys +Test get-contact-sites +Test list-contact-organisations +Test list-organisation-contacts +Test set-contact-emails +Test set-contact-name +Test set-contact-organisations +Test set-contact-pgpkeys +Test set-contact-sites +Add man pages +Add readme +Add tests +Add multicall binary diff --git a/common.h b/common.h new file mode 100644 index 0000000..14c3319 --- /dev/null +++ b/common.h @@ -0,0 +1,4 @@ +/* See LICENSE file for copyright and license details. */ +#include "libcontacts.h" +#include "libsimple.h" +#include "libsimple-arg.h" diff --git a/config.mk b/config.mk new file mode 100644 index 0000000..34514f2 --- /dev/null +++ b/config.mk @@ -0,0 +1,8 @@ +PREFIX = /usr +MANPREFIX = $(PREFIX)/share/man + +CC = cc + +CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700 +CFLAGS = -std=c99 -Wall -O2 +LDFLAGS = -s -lcontacts -lsimple diff --git a/find-contact-by-email.c b/find-contact-by-email.c new file mode 100644 index 0000000..cff71db --- /dev/null +++ b/find-contact-by-email.c @@ -0,0 +1,62 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + +USAGE("[-c context] (-L | address)"); + + +int +main(int argc, char *argv[]) +{ + int list = 0; + struct passwd *user; + struct libcontacts_contact **contacts; + struct libcontacts_email **emails, *email; + char *context = NULL; + size_t i; + + ARGBEGIN { + case 'c': + if (context) + usage(); + context = ARG(); + break; + case 'L': + list = 1; + break; + default: + usage(); + } ARGEND; + + if (argc != 1 - list) + usage(); + + errno = 0; + user = getpwuid(getuid()); + if (!user) + eprintf("getpwuid: %s\n", errno ? strerror(errno) : "user does not exist"); + + if (libcontacts_load_contacts(&contacts, user)) + eprintf("libcontacts_load_contacts:"); + for (i = 0; contacts[i]; i++) { + if ((emails = contacts[i]->emails)) { + for (; (email = *emails); emails++) { + if (!email->address) + continue; + if (context && (!email->context || strcmp(email->context, context))) + continue; + if (list) + printf("%s (%s)\n", contacts[i]->id, email->address); + else if (!strcmp(email->address, argv[0])) + printf("%s\n", contacts[i]->id); + } + } + libcontacts_contact_destroy(contacts[i]); + free(contacts[i]); + } + free(contacts); + + if (fflush(stdout) || ferror(stdout) || fclose(stdout)) + eprintf("printf:"); + + return 0; +} diff --git a/find-contact-by-name.c b/find-contact-by-name.c new file mode 100644 index 0000000..d99f0a8 --- /dev/null +++ b/find-contact-by-name.c @@ -0,0 +1,74 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + +USAGE("[-F | -f | -l | -n] (-L | name)"); + + +int +main(int argc, char *argv[]) +{ + int list = 0; + struct passwd *user; + struct libcontacts_contact **contacts; + char *name; + size_t i, offset = 0; + + ARGBEGIN { + case 'F': + if (offset) + usage(); + offset = offsetof(struct libcontacts_contact, full_name); + break; + case 'f': + if (offset) + usage(); + offset = offsetof(struct libcontacts_contact, first_name); + break; + case 'l': + if (offset) + usage(); + offset = offsetof(struct libcontacts_contact, last_name); + break; + case 'n': + if (offset) + usage(); + offset = offsetof(struct libcontacts_contact, nickname); + break; + case 'L': + list = 1; + break; + default: + usage(); + } ARGEND; + + if (argc != 1 - list) + usage(); + + if (!offset) + offset = offsetof(struct libcontacts_contact, name); + + errno = 0; + user = getpwuid(getuid()); + if (!user) + eprintf("getpwuid: %s\n", errno ? strerror(errno) : "user does not exist"); + + if (libcontacts_load_contacts(&contacts, user)) + eprintf("libcontacts_load_contacts:"); + for (i = 0; contacts[i]; i++) { + name = *(char **)&offset[(char *)contacts[i]]; + if (list) { + if (name) + printf("%s (%s)\n", contacts[i]->id, name); + } else if (name && !strcmp(name, argv[0])) { + printf("%s\n", contacts[i]->id); + } + libcontacts_contact_destroy(contacts[i]); + free(contacts[i]); + } + free(contacts); + + if (fflush(stdout) || ferror(stdout) || fclose(stdout)) + eprintf("printf:"); + + return 0; +} diff --git a/find-contact-by-pgpkey.c b/find-contact-by-pgpkey.c new file mode 100644 index 0000000..85d2202 --- /dev/null +++ b/find-contact-by-pgpkey.c @@ -0,0 +1,62 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + +USAGE("[-c context] (-L | fingerprint)"); + + +int +main(int argc, char *argv[]) +{ + int list = 0; + struct passwd *user; + struct libcontacts_contact **contacts; + struct libcontacts_pgpkey **pgpkeys, *pgpkey; + char *context = NULL; + size_t i; + + ARGBEGIN { + case 'c': + if (context) + usage(); + context = ARG(); + break; + case 'L': + list = 1; + break; + default: + usage(); + } ARGEND; + + if (argc != 1 - list) + usage(); + + errno = 0; + user = getpwuid(getuid()); + if (!user) + eprintf("getpwuid: %s\n", errno ? strerror(errno) : "user does not exist"); + + if (libcontacts_load_contacts(&contacts, user)) + eprintf("libcontacts_load_contacts:"); + for (i = 0; contacts[i]; i++) { + if ((pgpkeys = contacts[i]->pgpkeys)) { + for (; (pgpkey = *pgpkeys); pgpkeys++) { + if (!pgpkey->id) + continue; + if (context && (!pgpkey->context || strcmp(pgpkey->context, context))) + continue; + if (list) + printf("%s (%s)\n", contacts[i]->id, pgpkey->id); + else if (!strcmp(pgpkey->id, argv[0])) + printf("%s\n", contacts[i]->id); + } + } + libcontacts_contact_destroy(contacts[i]); + free(contacts[i]); + } + free(contacts); + + if (fflush(stdout) || ferror(stdout) || fclose(stdout)) + eprintf("printf:"); + + return 0; +} diff --git a/find-contact-by-site.c b/find-contact-by-site.c new file mode 100644 index 0000000..afda922 --- /dev/null +++ b/find-contact-by-site.c @@ -0,0 +1,62 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + +USAGE("[-c context] (-L | address)"); + + +int +main(int argc, char *argv[]) +{ + int list = 0; + struct passwd *user; + struct libcontacts_contact **contacts; + struct libcontacts_site **sites, *site; + char *context = NULL; + size_t i; + + ARGBEGIN { + case 'c': + if (context) + usage(); + context = ARG(); + break; + case 'L': + list = 1; + break; + default: + usage(); + } ARGEND; + + if (argc != 1 - list) + usage(); + + errno = 0; + user = getpwuid(getuid()); + if (!user) + eprintf("getpwuid: %s\n", errno ? strerror(errno) : "user does not exist"); + + if (libcontacts_load_contacts(&contacts, user)) + eprintf("libcontacts_load_contacts:"); + for (i = 0; contacts[i]; i++) { + if ((sites = contacts[i]->sites)) { + for (; (site = *sites); sites++) { + if (!site->address) + continue; + if (context && (!site->context || strcmp(site->context, context))) + continue; + if (list) + printf("%s (%s)\n", contacts[i]->id, site->address); + else if (!strcmp(site->address, argv[0])) + printf("%s\n", contacts[i]->id); + } + } + libcontacts_contact_destroy(contacts[i]); + free(contacts[i]); + } + free(contacts); + + if (fflush(stdout) || ferror(stdout) || fclose(stdout)) + eprintf("printf:"); + + return 0; +} diff --git a/get-contact-emails.c b/get-contact-emails.c new file mode 100644 index 0000000..433cf22 --- /dev/null +++ b/get-contact-emails.c @@ -0,0 +1,86 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + +USAGE("[-c context] [-a address] [-CA] contact-id ..."); + + +int +main(int argc, char *argv[]) +{ + int display_ctx = 0, display_addr = 0; + struct passwd *user; + struct libcontacts_contact contact; + struct libcontacts_email **emails, *email; + const char *lookup_ctx = NULL, *lookup_addr = NULL; + int ret = 0; + size_t i; + + ARGBEGIN { + case 'c': + if (lookup_ctx) + usage(); + lookup_ctx = ARG(); + break; + case 'a': + if (lookup_addr) + usage(); + lookup_addr = ARG(); + break; + case 'C': + display_ctx = 1; + break; + case 'A': + display_addr = 1; + break; + default: + usage(); + } ARGEND; + + if (!argc) + usage(); + + if (lookup_ctx && !lookup_addr && !display_ctx && !display_addr) + display_addr = 1; + if (lookup_addr && !lookup_ctx && !display_ctx && !display_addr) + display_ctx = 1; + + for (i = 0; argv[i]; i++) + if (!*argv[i] || strchr(argv[i], '/')) + usage(); + + errno = 0; + user = getpwuid(getuid()); + if (!user) + eprintf("getpwuid: %s\n", errno ? strerror(errno) : "user does not exist"); + + for (; *argv; argv++) { + if (libcontacts_load_contact(*argv, &contact, user)) { + weprintf("libcontacts_load_contact %s: %s\n", *argv, errno ? strerror(errno) : "contact file is malformatted"); + ret = 1; + } else { + for (emails = contact.emails; (email = *emails); emails++) { + if (lookup_ctx && (!email->context || strcmp(email->context, lookup_ctx))) + continue; + if (lookup_addr && (!email->address || strcmp(email->address, lookup_addr))) + continue; + if (lookup_ctx && lookup_addr && !display_ctx && !display_addr) { + printf("%s\n", *argv); + continue; + } + if (argc > 1) + printf("%s: ", *argv); + if (display_ctx && display_addr) + printf("%s: %s\n", email->context, email->address); + else if (display_addr) + printf("%s\n", email->address); + else + printf("%s\n", email->context); + } + libcontacts_contact_destroy(&contact); + } + } + + if (fflush(stdout) || ferror(stdout) || fclose(stdout)) + eprintf("printf:"); + return ret; +} diff --git a/get-contact-file.c b/get-contact-file.c new file mode 100644 index 0000000..e244941 --- /dev/null +++ b/get-contact-file.c @@ -0,0 +1,34 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + +/* Useful for deleting or backing up contacts */ + +USAGE("contact-id"); + + +int +main(int argc, char *argv[]) +{ + struct passwd *user; + char *path; + + NOFLAGS(argc != 1); + + if (!*argv[0] || strchr(argv[0], '/')) + usage(); + + errno = 0; + user = getpwuid(getuid()); + if (!user) + eprintf("getpwuid: %s\n", errno ? strerror(errno) : "user does not exist"); + + path = libcontacts_get_path(argv[0], user); + if (!path) + eprintf("libcontacts_get_path %s:", argv[0]); + + printf("%s\n", path); + + if (fflush(stdout) || ferror(stdout) || fclose(stdout)) + eprintf("printf:"); + return 0; +} diff --git a/get-contact-gender.c b/get-contact-gender.c new file mode 100644 index 0000000..32fef81 --- /dev/null +++ b/get-contact-gender.c @@ -0,0 +1,57 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + +USAGE("[-f] contact-id ..."); + + +int +main(int argc, char *argv[]) +{ + struct passwd *user; + struct libcontacts_contact contact; + int output_flag = 0, ret = 0; + size_t i; + + ARGBEGIN { + case 'f': + output_flag = 1; + break; + default: + usage(); + } ARGEND; + + if (!argc) + usage(); + + for (i = 0; argv[i]; i++) + if (!*argv[i] || strchr(argv[i], '/')) + usage(); + + errno = 0; + user = getpwuid(getuid()); + if (!user) + eprintf("getpwuid: %s\n", errno ? strerror(errno) : "user does not exist"); + + for (; *argv; argv++) { + if (libcontacts_load_contact(*argv, &contact, user)) { + weprintf("libcontacts_load_contact %s: %s\n", *argv, errno ? strerror(errno) : "contact file is malformatted"); + ret = 1; + } else { + if (argc > 1) + printf("%s: ", *argv); + if (contact.gender == LIBCONTACTS_NOT_A_PERSON) + printf("%s\n", output_flag ? "-o" : "none"); + else if (contact.gender == LIBCONTACTS_MALE) + printf("%s\n", output_flag ? "-m" : "male"); + else if (contact.gender == LIBCONTACTS_FEMALE) + printf("%s\n", output_flag ? "-f" : "female"); + else + printf("%s\n", output_flag ? "-u" : "unset"); + libcontacts_contact_destroy(&contact); + } + } + + if (fflush(stdout) || ferror(stdout) || fclose(stdout)) + eprintf("printf:"); + return ret; +} diff --git a/get-contact-name.c b/get-contact-name.c new file mode 100644 index 0000000..8a0ae0c --- /dev/null +++ b/get-contact-name.c @@ -0,0 +1,74 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + +USAGE("[-F | -f | -l | n] contact-id ..."); + + +int +main(int argc, char *argv[]) +{ + struct passwd *user; + struct libcontacts_contact contact; + int ret = 0; + size_t i, offset = 0; + char *name; + + ARGBEGIN { + case 'F': + if (offset) + usage(); + offset = offsetof(struct libcontacts_contact, full_name); + break; + case 'f': + if (offset) + usage(); + offset = offsetof(struct libcontacts_contact, first_name); + break; + case 'l': + if (offset) + usage(); + offset = offsetof(struct libcontacts_contact, last_name); + break; + case 'n': + if (offset) + usage(); + offset = offsetof(struct libcontacts_contact, nickname); + break; + default: + usage(); + } ARGEND; + + if (!argc) + usage(); + + for (i = 0; argv[i]; i++) + if (!*argv[i] || strchr(argv[i], '/')) + usage(); + + if (!offset) + offset = offsetof(struct libcontacts_contact, name); + + errno = 0; + user = getpwuid(getuid()); + if (!user) + eprintf("getpwuid: %s\n", errno ? strerror(errno) : "user does not exist"); + + for (; *argv; argv++) { + if (libcontacts_load_contact(*argv, &contact, user)) { + weprintf("libcontacts_load_contact %s: %s\n", *argv, errno ? strerror(errno) : "contact file is malformatted"); + ret = 1; + } else { + name = *(char **)&offset[(char *)&contact]; + if (name) { + if (argc > 1) + printf("%s: ", *argv); + printf("%s\n", name); + } + libcontacts_contact_destroy(&contact); + } + } + + if (fflush(stdout) || ferror(stdout) || fclose(stdout)) + eprintf("printf:"); + return ret; +} diff --git a/get-contact-notes.c b/get-contact-notes.c new file mode 100644 index 0000000..96235b4 --- /dev/null +++ b/get-contact-notes.c @@ -0,0 +1,35 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + +USAGE("contact-id"); + + +int +main(int argc, char *argv[]) +{ + struct passwd *user; + struct libcontacts_contact contact; + + NOFLAGS(argc != 1); + + if (!*argv[0] || strchr(argv[0], '/')) + usage(); + + errno = 0; + user = getpwuid(getuid()); + if (!user) + eprintf("getpwuid: %s\n", errno ? strerror(errno) : "user does not exist"); + + if (libcontacts_load_contact(argv[0], &contact, user)) + eprintf("libcontacts_load_contact %s: %s\n", argv[0], errno ? strerror(errno) : "contact file is malformatted"); + + if (contact.notes && *contact.notes) { + printf("%s", contact.notes); + if (fflush(stdout) || ferror(stdout) || fclose(stdout)) + eprintf("printf:"); + } + + libcontacts_contact_destroy(&contact); + + return 0; +} diff --git a/get-contact-organisations.c b/get-contact-organisations.c new file mode 100644 index 0000000..c16b333 --- /dev/null +++ b/get-contact-organisations.c @@ -0,0 +1,86 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + +USAGE("[-o organisation] [-t title] [-OT] contact-id ..."); + + +int +main(int argc, char *argv[]) +{ + int display_org = 0, display_title = 0; + struct passwd *user; + struct libcontacts_contact contact; + struct libcontacts_organisation **orgs, *org; + const char *lookup_org = NULL, *lookup_title = NULL; + int ret = 0; + size_t i; + + ARGBEGIN { + case 'o': + if (lookup_org) + usage(); + lookup_org = ARG(); + break; + case 't': + if (lookup_title) + usage(); + lookup_title = ARG(); + break; + case 'O': + display_org = 1; + break; + case 'T': + display_title = 1; + break; + default: + usage(); + } ARGEND; + + if (!argc) + usage(); + + if (lookup_org && !lookup_title && !display_org && !display_title) + display_title = 1; + if (lookup_title && !lookup_org && !display_org && !display_title) + display_org = 1; + + for (i = 0; argv[i]; i++) + if (!*argv[i] || strchr(argv[i], '/')) + usage(); + + errno = 0; + user = getpwuid(getuid()); + if (!user) + eprintf("getpwuid: %s\n", errno ? strerror(errno) : "user does not exist"); + + for (; *argv; argv++) { + if (libcontacts_load_contact(*argv, &contact, user)) { + weprintf("libcontacts_load_contact %s: %s\n", *argv, errno ? strerror(errno) : "contact file is malformatted"); + ret = 1; + } else { + for (orgs = contact.organisations; (org = *orgs); orgs++) { + if (lookup_org && (!org->organisation || strcmp(org->organisation, lookup_org))) + continue; + if (lookup_title && (!org->title || strcmp(org->title, lookup_title))) + continue; + if (lookup_org && lookup_title && !display_org && !display_title) { + printf("%s\n", *argv); + continue; + } + if (argc > 1) + printf("%s: ", *argv); + if (display_org && display_title) + printf("%s: %s\n", org->organisation, org->title); + else if (display_title) + printf("%s\n", org->title); + else + printf("%s\n", org->organisation); + } + libcontacts_contact_destroy(&contact); + } + } + + if (fflush(stdout) || ferror(stdout) || fclose(stdout)) + eprintf("printf:"); + return ret; +} diff --git a/get-contact-pgpkeys.c b/get-contact-pgpkeys.c new file mode 100644 index 0000000..9a1250a --- /dev/null +++ b/get-contact-pgpkeys.c @@ -0,0 +1,86 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + +USAGE("[-c context] [-f fingerprint] [-CF] contact-id ..."); + + +int +main(int argc, char *argv[]) +{ + int display_ctx = 0, display_id = 0; + struct passwd *user; + struct libcontacts_contact contact; + struct libcontacts_pgpkey **keys, *key; + const char *lookup_ctx = NULL, *lookup_id = NULL; + int ret = 0; + size_t i; + + ARGBEGIN { + case 'c': + if (lookup_ctx) + usage(); + lookup_ctx = ARG(); + break; + case 'f': + if (lookup_id) + usage(); + lookup_id = ARG(); + break; + case 'C': + display_ctx = 1; + break; + case 'F': + display_id = 1; + break; + default: + usage(); + } ARGEND; + + if (!argc) + usage(); + + if (lookup_ctx && !lookup_id && !display_ctx && !display_id) + display_id = 1; + if (lookup_id && !lookup_ctx && !display_ctx && !display_id) + display_ctx = 1; + + for (i = 0; argv[i]; i++) + if (!*argv[i] || strchr(argv[i], '/')) + usage(); + + errno = 0; + user = getpwuid(getuid()); + if (!user) + eprintf("getpwuid: %s\n", errno ? strerror(errno) : "user does not exist"); + + for (; *argv; argv++) { + if (libcontacts_load_contact(*argv, &contact, user)) { + weprintf("libcontacts_load_contact %s: %s\n", *argv, errno ? strerror(errno) : "contact file is malformatted"); + ret = 1; + } else { + for (keys = contact.pgpkeys; (key = *keys); keys++) { + if (lookup_ctx && (!key->context || strcmp(key->context, lookup_ctx))) + continue; + if (lookup_id && (!key->id || strcmp(key->id, lookup_id))) + continue; + if (lookup_ctx && lookup_id && !display_ctx && !display_id) { + printf("%s\n", *argv); + continue; + } + if (argc > 1) + printf("%s: ", *argv); + if (display_ctx && display_id) + printf("%s: %s\n", key->context, key->id); + else if (display_id) + printf("%s\n", key->id); + else + printf("%s\n", key->context); + } + libcontacts_contact_destroy(&contact); + } + } + + if (fflush(stdout) || ferror(stdout) || fclose(stdout)) + eprintf("printf:"); + return ret; +} diff --git a/get-contact-sites.c b/get-contact-sites.c new file mode 100644 index 0000000..6627cc3 --- /dev/null +++ b/get-contact-sites.c @@ -0,0 +1,86 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + +USAGE("[-c context] [-a address] [-CA] contact-id ..."); + + +int +main(int argc, char *argv[]) +{ + int display_ctx = 0, display_addr = 0; + struct passwd *user; + struct libcontacts_contact contact; + struct libcontacts_site **sites, *site; + const char *lookup_ctx = NULL, *lookup_addr = NULL; + int ret = 0; + size_t i; + + ARGBEGIN { + case 'c': + if (lookup_ctx) + usage(); + lookup_ctx = ARG(); + break; + case 'a': + if (lookup_addr) + usage(); + lookup_addr = ARG(); + break; + case 'C': + display_ctx = 1; + break; + case 'A': + display_addr = 1; + break; + default: + usage(); + } ARGEND; + + if (!argc) + usage(); + + if (lookup_ctx && !lookup_addr && !display_ctx && !display_addr) + display_addr = 1; + if (lookup_addr && !lookup_ctx && !display_ctx && !display_addr) + display_ctx = 1; + + for (i = 0; argv[i]; i++) + if (!*argv[i] || strchr(argv[i], '/')) + usage(); + + errno = 0; + user = getpwuid(getuid()); + if (!user) + eprintf("getpwuid: %s\n", errno ? strerror(errno) : "user does not exist"); + + for (; *argv; argv++) { + if (libcontacts_load_contact(*argv, &contact, user)) { + weprintf("libcontacts_load_contact %s: %s\n", *argv, errno ? strerror(errno) : "contact file is malformatted"); + ret = 1; + } else { + for (sites = contact.sites; (site = *sites); sites++) { + if (lookup_ctx && (!site->context || strcmp(site->context, lookup_ctx))) + continue; + if (lookup_addr && (!site->address || strcmp(site->address, lookup_addr))) + continue; + if (lookup_ctx && lookup_addr && !display_ctx && !display_addr) { + printf("%s\n", *argv); + continue; + } + if (argc > 1) + printf("%s: ", *argv); + if (display_ctx && display_addr) + printf("%s: %s\n", site->context, site->address); + else if (display_addr) + printf("%s\n", site->address); + else + printf("%s\n", site->context); + } + libcontacts_contact_destroy(&contact); + } + } + + if (fflush(stdout) || ferror(stdout) || fclose(stdout)) + eprintf("printf:"); + return ret; +} diff --git a/is-contact-ice.c b/is-contact-ice.c new file mode 100644 index 0000000..057fc2d --- /dev/null +++ b/is-contact-ice.c @@ -0,0 +1,41 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + +USAGE("contact-id ..."); + + +int +main(int argc, char *argv[]) +{ + struct passwd *user; + struct libcontacts_contact contact; + int ret = 0; + size_t i; + + NOFLAGS(!argc); + + for (i = 0; argv[i]; i++) + if (!*argv[i] || strchr(argv[i], '/')) + usage(); + + errno = 0; + user = getpwuid(getuid()); + if (!user) + eprintf("getpwuid: %s\n", errno ? strerror(errno) : "user does not exist"); + + for (; *argv; argv++) { + if (libcontacts_load_contact(*argv, &contact, user)) { + weprintf("libcontacts_load_contact %s: %s\n", *argv, errno ? strerror(errno) : "contact file is malformatted"); + ret = 1; + } else { + if (argc > 1) + printf("%s: ", *argv); + printf("%s\n", contact.in_case_of_emergency ? "yes" : "no"); + libcontacts_contact_destroy(&contact); + } + } + + if (fflush(stdout) || ferror(stdout) || fclose(stdout)) + eprintf("printf:"); + return ret; +} diff --git a/list-contacts.c b/list-contacts.c new file mode 100644 index 0000000..5983f24 --- /dev/null +++ b/list-contacts.c @@ -0,0 +1,84 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + +USAGE("[-efmnou]"); + + +int +main(int argc, char *argv[]) +{ + int names = 0, emergency = 0; + int include_men = 0, include_women = 0, include_orgs = 0, include_unspec = 0; + struct passwd *user; + struct libcontacts_contact **contacts; + char **ids; + size_t i; + + ARGBEGIN { + case 'e': + emergency = 1; + break; + case 'f': + include_women = 1; + break; + case 'm': + include_men = 1; + break; + case 'n': + names = 1; + break; + case 'o': + include_orgs = 1; + break; + case 'u': + include_unspec = 1; + break; + default: + usage(); + } ARGEND; + + if (argc) + usage(); + + errno = 0; + user = getpwuid(getuid()); + if (!user) + eprintf("getpwuid: %s\n", errno ? strerror(errno) : "user does not exist"); + + if (!names && !emergency && !include_men && !include_women && !include_orgs && !include_unspec) { + if (libcontacts_list_contacts(&ids, user)) + eprintf("libcontacts_list_contacts:"); + for (i = 0; ids[i]; i++) { + printf("%s\n", ids[i]); + free(ids[i]); + } + free(ids); + } else { + if (!include_men && !include_women && !include_orgs && !include_unspec) + include_men = include_women = include_orgs = include_unspec = 1; + if (libcontacts_load_contacts(&contacts, user)) + eprintf("libcontacts_load_contacts:"); + for (i = 0; contacts[i]; i++) { + if (emergency && !contacts[i]->in_case_of_emergency) + continue; + if (include_men && contacts[i]->gender == LIBCONTACTS_MALE); + else if (include_women && contacts[i]->gender == LIBCONTACTS_FEMALE); + else if (include_orgs && contacts[i]->gender == LIBCONTACTS_NOT_A_PERSON); + else if (include_unspec && contacts[i]->gender == LIBCONTACTS_UNSPECIFIED_GENDER); + else + continue; + if (names && contacts[i]->name) + printf("%s (%s)\n", contacts[i]->id, contacts[i]->name); + else + printf("%s\n", contacts[i]->id); + libcontacts_contact_destroy(contacts[i]); + free(contacts[i]); + } + free(contacts); + } + + if (fflush(stdout) || ferror(stdout) || fclose(stdout)) + eprintf("printf:"); + + return 0; +} diff --git a/set-contact-emails.c b/set-contact-emails.c new file mode 100644 index 0000000..5911484 --- /dev/null +++ b/set-contact-emails.c @@ -0,0 +1,105 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + +USAGE("[-a | -c] contact-id context address | -u contact-id context [address] | -U contact-id [context] address"); + + +int +main(int argc, char *argv[]) +{ + int update_address = 0, update_context = 0; + int remove_by_context = 0, remove_by_address = 0; + int edit; + struct passwd *user; + struct libcontacts_contact contact; + struct libcontacts_email **r, **w; + size_t i; + + ARGBEGIN { + case 'a': + update_address = 1; + break; + case 'c': + update_context = 1; + break; + case 'u': + remove_by_context = 1; + break; + case 'U': + remove_by_address = 1; + break; + default: + usage(); + } ARGEND; + + edit = update_address + update_context + remove_by_context + remove_by_address; + if (edit > 1 || argc < 3 - remove_by_context - remove_by_address || argc > 3) + usage(); + + if (!*argv[0] || strchr(argv[0], '/')) + usage(); + + errno = 0; + user = getpwuid(getuid()); + if (!user) + eprintf("getpwuid: %s\n", errno ? strerror(errno) : "user does not exist"); + + if (libcontacts_load_contact(argv[0], &contact, user)) + eprintf("libcontacts_load_contact %s: %s\n", argv[0], errno ? strerror(errno) : "contact file is malformatted"); + + i = 0; + if (contact.emails) { + if (!edit) { + for (; contact.emails[i]; i++); + } else if (update_address) { + for (; contact.emails[i]; i++) { + if (contact.emails[i]->context && !strcmp(contact.emails[i]->context, argv[1])) { + free(contact.emails[i]->address); + contact.emails[i]->address = estrdup(argv[2]); + goto save; + } + } + } else if (update_context) { + for (; contact.emails[i]; i++) { + if (contact.emails[i]->address && !strcmp(contact.emails[i]->address, argv[2])) { + free(contact.emails[i]->context); + contact.emails[i]->context = estrdup(argv[1]); + goto save; + } + } + } else if (argc == 3) { + for (; contact.emails[i]; i++) + if (contact.emails[i]->context && !strcmp(contact.emails[i]->context, argv[1])) + if (contact.emails[i]->address && !strcmp(contact.emails[i]->address, argv[2])) + break; + } else if (remove_by_context) { + for (; contact.emails[i]; i++) + if (contact.emails[i]->context && !strcmp(contact.emails[i]->context, argv[1])) + break; + } else { + for (; contact.emails[i]; i++) + if (contact.emails[i]->address && !strcmp(contact.emails[i]->address, argv[1])) + break; + } + } + if (!edit || update_address || update_context) { + contact.emails = erealloc(contact.emails, (i + 2) * sizeof(*contact.emails)); + contact.emails[i + 1] = NULL; + contact.emails[i] = ecalloc(1, sizeof(**contact.emails)); + contact.emails[i]->context = estrdup(argv[1]); + contact.emails[i]->address = estrdup(argv[2]); + } else if (contact.emails && contact.emails[i]) { + libcontacts_email_destroy(contact.emails[i]); + free(contact.emails[i]); + for (r = &1[w = &contact.emails[i]]; *r;) + *w++ = *r++; + *w = NULL; + } + +save: + if (libcontacts_save_contact(&contact, user)) + eprintf("libcontacts_save_contact %s:", argv[0]); + libcontacts_contact_destroy(&contact); + + return 0; +} diff --git a/set-contact-gender.c b/set-contact-gender.c new file mode 100644 index 0000000..f9750d6 --- /dev/null +++ b/set-contact-gender.c @@ -0,0 +1,71 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + +USAGE("(-f | -m | -o | -u) contact-id ..."); + + +int +main(int argc, char *argv[]) +{ + enum libcontacts_gender gender = LIBCONTACTS_UNSPECIFIED_GENDER; + int gender_specified = 0, ret = 0; + struct passwd *user; + struct libcontacts_contact contact; + size_t i; + + ARGBEGIN { + case 'f': + if (gender_specified) + usage(); + gender_specified = 1; + gender = LIBCONTACTS_FEMALE; + break; + case 'm': + if (gender_specified) + usage(); + gender_specified = 1; + gender = LIBCONTACTS_MALE; + break; + case 'o': + if (gender_specified) + usage(); + gender_specified = 1; + gender = LIBCONTACTS_NOT_A_PERSON; + break; + case 'u': + if (gender_specified) + usage(); + gender_specified = 1; + break; + default: + usage(); + } ARGEND; + + if (!gender_specified || !argc) + usage(); + + for (i = 0; argv[i]; i++) + if (!*argv[i] || strchr(argv[i], '/')) + usage(); + + errno = 0; + user = getpwuid(getuid()); + if (!user) + eprintf("getpwuid: %s\n", errno ? strerror(errno) : "user does not exist"); + + for (; *argv; argv++) { + if (libcontacts_load_contact(*argv, &contact, user)) { + weprintf("libcontacts_load_contact %s: %s\n", *argv, errno ? strerror(errno) : "contact file is malformatted"); + ret = 1; + } else { + contact.gender = gender; + if (libcontacts_save_contact(&contact, user)) { + weprintf("libcontacts_save_contact %s:", *argv); + ret = 1; + } + libcontacts_contact_destroy(&contact); + } + } + + return ret; +} diff --git a/set-contact-ice.c b/set-contact-ice.c new file mode 100644 index 0000000..2dcb612 --- /dev/null +++ b/set-contact-ice.c @@ -0,0 +1,50 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + +USAGE("[-u] contact-id ..."); + + +int +main(int argc, char *argv[]) +{ + int set_ice = 1, ret = 0; + struct passwd *user; + struct libcontacts_contact contact; + size_t i; + + ARGBEGIN { + case 'u': + set_ice = 0; + break; + default: + usage(); + } ARGEND; + + if (!argc) + usage(); + + for (i = 0; argv[i]; i++) + if (!*argv[i] || strchr(argv[i], '/')) + usage(); + + errno = 0; + user = getpwuid(getuid()); + if (!user) + eprintf("getpwuid: %s\n", errno ? strerror(errno) : "user does not exist"); + + for (; *argv; argv++) { + if (libcontacts_load_contact(*argv, &contact, user)) { + weprintf("libcontacts_load_contact %s: %s\n", *argv, errno ? strerror(errno) : "contact file is malformatted"); + ret = 1; + } else { + contact.in_case_of_emergency = set_ice; + if (libcontacts_save_contact(&contact, user)) { + weprintf("libcontacts_save_contact %s:", *argv); + ret = 1; + } + libcontacts_contact_destroy(&contact); + } + } + + return ret; +} diff --git a/set-contact-name.c b/set-contact-name.c new file mode 100644 index 0000000..dad34d1 --- /dev/null +++ b/set-contact-name.c @@ -0,0 +1,72 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + +USAGE("[-F | -f | -l | n] (-u contact-id | contact-id name)"); + + +int +main(int argc, char *argv[]) +{ + int unset = 0; + struct passwd *user; + struct libcontacts_contact contact; + size_t offset = 0; + char **namep; + + ARGBEGIN { + case 'F': + if (offset) + usage(); + offset = offsetof(struct libcontacts_contact, full_name); + break; + case 'f': + if (offset) + usage(); + offset = offsetof(struct libcontacts_contact, first_name); + break; + case 'l': + if (offset) + usage(); + offset = offsetof(struct libcontacts_contact, last_name); + break; + case 'n': + if (offset) + usage(); + offset = offsetof(struct libcontacts_contact, nickname); + break; + case 'u': + unset = 1; + break; + default: + usage(); + } ARGEND; + + if (argc != 2 - unset) + usage(); + + if (!*argv[0] || strchr(argv[0], '/')) + usage(); + + if (!offset) + offset = offsetof(struct libcontacts_contact, name); + + errno = 0; + user = getpwuid(getuid()); + if (!user) + eprintf("getpwuid: %s\n", errno ? strerror(errno) : "user does not exist"); + + if (libcontacts_load_contact(*argv, &contact, user)) + eprintf("libcontacts_load_contact %s: %s\n", *argv, errno ? strerror(errno) : "contact file is malformatted"); + + namep = (char **)&offset[(char *)&contact]; + if (!unset || *namep) { + free(*namep); + *namep = unset ? NULL : estrdup(argv[1]); + + if (libcontacts_save_contact(&contact, user)) + eprintf("libcontacts_save_contact %s:", *argv); + } + + libcontacts_contact_destroy(&contact); + return 0; +} diff --git a/set-contact-notes.c b/set-contact-notes.c new file mode 100644 index 0000000..6eeeeb4 --- /dev/null +++ b/set-contact-notes.c @@ -0,0 +1,62 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + +USAGE("[-u] contact-id"); + + +int +main(int argc, char *argv[]) +{ + int unset = 0; + struct passwd *user; + struct libcontacts_contact contact; + size_t size = 0, len = 0; + ssize_t r; + + ARGBEGIN { + case 'u': + unset = 1; + break; + default: + usage(); + } ARGEND; + + if (argc != 1) + usage(); + + if (!*argv[0] || strchr(argv[0], '/')) + usage(); + + errno = 0; + user = getpwuid(getuid()); + if (!user) + eprintf("getpwuid: %s\n", errno ? strerror(errno) : "user does not exist"); + + if (libcontacts_load_contact(argv[0], &contact, user)) + eprintf("libcontacts_load_contact %s: %s\n", argv[0], errno ? strerror(errno) : "contact file is malformatted"); + + free(contact.notes); + contact.notes = NULL; + if (!unset) { + for (;;) { + if (len == size) + contact.notes = erealloc(contact.notes, size += 512); + r = read(STDIN_FILENO, &contact.notes[len], size - len); + if (r <= 0) { + if (!r) + break; + eprintf("read :"); + } + len += (size_t)r; + } + if (size) + contact.notes[len] = '\0'; + } + + if (libcontacts_save_contact(&contact, user)) + eprintf("libcontacts_save_contact %s:", argv[0]); + + libcontacts_contact_destroy(&contact); + + return 0; +} diff --git a/set-contact-organisations.c b/set-contact-organisations.c new file mode 100644 index 0000000..17db004 --- /dev/null +++ b/set-contact-organisations.c @@ -0,0 +1,106 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + +USAGE("[-o | -t] contact-id organisation title | -u contact-id organisation [title] | -U contact-id [organisation] title"); + + +int +main(int argc, char *argv[]) +{ + int update_title = 0, update_organisation = 0; + int remove_by_organisation = 0, remove_by_title = 0; + int edit; + struct passwd *user; + struct libcontacts_contact contact; + struct libcontacts_organisation **r, **w; + size_t i; + + ARGBEGIN { + case 'o': + update_title = 1; + break; + case 't': + update_organisation = 1; + break; + case 'u': + remove_by_organisation = 1; + break; + case 'U': + remove_by_title = 1; + break; + default: + usage(); + } ARGEND; + + edit = update_title + update_organisation + remove_by_organisation + remove_by_title; + if (edit > 1 || argc < 3 - remove_by_organisation - remove_by_title || argc > 3) + usage(); + + if (!*argv[0] || strchr(argv[0], '/')) + usage(); + + errno = 0; + user = getpwuid(getuid()); + if (!user) + eprintf("getpwuid: %s\n", errno ? strerror(errno) : "user does not exist"); + + if (libcontacts_load_contact(argv[0], &contact, user)) + eprintf("libcontacts_load_contact %s: %s\n", argv[0], errno ? strerror(errno) : "contact file is malformatted"); + + i = 0; + if (contact.organisations) { + if (!edit) { + for (; contact.organisations[i]; i++); + } else if (update_title) { + for (; contact.organisations[i]; i++) { + if (contact.organisations[i]->organisation && + !strcmp(contact.organisations[i]->organisation, argv[1])) { + free(contact.organisations[i]->title); + contact.organisations[i]->title = estrdup(argv[2]); + goto save; + } + } + } else if (update_organisation) { + for (; contact.organisations[i]; i++) { + if (contact.organisations[i]->title && !strcmp(contact.organisations[i]->title, argv[2])) { + free(contact.organisations[i]->organisation); + contact.organisations[i]->organisation = estrdup(argv[1]); + goto save; + } + } + } else if (argc == 3) { + for (; contact.organisations[i]; i++) + if (contact.organisations[i]->organisation && !strcmp(contact.organisations[i]->organisation, argv[1])) + if (contact.organisations[i]->title && !strcmp(contact.organisations[i]->title, argv[2])) + break; + } else if (remove_by_organisation) { + for (; contact.organisations[i]; i++) + if (contact.organisations[i]->organisation && !strcmp(contact.organisations[i]->organisation, argv[1])) + break; + } else { + for (; contact.organisations[i]; i++) + if (contact.organisations[i]->title && !strcmp(contact.organisations[i]->title, argv[1])) + break; + } + } + if (!edit || update_title || update_organisation) { + contact.organisations = erealloc(contact.organisations, (i + 2) * sizeof(*contact.organisations)); + contact.organisations[i + 1] = NULL; + contact.organisations[i] = ecalloc(1, sizeof(**contact.organisations)); + contact.organisations[i]->organisation = estrdup(argv[1]); + contact.organisations[i]->title = estrdup(argv[2]); + } else if (contact.organisations && contact.organisations[i]) { + libcontacts_organisation_destroy(contact.organisations[i]); + free(contact.organisations[i]); + for (r = &1[w = &contact.organisations[i]]; *r;) + *w++ = *r++; + *w = NULL; + } + +save: + if (libcontacts_save_contact(&contact, user)) + eprintf("libcontacts_save_contact %s:", argv[0]); + libcontacts_contact_destroy(&contact); + + return 0; +} diff --git a/set-contact-pgpkeys.c b/set-contact-pgpkeys.c new file mode 100644 index 0000000..b5bebfb --- /dev/null +++ b/set-contact-pgpkeys.c @@ -0,0 +1,105 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + +USAGE("[-c | -f] contact-id context fingerprint | -u contact-id context [fingerprint] | -U contact-id [context] fingerprint"); + + +int +main(int argc, char *argv[]) +{ + int update_id = 0, update_context = 0; + int remove_by_context = 0, remove_by_id = 0; + int edit; + struct passwd *user; + struct libcontacts_contact contact; + struct libcontacts_pgpkey **r, **w; + size_t i; + + ARGBEGIN { + case 'c': + update_context = 1; + break; + case 'f': + update_id = 1; + break; + case 'u': + remove_by_context = 1; + break; + case 'U': + remove_by_id = 1; + break; + default: + usage(); + } ARGEND; + + edit = update_id + update_context + remove_by_context + remove_by_id; + if (edit > 1 || argc < 3 - remove_by_context - remove_by_id || argc > 3) + usage(); + + if (!*argv[0] || strchr(argv[0], '/')) + usage(); + + errno = 0; + user = getpwuid(getuid()); + if (!user) + eprintf("getpwuid: %s\n", errno ? strerror(errno) : "user does not exist"); + + if (libcontacts_load_contact(argv[0], &contact, user)) + eprintf("libcontacts_load_contact %s: %s\n", argv[0], errno ? strerror(errno) : "contact file is malformatted"); + + i = 0; + if (contact.pgpkeys) { + if (!edit) { + for (; contact.pgpkeys[i]; i++); + } else if (update_id) { + for (; contact.pgpkeys[i]; i++) { + if (contact.pgpkeys[i]->context && !strcmp(contact.pgpkeys[i]->context, argv[1])) { + free(contact.pgpkeys[i]->id); + contact.pgpkeys[i]->id = estrdup(argv[2]); + goto save; + } + } + } else if (update_context) { + for (; contact.pgpkeys[i]; i++) { + if (contact.pgpkeys[i]->id && !strcmp(contact.pgpkeys[i]->id, argv[2])) { + free(contact.pgpkeys[i]->context); + contact.pgpkeys[i]->context = estrdup(argv[1]); + goto save; + } + } + } else if (argc == 3) { + for (; contact.pgpkeys[i]; i++) + if (contact.pgpkeys[i]->context && !strcmp(contact.pgpkeys[i]->context, argv[1])) + if (contact.pgpkeys[i]->id && !strcmp(contact.pgpkeys[i]->id, argv[2])) + break; + } else if (remove_by_context) { + for (; contact.pgpkeys[i]; i++) + if (contact.pgpkeys[i]->context && !strcmp(contact.pgpkeys[i]->context, argv[1])) + break; + } else { + for (; contact.pgpkeys[i]; i++) + if (contact.pgpkeys[i]->id && !strcmp(contact.pgpkeys[i]->id, argv[1])) + break; + } + } + if (!edit || update_id || update_context) { + contact.pgpkeys = erealloc(contact.pgpkeys, (i + 2) * sizeof(*contact.pgpkeys)); + contact.pgpkeys[i + 1] = NULL; + contact.pgpkeys[i] = ecalloc(1, sizeof(**contact.pgpkeys)); + contact.pgpkeys[i]->context = estrdup(argv[1]); + contact.pgpkeys[i]->id = estrdup(argv[2]); + } else if (contact.pgpkeys && contact.pgpkeys[i]) { + libcontacts_pgpkey_destroy(contact.pgpkeys[i]); + free(contact.pgpkeys[i]); + for (r = &1[w = &contact.pgpkeys[i]]; *r;) + *w++ = *r++; + *w = NULL; + } + +save: + if (libcontacts_save_contact(&contact, user)) + eprintf("libcontacts_save_contact %s:", argv[0]); + libcontacts_contact_destroy(&contact); + + return 0; +} diff --git a/set-contact-sites.c b/set-contact-sites.c new file mode 100644 index 0000000..e826f73 --- /dev/null +++ b/set-contact-sites.c @@ -0,0 +1,105 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + +USAGE("[-a | -c] contact-id context address | -u contact-id context [address] | -U contact-id [context] address"); + + +int +main(int argc, char *argv[]) +{ + int update_address = 0, update_context = 0; + int remove_by_context = 0, remove_by_address = 0; + int edit; + struct passwd *user; + struct libcontacts_contact contact; + struct libcontacts_site **r, **w; + size_t i; + + ARGBEGIN { + case 'a': + update_address = 1; + break; + case 'c': + update_context = 1; + break; + case 'u': + remove_by_context = 1; + break; + case 'U': + remove_by_address = 1; + break; + default: + usage(); + } ARGEND; + + edit = update_address + update_context + remove_by_context + remove_by_address; + if (edit > 1 || argc < 3 - remove_by_context - remove_by_address || argc > 3) + usage(); + + if (!*argv[0] || strchr(argv[0], '/')) + usage(); + + errno = 0; + user = getpwuid(getuid()); + if (!user) + eprintf("getpwuid: %s\n", errno ? strerror(errno) : "user does not exist"); + + if (libcontacts_load_contact(argv[0], &contact, user)) + eprintf("libcontacts_load_contact %s: %s\n", argv[0], errno ? strerror(errno) : "contact file is malformatted"); + + i = 0; + if (contact.sites) { + if (!edit) { + for (; contact.sites[i]; i++); + } else if (update_address) { + for (; contact.sites[i]; i++) { + if (contact.sites[i]->context && !strcmp(contact.sites[i]->context, argv[1])) { + free(contact.sites[i]->address); + contact.sites[i]->address = estrdup(argv[2]); + goto save; + } + } + } else if (update_context) { + for (; contact.sites[i]; i++) { + if (contact.sites[i]->address && !strcmp(contact.sites[i]->address, argv[2])) { + free(contact.sites[i]->context); + contact.sites[i]->context = estrdup(argv[1]); + goto save; + } + } + } else if (argc == 3) { + for (; contact.sites[i]; i++) + if (contact.sites[i]->context && !strcmp(contact.sites[i]->context, argv[1])) + if (contact.sites[i]->address && !strcmp(contact.sites[i]->address, argv[2])) + break; + } else if (remove_by_context) { + for (; contact.sites[i]; i++) + if (contact.sites[i]->context && !strcmp(contact.sites[i]->context, argv[1])) + break; + } else { + for (; contact.sites[i]; i++) + if (contact.sites[i]->address && !strcmp(contact.sites[i]->address, argv[1])) + break; + } + } + if (!edit || update_address || update_context) { + contact.sites = erealloc(contact.sites, (i + 2) * sizeof(*contact.sites)); + contact.sites[i + 1] = NULL; + contact.sites[i] = ecalloc(1, sizeof(**contact.sites)); + contact.sites[i]->context = estrdup(argv[1]); + contact.sites[i]->address = estrdup(argv[2]); + } else if (contact.sites && contact.sites[i]) { + libcontacts_site_destroy(contact.sites[i]); + free(contact.sites[i]); + for (r = &1[w = &contact.sites[i]]; *r;) + *w++ = *r++; + *w = NULL; + } + +save: + if (libcontacts_save_contact(&contact, user)) + eprintf("libcontacts_save_contact %s:", argv[0]); + libcontacts_contact_destroy(&contact); + + return 0; +} -- cgit v1.2.3-70-g09d2