aboutsummaryrefslogblamecommitdiffstats
path: root/common.h
blob: d1345f57c27d8ac9e72b523ce0899b9f5f4ea132 (plain) (tree)
1
2
3
4
5
6
7
8
9
                                                         



                                          



                          

                 
 


                    


                       


                                           


                                                                              

                      
                                                                                                                             































































































































































                                                                                                                        
/* See LICENSE file for copyright and license details. */
#ifdef MULTICALL_BINARY
# define LIBSIMPLY_CONFIG_MULTICALL_BINARY
#endif

#include <libcontacts.h>
#include <libsimple.h>
#include <libsimple-arg.h>

#include <math.h>


#ifndef BUFSIZ
# define BUFSIZ 4096
#endif


/* common-birthday.c */
#if defined(__GNUC__) || defined(__clang__)
__attribute__((__pure__))
#endif
int get_age(struct libcontacts_birthday *bday, const struct tm *now);
void print_birthdate(struct libcontacts_birthday *bday, const struct tm *now);
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;\
	}