aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMattias Andrée <maandree@kth.se>2021-04-12 00:07:26 +0200
committerMattias Andrée <maandree@kth.se>2021-04-12 00:07:26 +0200
commit1a21982ebc2747a694558c6e82cea54bd5dbead9 (patch)
tree42a145211772e876d85dfcc65655fa3130016313
parentImprove set-contact- utils (diff)
downloadcontacts-1a21982ebc2747a694558c6e82cea54bd5dbead9.tar.gz
contacts-1a21982ebc2747a694558c6e82cea54bd5dbead9.tar.bz2
contacts-1a21982ebc2747a694558c6e82cea54bd5dbead9.tar.xz
Deduplicate code and make some minor improvements
Signed-off-by: Mattias Andrée <maandree@kth.se>
-rw-r--r--TODO7
-rw-r--r--common.h160
-rw-r--r--set-contact-birthday.c3
-rw-r--r--set-contact-blocks.c28
-rw-r--r--set-contact-chats.c137
-rw-r--r--set-contact-emails.c118
-rw-r--r--set-contact-gender.c3
-rw-r--r--set-contact-groups.c11
-rw-r--r--set-contact-numbers.c146
-rw-r--r--set-contact-organisations.c118
-rw-r--r--set-contact-pgpkeys.c118
-rw-r--r--set-contact-photos.c32
-rw-r--r--set-contact-sites.c118
13 files changed, 241 insertions, 758 deletions
diff --git a/TODO b/TODO
index 9028b62..eeeb141 100644
--- a/TODO
+++ b/TODO
@@ -11,14 +11,7 @@ Test list-chat-contacts
Test list-contact-organisations
Test list-organisation-contacts
Test set-contact-blocks
-Test set-contact-chats
-Test set-contact-emails
-Test set-contact-groups
-Test set-contact-numbers
-Test set-contact-organisations
-Test set-contact-pgpkeys
Test set-contact-photos
-Test set-contact-sites
Test unblock-contact
Add ability to filter on unset values in entries
Add ability to remove values in entries
diff --git a/common.h b/common.h
index 6aecf6c..d1345f5 100644
--- a/common.h
+++ b/common.h
@@ -25,3 +25,163 @@ void print_birthday(struct libcontacts_birthday *bday, const struct tm *now);
/* common-address.c */
int parse_coord(const char *s, double *lat, double *lat_min, double *lat_max, double *lon, double *lon_min, double *lon_max);
+
+
+
+#ifndef LIST_BOOL_PARAMS
+# define LIST_BOOL_PARAMS(X)
+#endif
+
+#define X_USAGE_UPPER(UPPERC, UPPERS, LOWERC, LOWERS, VAR, DISPLAY)\
+ "[-"UPPERS" old-"DISPLAY"] "
+
+#define X_USAGE_LOWER(UPPERC, UPPERS, LOWERC, LOWERS, VAR, DISPLAY)\
+ "[-"LOWERS" new-"DISPLAY"] "
+
+#define X_USAGE_BOOL(UPPERC, UPPERS, LOWERC, LOWERS, VAR, DISPLAY)\
+ "[-"UPPERS" | -"LOWERS"] "
+
+#define X_PARAMS(UPPERC, UPPERS, LOWERC, LOWERS, VAR, DISPLAY)\
+ char *VAR = NULL, *lookup_##VAR = NULL, *old_##VAR = NULL;
+
+#define X_BOOL_PARAMS(UPPERC, UPPERS, LOWERC, LOWERS, VAR, DISPLAY)\
+ int set_##VAR = -1;
+
+#define X_ARGPARSE(UPPERC, UPPERS, LOWERC, LOWERS, VAR, DISPLAY)\
+ case UPPERC:\
+ add = 0;\
+ if (lookup_##VAR)\
+ usage();\
+ lookup_##VAR = ARG();\
+ break;\
+ case LOWERC:\
+ edit = 1;\
+ if (VAR)\
+ usage();\
+ VAR = ARG();\
+ break;
+
+#define X_BOOL_ARGPARSE(UPPERC, UPPERS, LOWERC, LOWERS, VAR, DISPLAY)\
+ case UPPERC:\
+ if (set_##VAR >= 0)\
+ usage();\
+ set_##VAR = 0;\
+ break;\
+ case LOWERC:\
+ if (set_##VAR >= 0)\
+ usage();\
+ set_##VAR = 1;\
+ break;
+
+#define X_LOWER(UPPERC, UPPERS, LOWERC, LOWERS, VAR, DISPLAY)\
+ LOWERS
+
+#define X_LOOKUP(UPPERC, UPPERS, LOWERC, LOWERS, VAR, DISPLAY)\
+ if (lookup_##VAR && strcmpnul(contact.CATEGORY[i]->VAR, lookup_##VAR))\
+ continue;
+
+#define X_BOOL_LOOKUP(UPPERC, UPPERS, LOWERC, LOWERS, VAR, DISPLAY)\
+ if (remove && set_##VAR >= 0 && contact.CATEGORY[i]->is_##VAR != set_##VAR)\
+ continue;
+
+#define X_CHANGE(UPPERC, UPPERS, LOWERC, LOWERS, VAR, DISPLAY)\
+ if (VAR) {\
+ old_##VAR = contact.CATEGORY[i]->VAR;\
+ contact.CATEGORY[i]->VAR = VAR;\
+ }
+
+#define X_BOOL_SET(UPPERC, UPPERS, LOWERC, LOWERS, VAR, DISPLAY)\
+ if (set_##VAR >= 0)\
+ contact.CATEGORY[i]->is_##VAR = set_##VAR;
+
+#define X_ADD(UPPERC, UPPERS, LOWERC, LOWERS, VAR, DISPLAY)\
+ contact.CATEGORY[i]->VAR = VAR;
+
+#define X_RESTORE(UPPERC, UPPERS, LOWERC, LOWERS, VAR, DISPLAY)\
+ contact.CATEGORY[i]->VAR = old_##VAR;
+
+#define IMPLEMENT_SET_ON_LIST(CAT)\
+ USAGE(LIST_PARAMS(X_USAGE_UPPER)LIST_BOOL_PARAMS(X_USAGE_BOOL)"("LIST_PARAMS(X_USAGE_LOWER)"| -u) contact-id");\
+ \
+ int\
+ main(int argc, char *argv[])\
+ {\
+ int add = 1, edit = 0, remove = 0;\
+ LIST_PARAMS(X_PARAMS)\
+ LIST_BOOL_PARAMS(X_BOOL_PARAMS)\
+ struct passwd *user;\
+ struct libcontacts_contact contact;\
+ struct libcontacts_##CAT **r = NULL, **w;\
+ size_t i;\
+ \
+ ARGBEGIN {\
+ LIST_PARAMS(X_ARGPARSE)\
+ LIST_BOOL_PARAMS(X_BOOL_ARGPARSE)\
+ case 'u':\
+ remove = 1;\
+ break;\
+ default:\
+ usage();\
+ } ARGEND;\
+ \
+ if (argc != 1 || !*argv[0] || strchr(argv[0], '/'))\
+ usage();\
+ \
+ if (remove == edit) {\
+ if (edit)\
+ usage();\
+ eprintf("at least one of -"LIST_PARAMS(X_LOWER)"u is required\n");\
+ }\
+ \
+ if (add)\
+ edit = 0;\
+ \
+ 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 ((edit || remove) && contact.CATEGORY) {\
+ for (; contact.CATEGORY[i]; i++) {\
+ LIST_PARAMS(X_LOOKUP)\
+ LIST_BOOL_PARAMS(X_BOOL_LOOKUP)\
+ break;\
+ }\
+ if (!contact.CATEGORY[i]) {\
+ libcontacts_contact_destroy(&contact);\
+ return 0;\
+ } else if (!edit) {\
+ r = &contact.CATEGORY[i];\
+ libcontacts_##CAT##_destroy(*r);\
+ free(*r);\
+ for (w = r++; (*w++ = *r++););\
+ } else {\
+ LIST_PARAMS(X_CHANGE)\
+ LIST_BOOL_PARAMS(X_BOOL_SET)\
+ }\
+ } else if (!edit && !remove) {\
+ if (contact.CATEGORY)\
+ for (; contact.CATEGORY[i]; i++);\
+ contact.CATEGORY = erealloc(contact.CATEGORY, (i + 2) * sizeof(*contact.CATEGORY));\
+ contact.CATEGORY[i + 1] = NULL;\
+ contact.CATEGORY[i] = ecalloc(1, sizeof(**contact.CATEGORY));\
+ LIST_PARAMS(X_ADD)\
+ LIST_BOOL_PARAMS(X_BOOL_SET)\
+ }\
+ \
+ if (libcontacts_save_contact(&contact, user))\
+ eprintf("libcontacts_save_contact %s:", argv[0]);\
+ \
+ if (!r) {\
+ LIST_PARAMS(X_RESTORE)\
+ }\
+ \
+ libcontacts_contact_destroy(&contact);\
+ return 0;\
+ }
diff --git a/set-contact-birthday.c b/set-contact-birthday.c
index 74dadc7..c65e65d 100644
--- a/set-contact-birthday.c
+++ b/set-contact-birthday.c
@@ -106,7 +106,8 @@ main(int argc, char *argv[])
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");
+ weprintf("libcontacts_load_contact %s: %s\n", *argv,
+ errno ? strerror(errno) : "contact file is malformatted");
ret = 1;
} else {
if (remove) {
diff --git a/set-contact-blocks.c b/set-contact-blocks.c
index dc01919..9e1ada5 100644
--- a/set-contact-blocks.c
+++ b/set-contact-blocks.c
@@ -13,9 +13,9 @@ main(int argc, char *argv[])
enum libcontacts_block_type lookup_shadow_block = LIBCONTACTS_BLOCK_IGNORE;
time_t soft_unblock = 0, hard_unblock = 0;
time_t lookup_soft_unblock = 0, lookup_hard_unblock = 0;
- char *srv = NULL, *type = NULL, *style = NULL, *ask = NULL, *ublk = NULL;
- char *lookup_srv = NULL, *lookup_type = NULL, *lookup_style = NULL;
- char *lookup_ask = NULL, *lookup_ublk = NULL, *old_srv = NULL, global[] = ".global";
+ const char *srv = NULL, *type = NULL, *style = NULL, *ask = NULL, *ublk = NULL;
+ const char *lookup_srv = NULL, *lookup_type = NULL, *lookup_style = NULL;
+ const char *lookup_ask = NULL, *lookup_ublk = NULL;
struct passwd *user;
struct libcontacts_contact contact;
char *p;
@@ -106,9 +106,6 @@ main(int argc, char *argv[])
usage();
} ARGEND;
- if (add)
- edit = 0;
-
if (argc != 1 || !*argv[0] || strchr(argv[0], '/'))
usage();
@@ -156,17 +153,22 @@ main(int argc, char *argv[])
eprintf("value of -y shall be either \"silent\", \"as-off\", \"as-busy\", or \"ignore\"\n");
}
+ if (add)
+ edit = 0;
+
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 (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 (edit && contact.blocks) {
- for (i = 0; contact.blocks[i]; i++) {
+ for (; contact.blocks[i]; i++) {
if (lookup_srv && strcmpnul(contact.blocks[i]->service, lookup_srv))
continue;
if (lookup_type && contact.blocks[i]->explicit != lookup_explicit)
@@ -178,8 +180,8 @@ main(int argc, char *argv[])
if (lookup_ublk && contact.blocks[i]->hard_unblock != lookup_hard_unblock)
continue;
if (srv) {
- old_srv = contact.blocks[i]->service;
- contact.blocks[i]->service = srv;
+ free(contact.blocks[i]->service);
+ contact.blocks[i]->service = estrdup(srv);
}
if (type)
contact.blocks[i]->explicit = explicit;
@@ -196,7 +198,7 @@ main(int argc, char *argv[])
contact.blocks = erealloc(contact.blocks, (i + 2) * sizeof(*contact.blocks));
contact.blocks[i + 1] = NULL;
contact.blocks[i] = ecalloc(1, sizeof(**contact.emails));
- contact.blocks[i]->service = srv ? srv : global;
+ contact.blocks[i]->service = estrdup(srv ? srv : ".global");
contact.blocks[i]->explicit = explicit;
contact.blocks[i]->shadow_block = shadow_block;
contact.blocks[i]->soft_unblock = soft_unblock;
@@ -206,8 +208,6 @@ main(int argc, char *argv[])
if (libcontacts_save_contact(&contact, user))
eprintf("libcontacts_save_contact %s:", argv[0]);
- contact.blocks[i]->service = old_srv;
libcontacts_contact_destroy(&contact);
-
return 0;
}
diff --git a/set-contact-chats.c b/set-contact-chats.c
index d2811d0..a4e0f8d 100644
--- a/set-contact-chats.c
+++ b/set-contact-chats.c
@@ -1,133 +1,10 @@
/* See LICENSE file for copyright and license details. */
-#include "common.h"
-
-USAGE("[-A old-address] [-C old-context] [-S old-service] ([-a new-adress] [-c new-context] [-s new-service] | -u) contact-id");
-
-
-int
-main(int argc, char *argv[])
-{
- int add = 1, edit = 0, remove = 0;
- char *address = NULL, *context = NULL, *service = NULL;
- char *lookup_address = NULL, *lookup_context = NULL, *lookup_service = NULL;
- char *old_address = NULL, *old_context = NULL, *old_service = NULL;
- struct passwd *user;
- struct libcontacts_contact contact;
- struct libcontacts_chat **r, **w;
- size_t i;
-
- ARGBEGIN {
- case 'A':
- add = 0;
- if (lookup_address)
- usage();
- lookup_address = ARG();
- break;
- case 'a':
- edit = 1;
- if (address)
- usage();
- address = ARG();
- break;
- case 'C':
- add = 0;
- if (lookup_context)
- usage();
- lookup_context = ARG();
- break;
- case 'c':
- edit = 1;
- if (context)
- usage();
- context = ARG();
- break;
- case 'S':
- add = 0;
- if (lookup_service)
- usage();
- lookup_service = ARG();
- break;
- case 's':
- edit = 1;
- if (service)
- usage();
- service = ARG();
- break;
- case 'u':
- remove = 1;
- break;
- default:
- usage();
- } ARGEND;
-
- if (remove == edit) {
- if (edit)
- usage();
- eprintf("at least one of -acsu is required\n");
- }
-
- if (add)
- edit = 0;
+#define CATEGORY chats
- if (argc != 1 || !*argv[0] || strchr(argv[0], '/'))
- usage();
+#define LIST_PARAMS(X)\
+ X('A', "A", 'a', "a", address, "address")\
+ X('S', "S", 's', "s", service, "service")\
+ X('C', "C", 'c', "c", context, "context")
- 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 ((edit || remove) && contact.chats) {
- for (r = contact.chats; *r; r++) {
- if (lookup_context && strcmpnul((*r)->context, lookup_context))
- continue;
- if (lookup_address && strcmpnul((*r)->context, lookup_address))
- continue;
- break;
- }
- if (!edit) {
- libcontacts_chat_destroy(*r);
- free(*r);
- for (w = r++; (*w++ = *r++););
- } else if (*r) {
- if (context) {
- old_context = contact.chats[i]->context;
- contact.chats[i]->context = context;
- }
- if (service) {
- old_service = contact.chats[i]->service;
- contact.chats[i]->service = service;
- }
- if (address) {
- old_address = contact.chats[i]->address;
- contact.chats[i]->address = address;
- }
- } else {
- libcontacts_contact_destroy(&contact);
- return 0;
- }
- } else if (!edit && !remove) {
- if (contact.chats)
- for (i = 0; contact.chats[i]; i++);
- contact.chats = erealloc(contact.chats, (i + 2) * sizeof(*contact.chats));
- contact.chats[i + 1] = NULL;
- contact.chats[i] = ecalloc(1, sizeof(**contact.chats));
- contact.chats[i]->context = context;
- contact.chats[i]->service = service;
- contact.chats[i]->address = address;
- }
-
- if (libcontacts_save_contact(&contact, user))
- eprintf("libcontacts_save_contact %s:", argv[0]);
-
- contact.chats[i]->context = old_context;
- contact.chats[i]->service = old_service;
- contact.chats[i]->address = old_address;
- libcontacts_contact_destroy(&contact);
-
- return 0;
-}
+#include "common.h"
+IMPLEMENT_SET_ON_LIST(chat)
diff --git a/set-contact-emails.c b/set-contact-emails.c
index d1cece5..31efe8c 100644
--- a/set-contact-emails.c
+++ b/set-contact-emails.c
@@ -1,115 +1,9 @@
/* See LICENSE file for copyright and license details. */
-#include "common.h"
-
-USAGE("[-A old-address] [-C old-context] ([-a new-adress] [-c new-context] | -u) contact-id");
-
-
-int
-main(int argc, char *argv[])
-{
- int add = 1, edit = 0, remove = 0;
- char *address = NULL, *context = NULL;
- char *lookup_address = NULL, *lookup_context = NULL;
- char *old_address = NULL, *old_context = NULL;
- struct passwd *user;
- struct libcontacts_contact contact;
- struct libcontacts_email **r, **w;
- size_t i;
-
- ARGBEGIN {
- case 'A':
- add = 0;
- if (lookup_address)
- usage();
- lookup_address = ARG();
- break;
- case 'a':
- edit = 1;
- if (address)
- usage();
- address = ARG();
- break;
- case 'C':
- add = 0;
- if (lookup_context)
- usage();
- lookup_context = ARG();
- break;
- case 'c':
- edit = 1;
- if (context)
- usage();
- context = ARG();
- break;
- case 'u':
- remove = 1;
- break;
- default:
- usage();
- } ARGEND;
-
- if (remove == edit) {
- if (edit)
- usage();
- eprintf("at least one of -acu is required\n");
- }
-
- if (add)
- edit = 0;
+#define CATEGORY emails
- if (argc != 1 || !*argv[0] || strchr(argv[0], '/'))
- usage();
+#define LIST_PARAMS(X)\
+ X('A', "A", 'a', "a", address, "address")\
+ X('C', "C", 'c', "c", context, "context")
- 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 ((edit || remove) && contact.emails) {
- for (r = contact.emails; *r; r++) {
- if (lookup_context && strcmpnul((*r)->context, lookup_context))
- continue;
- if (lookup_address && strcmpnul((*r)->context, lookup_address))
- continue;
- break;
- }
- if (!edit) {
- libcontacts_email_destroy(*r);
- free(*r);
- for (w = r++; (*w++ = *r++););
- } else if (*r) {
- if (context) {
- old_context = contact.emails[i]->context;
- contact.emails[i]->context = context;
- }
- if (address) {
- old_address = contact.emails[i]->address;
- contact.emails[i]->address = address;
- }
- } else {
- libcontacts_contact_destroy(&contact);
- return 0;
- }
- } else if (!edit && !remove) {
- if (contact.emails)
- for (i = 0; contact.emails[i]; i++);
- 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 = context;
- contact.emails[i]->address = address;
- }
-
- if (libcontacts_save_contact(&contact, user))
- eprintf("libcontacts_save_contact %s:", argv[0]);
-
- contact.emails[i]->context = old_context;
- contact.emails[i]->address = old_address;
- libcontacts_contact_destroy(&contact);
-
- return 0;
-}
+#include "common.h"
+IMPLEMENT_SET_ON_LIST(email)
diff --git a/set-contact-gender.c b/set-contact-gender.c
index b0b0258..70b9150 100644
--- a/set-contact-gender.c
+++ b/set-contact-gender.c
@@ -55,7 +55,8 @@ main(int argc, char *argv[])
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");
+ weprintf("libcontacts_load_contact %s: %s\n", *argv,
+ errno ? strerror(errno) : "contact file is malformatted");
ret = 1;
continue;
}
diff --git a/set-contact-groups.c b/set-contact-groups.c
index 2b8e3c1..f0408c5 100644
--- a/set-contact-groups.c
+++ b/set-contact-groups.c
@@ -39,7 +39,8 @@ main(int argc, char *argv[])
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");
+ weprintf("libcontacts_load_contact %s: %s\n", *argv,
+ errno ? strerror(errno) : "contact file is malformatted");
ret = 1;
continue;
}
@@ -48,17 +49,15 @@ main(int argc, char *argv[])
if (!strcmp(contact.groups[i], group))
break;
r = &contact.groups[i];
+ if (!remove && !*r)
+ goto add_group;
if (remove && *r) {
free(*r);
- for (w = r++; *r;)
- *w++ = *r++;
- *w = NULL;
+ for (w = r++; (*w++ = *r++););
if (libcontacts_save_contact(&contact, user)) {
weprintf("libcontacts_save_contact %s:", *argv);
ret = 1;
}
- } else if (!remove && !*r) {
- goto add_group;
}
} else if (!remove) {
i = 0;
diff --git a/set-contact-numbers.c b/set-contact-numbers.c
index b3ecfb2..5b81d7e 100644
--- a/set-contact-numbers.c
+++ b/set-contact-numbers.c
@@ -1,141 +1,13 @@
/* See LICENSE file for copyright and license details. */
-#include "common.h"
-
-USAGE("[-C old-context] [-N old-number] [-F | -f] [-M | -m] ([-c new-context] [-n new-number] | -u) contact-id");
-
-
-int
-main(int argc, char *argv[])
-{
- int set_facsimile = -1, set_mobile = -1, add = 1, edit = 0, remove = 0;
- char *context = NULL, *number = NULL;
- char *lookup_context = NULL, *lookup_number = NULL;
- char *old_context = NULL, *old_number = NULL;
- struct passwd *user;
- struct libcontacts_contact contact;
- struct libcontacts_number **r, **w;
- size_t i;
-
- ARGBEGIN {
- case 'C':
- add = 0;
- if (lookup_context)
- usage();
- lookup_context = ARG();
- break;
- case 'c':
- edit = 1;
- if (context)
- usage();
- context = ARG();
- break;
- case 'N':
- add = 0;
- if (lookup_number)
- usage();
- lookup_number = ARG();
- break;
- case 'n':
- edit = 1;
- if (number)
- usage();
- number = ARG();
- break;
- case 'F':
- if (set_facsimile >= 0)
- return 0;
- set_facsimile = 0;
- break;
- case 'f':
- if (set_facsimile >= 0)
- return 0;
- set_facsimile = 1;
- break;
- case 'M':
- if (set_mobile >= 0)
- return 0;
- set_mobile = 0;
- break;
- case 'm':
- if (set_mobile >= 0)
- return 0;
- set_mobile = 1;
- break;
- case 'u':
- remove = 1;
- break;
- default:
- usage();
- } ARGEND;
-
- if (remove == edit) {
- if (edit)
- usage();
- eprintf("at least one of -cnu is required\n");
- }
+#define CATEGORY numbers
- if (add)
- edit = 0;
+#define LIST_PARAMS(X)\
+ X('C', "C", 'c', "c", context, "context")\
+ X('N', "N", 'n', "n", number, "number")
- if (argc != 0 || !*argv[0] || strchr(argv[0], '/'))
- usage();
+#define LIST_BOOL_PARAMS(X)\
+ X('F', "F", 'f', "f", facsimile, "facsimile")\
+ X('M', "M", 'm', "m", mobile, "mobile")
- 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 ((edit || remove) && contact.numbers) {
- for (r = contact.numbers; *r; r++) {
- if (lookup_context && strcmpnul((*r)->context, lookup_context))
- continue;
- if (lookup_number && strcmpnul((*r)->context, lookup_number))
- continue;
- break;
- }
- if (!edit) {
- libcontacts_number_destroy(*r);
- free(*r);
- for (w = r++; (*w++ = *r++););
- } else if (*r) {
- if (context) {
- old_context = contact.numbers[i]->context;
- contact.numbers[i]->context = context;
- }
- if (number) {
- old_number = contact.numbers[i]->number;
- contact.numbers[i]->number = number;
- }
- if (set_mobile >= 0)
- contact.numbers[i]->is_mobile = set_mobile;
- if (set_facsimile >= 0)
- contact.numbers[i]->is_facsimile = set_facsimile;
- } else {
- libcontacts_contact_destroy(&contact);
- return 0;
- }
- } else if (!edit && !remove) {
- if (contact.numbers)
- for (i = 0; contact.numbers[i]; i++);
- contact.numbers = erealloc(contact.numbers, (i + 2) * sizeof(*contact.numbers));
- contact.numbers[i + 1] = NULL;
- contact.numbers[i] = ecalloc(1, sizeof(**contact.numbers));
- contact.numbers[i]->context = context;
- contact.numbers[i]->number = number;
- contact.numbers[i]->is_mobile = set_mobile > 0;
- contact.numbers[i]->is_facsimile = set_facsimile > 0;
- }
-
- if (libcontacts_save_contact(&contact, user))
- eprintf("libcontacts_save_contact %s:", argv[0]);
-
- contact.numbers[i]->context = old_context;
- contact.numbers[i]->number = old_number;
- libcontacts_contact_destroy(&contact);
-
- return 0;
-}
+#include "common.h"
+IMPLEMENT_SET_ON_LIST(number)
diff --git a/set-contact-organisations.c b/set-contact-organisations.c
index 733b8de..527e178 100644
--- a/set-contact-organisations.c
+++ b/set-contact-organisations.c
@@ -1,115 +1,9 @@
/* See LICENSE file for copyright and license details. */
-#include "common.h"
-
-USAGE("[-O old-organisation] [-T old-title] ([-o new-adress] [-t new-title] | -u) contact-id");
-
-
-int
-main(int argc, char *argv[])
-{
- int add = 1, edit = 0, remove = 0;
- char *organisation = NULL, *title = NULL;
- char *lookup_organisation = NULL, *lookup_title = NULL;
- char *old_organisation = NULL, *old_title = NULL;
- struct passwd *user;
- struct libcontacts_contact contact;
- struct libcontacts_organisation **r, **w;
- size_t i;
-
- ARGBEGIN {
- case 'O':
- add = 0;
- if (lookup_organisation)
- usage();
- lookup_organisation = ARG();
- break;
- case 'o':
- edit = 1;
- if (organisation)
- usage();
- organisation = ARG();
- break;
- case 'T':
- add = 0;
- if (lookup_title)
- usage();
- lookup_title = ARG();
- break;
- case 't':
- edit = 1;
- if (title)
- usage();
- title = ARG();
- break;
- case 'u':
- remove = 1;
- break;
- default:
- usage();
- } ARGEND;
-
- if (remove == edit) {
- if (edit)
- usage();
- eprintf("at least one of -otu is required\n");
- }
-
- if (add)
- edit = 0;
+#define CATEGORY organisations
- if (argc != 1 || !*argv[0] || strchr(argv[0], '/'))
- usage();
+#define LIST_PARAMS(X)\
+ X('O', "O", 'o', "o", organisation, "organisation")\
+ X('T', "T", 't', "t", title, "title")
- 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 ((edit || remove) && contact.organisations) {
- for (r = contact.organisations; *r; r++) {
- if (lookup_title && strcmpnul((*r)->title, lookup_title))
- continue;
- if (lookup_organisation && strcmpnul((*r)->title, lookup_organisation))
- continue;
- break;
- }
- if (!edit) {
- libcontacts_organisation_destroy(*r);
- free(*r);
- for (w = r++; (*w++ = *r++););
- } else if (*r) {
- if (title) {
- old_title = contact.organisations[i]->title;
- contact.organisations[i]->title = title;
- }
- if (organisation) {
- old_organisation = contact.organisations[i]->organisation;
- contact.organisations[i]->organisation = organisation;
- }
- } else {
- libcontacts_contact_destroy(&contact);
- return 0;
- }
- } else if (!edit && !remove) {
- if (contact.organisations)
- for (i = 0; contact.organisations[i]; i++);
- 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]->title = title;
- contact.organisations[i]->organisation = organisation;
- }
-
- if (libcontacts_save_contact(&contact, user))
- eprintf("libcontacts_save_contact %s:", argv[0]);
-
- contact.organisations[i]->title = old_title;
- contact.organisations[i]->organisation = old_organisation;
- libcontacts_contact_destroy(&contact);
-
- return 0;
-}
+#include "common.h"
+IMPLEMENT_SET_ON_LIST(organisation)
diff --git a/set-contact-pgpkeys.c b/set-contact-pgpkeys.c
index 93ad0ab..a221561 100644
--- a/set-contact-pgpkeys.c
+++ b/set-contact-pgpkeys.c
@@ -1,115 +1,9 @@
/* See LICENSE file for copyright and license details. */
-#include "common.h"
-
-USAGE("[-C old-context] [-F old-fingerprint] ([-c new-context] [-f new-fingerprint] | -u) contact-id");
-
-
-int
-main(int argc, char *argv[])
-{
- int add = 1, edit = 0, remove = 0;
- char *id = NULL, *context = NULL;
- char *lookup_id = NULL, *lookup_context = NULL;
- char *old_id = NULL, *old_context = NULL;
- struct passwd *user;
- struct libcontacts_contact contact;
- struct libcontacts_pgpkey **r, **w;
- size_t i;
-
- ARGBEGIN {
- case 'C':
- add = 0;
- if (lookup_context)
- usage();
- lookup_context = ARG();
- break;
- case 'c':
- edit = 0;
- if (context)
- usage();
- context = ARG();
- break;
- case 'F':
- add = 1;
- if (lookup_id)
- usage();
- lookup_id = ARG();
- break;
- case 'f':
- edit = 1;
- if (id)
- usage();
- id = ARG();
- break;
- case 'u':
- remove = 1;
- break;
- default:
- usage();
- } ARGEND;
-
- if (remove == edit) {
- if (edit)
- usage();
- eprintf("at least one of -cfu is required\n");
- }
-
- if (add)
- edit = 0;
+#define CATEGORY pgpkeys
- if (argc != 1 || !*argv[0] || strchr(argv[0], '/'))
- usage();
+#define LIST_PARAMS(X)\
+ X('C', "C", 'c', "c", context, "context")\
+ X('F', "F", 'f', "f", id, "fingerprint")
- 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 ((edit || remove) && contact.pgpkeys) {
- for (r = contact.pgpkeys; *r; r++) {
- if (lookup_context && strcmpnul((*r)->context, lookup_context))
- continue;
- if (lookup_id && strcmpnul((*r)->context, lookup_id))
- continue;
- break;
- }
- if (!edit) {
- libcontacts_pgpkey_destroy(*r);
- free(*r);
- for (w = r++; (*w++ = *r++););
- } else if (*r) {
- if (context) {
- old_context = contact.pgpkeys[i]->context;
- contact.pgpkeys[i]->context = context;
- }
- if (id) {
- old_id = contact.pgpkeys[i]->id;
- contact.pgpkeys[i]->id = id;
- }
- } else {
- libcontacts_contact_destroy(&contact);
- return 0;
- }
- } else if (!edit && !remove) {
- if (contact.pgpkeys)
- for (i = 0; contact.pgpkeys[i]; i++);
- 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 = context;
- contact.pgpkeys[i]->id = id;
- }
-
- if (libcontacts_save_contact(&contact, user))
- eprintf("libcontacts_save_contact %s:", argv[0]);
-
- contact.pgpkeys[i]->context = old_context;
- contact.pgpkeys[i]->id = old_id;
- libcontacts_contact_destroy(&contact);
-
- return 0;
-}
+#include "common.h"
+IMPLEMENT_SET_ON_LIST(pgpkey)
diff --git a/set-contact-photos.c b/set-contact-photos.c
index 9c62d24..51366dd 100644
--- a/set-contact-photos.c
+++ b/set-contact-photos.c
@@ -1,7 +1,7 @@
/* See LICENSE file for copyright and license details. */
#include "common.h"
-USAGE("[-ru] contact-id ... photo");
+USAGE("[-r | -u] contact-id ... photo");
static char *
@@ -15,8 +15,13 @@ get_target(const char *path, size_t *lenp)
if ((size_t)n == size)
target = erealloc(target, size += 512);
n = readlink(path, target, size);
- if (n < 0)
+ if (n < 0) {
+ if (errno == EINVAL) {
+ free(target);
+ return NULL;
+ }
eprintf("readlink %s:", path);
+ }
} while ((size_t)n >= size);
*lenp = (size_t)n;
@@ -37,13 +42,13 @@ get_absolute_path(const char *path, const char *cwd)
ret = emalloc(retlennul);
memcpy(ret, path, retlennul);
} else {
- len1 = strlen(path);
- len2 = strlen(cwd);
+ len1 = strlen(cwd);
+ len2 = strlen(path);
retlennul = len1 + len2 + 2;
ret = emalloc(retlennul);
- memcpy(ret, path, len1);
+ memcpy(ret, cwd, len1);
ret[len1++] = '/';
- memcpy(&ret[len1], cwd, ++len2);
+ memcpy(&ret[len1], path, ++len2);
}
again:
@@ -157,15 +162,15 @@ main(int argc, char *argv[])
break;
case 'u':
remove = 1;
- as_is = 1;
break;
default:
usage();
} ARGEND;
- if (argc < 2)
+ if (argc < 2 || (as_is & remove))
usage();
+ as_is |= remove;
photo = argv[--argc];
argv[argc] = NULL;
@@ -195,7 +200,8 @@ main(int argc, char *argv[])
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");
+ weprintf("libcontacts_load_contact %s: %s\n", *argv,
+ errno ? strerror(errno) : "contact file is malformatted");
ret = 1;
continue;
}
@@ -204,17 +210,15 @@ main(int argc, char *argv[])
if (!strcmp(contact.photos[i], photo))
break;
r = &contact.photos[i];
+ if (!remove && !*r)
+ goto add_photo;
if (remove && *r) {
free(*r);
- for (w = r++; *r;)
- *w++ = *r++;
- *w = NULL;
+ for (w = r++; (*w++ = *r++););
if (libcontacts_save_contact(&contact, user)) {
weprintf("libcontacts_save_contact %s:", *argv);
ret = 1;
}
- } else if (!remove && !*r) {
- goto add_photo;
}
} else if (!remove) {
i = 0;
diff --git a/set-contact-sites.c b/set-contact-sites.c
index 6a9f60f..6add649 100644
--- a/set-contact-sites.c
+++ b/set-contact-sites.c
@@ -1,115 +1,9 @@
/* See LICENSE file for copyright and license details. */
-#include "common.h"
-
-USAGE("[-A old-address] [-C old-context] ([-a new-adress] [-c new-context] | -u) contact-id");
-
-
-int
-main(int argc, char *argv[])
-{
- int add = 1, edit = 0, remove = 0;
- char *address = NULL, *context = NULL;
- char *lookup_address = NULL, *lookup_context = NULL;
- char *old_address = NULL, *old_context = NULL;
- struct passwd *user;
- struct libcontacts_contact contact;
- struct libcontacts_site **r, **w;
- size_t i;
-
- ARGBEGIN {
- case 'A':
- add = 0;
- if (lookup_address)
- usage();
- lookup_address = ARG();
- break;
- case 'a':
- edit = 1;
- if (address)
- usage();
- address = ARG();
- break;
- case 'C':
- add = 0;
- if (lookup_context)
- usage();
- lookup_context = ARG();
- break;
- case 'c':
- edit = 1;
- if (context)
- usage();
- context = ARG();
- break;
- case 'u':
- remove = 1;
- break;
- default:
- usage();
- } ARGEND;
-
- if (remove == edit) {
- if (edit)
- usage();
- eprintf("at least one of -acu is required\n");
- }
-
- if (add)
- edit = 0;
+#define CATEGORY sites
- if (argc != 1 || !*argv[0] || strchr(argv[0], '/'))
- usage();
+#define LIST_PARAMS(X)\
+ X('A', "A", 'a', "a", address, "address")\
+ X('C', "C", 'c', "c", context, "context")
- 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 ((edit || remove) && contact.sites) {
- for (r = contact.sites; *r; r++) {
- if (lookup_context && strcmpnul((*r)->context, lookup_context))
- continue;
- if (lookup_address && strcmpnul((*r)->context, lookup_address))
- continue;
- break;
- }
- if (!edit) {
- libcontacts_site_destroy(*r);
- free(*r);
- for (w = r++; (*w++ = *r++););
- } else if (*r) {
- if (context) {
- old_context = contact.sites[i]->context;
- contact.sites[i]->context = context;
- }
- if (address) {
- old_address = contact.sites[i]->address;
- contact.sites[i]->address = address;
- }
- } else {
- libcontacts_contact_destroy(&contact);
- return 0;
- }
- } else if (!edit && !remove) {
- if (contact.sites)
- for (i = 0; contact.sites[i]; i++);
- 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 = context;
- contact.sites[i]->address = address;
- }
-
- if (libcontacts_save_contact(&contact, user))
- eprintf("libcontacts_save_contact %s:", argv[0]);
-
- contact.sites[i]->context = old_context;
- contact.sites[i]->address = old_address;
- libcontacts_contact_destroy(&contact);
-
- return 0;
-}
+#include "common.h"
+IMPLEMENT_SET_ON_LIST(site)