diff options
-rw-r--r-- | Makefile | 5 | ||||
-rw-r--r-- | TODO | 4 | ||||
-rw-r--r-- | libcontacts.h | 4 | ||||
-rw-r--r-- | libcontacts_address_destroy.3 | 34 | ||||
-rw-r--r-- | libcontacts_birthday_destroy.3 | 34 | ||||
-rw-r--r-- | libcontacts_block_destroy.3 | 34 | ||||
-rw-r--r-- | libcontacts_chat_destroy.3 | 34 | ||||
-rw-r--r-- | libcontacts_contact_destroy.3 | 44 | ||||
-rw-r--r-- | libcontacts_email_destroy.3 | 34 | ||||
-rw-r--r-- | libcontacts_format_contact.3 | 52 | ||||
-rw-r--r-- | libcontacts_get_path.3 | 94 | ||||
-rw-r--r-- | libcontacts_list_contacts.3 | 67 | ||||
-rw-r--r-- | libcontacts_load_contact.3 | 75 | ||||
-rw-r--r-- | libcontacts_load_contact.c | 12 | ||||
-rw-r--r-- | libcontacts_load_contacts.3 | 74 | ||||
-rw-r--r-- | libcontacts_number_destroy.3 | 34 | ||||
-rw-r--r-- | libcontacts_organisation_destroy.3 | 34 | ||||
-rw-r--r-- | libcontacts_parse_contact.3 | 80 | ||||
-rw-r--r-- | libcontacts_parse_contact.c | 235 | ||||
-rw-r--r-- | libcontacts_pgpkey_destroy.3 | 34 | ||||
-rw-r--r-- | libcontacts_same_number.3 | 74 | ||||
-rw-r--r-- | libcontacts_save_contact.3 | 78 | ||||
-rw-r--r-- | libcontacts_save_contact.c | 8 | ||||
-rw-r--r-- | libcontacts_site_destroy.3 | 34 | ||||
-rw-r--r-- | test.c | 1 |
25 files changed, 1087 insertions, 126 deletions
@@ -42,6 +42,8 @@ HDR =\ LOBJ = $(OBJ:.o=.lo) +MAN3 = $(OBJ:.o=.3) + all: libcontacts.a libcontacts.$(LIBEXT) test $(OBJ): $($@:.o=.c) $(HDR) @@ -72,11 +74,13 @@ check: test install: libcontacts.a libcontacts.$(LIBEXT) mkdir -p -- "$(DESTDIR)$(PREFIX)/lib" mkdir -p -- "$(DESTDIR)$(PREFIX)/include" + mkdir -p -- "$(DESTDIR)$(MANPREFIX)/man3" cp -- libcontacts.a "$(DESTDIR)$(PREFIX)/lib/" cp -- libcontacts.h "$(DESTDIR)$(PREFIX)/include/" cp -- libcontacts.$(LIBEXT) "$(DESTDIR)$(PREFIX)/lib/libcontacts.$(LIBMINOREXT)" ln -sf -- libcontacts.$(LIBMINOREXT) "$(DESTDIR)$(PREFIX)/lib/libcontacts.$(LIBMAJOREXT)" ln -sf -- libcontacts.$(LIBMAJOREXT) "$(DESTDIR)$(PREFIX)/lib/libcontacts.$(LIBEXT)" + cp -- $(MAN3) "$(DESTDIR)$(MANPREFIX)/man3/" uninstall: -rm -f -- "$(DESTDIR)$(PREFIX)/lib/libcontacts.$(LIBMAJOREXT)" @@ -84,6 +88,7 @@ uninstall: -rm -f -- "$(DESTDIR)$(PREFIX)/lib/libcontacts.$(LIBEXT)" -rm -f -- "$(DESTDIR)$(PREFIX)/lib/libcontacts.a" -rm -f -- "$(DESTDIR)$(PREFIX)/include/libcontacts.h" + -cd -- "$(DESTDIR)$(MANPREFIX)/man3/" && rm -rf -- $(MAN3) clean: -rm -rf -- *.o *.a *.lo *.so *.dylib *.dll *.su test .testdir @@ -1 +1,3 @@ -Add man pages +Add libcontacts.7 +Add libcontacts.h.0 +Add contacts.5 diff --git a/libcontacts.h b/libcontacts.h index 98bce5b..6ce77d2 100644 --- a/libcontacts.h +++ b/libcontacts.h @@ -292,13 +292,13 @@ struct libcontacts_contact { void libcontacts_contact_destroy(struct libcontacts_contact *); int libcontacts_list_contacts(char ***, const struct passwd *, int); -int libcontacts_load_contact(const char *, struct libcontacts_contact *, const struct passwd *); /* errno = 0 if malformatted */ +int libcontacts_load_contact(const char *, struct libcontacts_contact *, const struct passwd *); int libcontacts_load_contacts(struct libcontacts_contact ***, const struct passwd *, int); int libcontacts_save_contact(struct libcontacts_contact *, const struct passwd *); int libcontacts_same_number(const char *, const char *, const char *, const char *); /* might be removed in the future */ char *libcontacts_get_path(const char *, const struct passwd *); -int libcontacts_parse_contact(char *, struct libcontacts_contact *); /* does not load .id, not stored in file, but is the filename */ +int libcontacts_parse_contact(char *, struct libcontacts_contact *); int libcontacts_format_contact(const struct libcontacts_contact *, char **); void libcontacts_block_destroy(struct libcontacts_block *); diff --git a/libcontacts_address_destroy.3 b/libcontacts_address_destroy.3 new file mode 100644 index 0000000..cc5c606 --- /dev/null +++ b/libcontacts_address_destroy.3 @@ -0,0 +1,34 @@ +.TH LIBCONTACTS_ADDRESS_DESTROY 3 LIBCONTACTS +.SH NAME +libcontacts_address_destroy \- Deallocate memory for a contact address entry +.SH SYNOPSIS +.nf +#include <libcontacts.h> + +int libcontacts_address_destroy(struct libcontacts_address *\fIentry\fP); +.fi +.PP +Link with +.IR -lcontacts . + +.SH DESCRIPTION +The +.BR libcontacts_address_destroy () +function deallocates the memory stored in +.IR *entry . +The caller must manually call +.BR free (3) +on the pointer +.I entry +afterwards if it a freeable pointer. + +.SH RETURN VALUE +None. + +.SH ERRORS +None. + +.SH SEE ALSO +.BR libcontacts.h (0), +.BR libcontacts (7), +.BR libcontacts_contact_destroy (3) diff --git a/libcontacts_birthday_destroy.3 b/libcontacts_birthday_destroy.3 new file mode 100644 index 0000000..d9ba628 --- /dev/null +++ b/libcontacts_birthday_destroy.3 @@ -0,0 +1,34 @@ +.TH LIBCONTACTS_BIRTHDAY_DESTROY 3 LIBCONTACTS +.SH NAME +libcontacts_birthday_destroy \- Deallocate memory for a contact birthday entry +.SH SYNOPSIS +.nf +#include <libcontacts.h> + +int libcontacts_birthday_destroy(struct libcontacts_birthday *\fIentry\fP); +.fi +.PP +Link with +.IR -lcontacts . + +.SH DESCRIPTION +The +.BR libcontacts_birthday_destroy () +function deallocates the memory stored in +.IR *entry . +The caller must manually call +.BR free (3) +on the pointer +.I entry +afterwards if it a freeable pointer. + +.SH RETURN VALUE +None. + +.SH ERRORS +None. + +.SH SEE ALSO +.BR libcontacts.h (0), +.BR libcontacts (7), +.BR libcontacts_contact_destroy (3) diff --git a/libcontacts_block_destroy.3 b/libcontacts_block_destroy.3 new file mode 100644 index 0000000..3742b52 --- /dev/null +++ b/libcontacts_block_destroy.3 @@ -0,0 +1,34 @@ +.TH LIBCONTACTS_BLOCK_DESTROY 3 LIBCONTACTS +.SH NAME +libcontacts_block_destroy \- Deallocate memory for a contact block entry +.SH SYNOPSIS +.nf +#include <libcontacts.h> + +int libcontacts_block_destroy(struct libcontacts_block *\fIentry\fP); +.fi +.PP +Link with +.IR -lcontacts . + +.SH DESCRIPTION +The +.BR libcontacts_block_destroy () +function deallocates the memory stored in +.IR *entry . +The caller must manually call +.BR free (3) +on the pointer +.I entry +afterwards if it a freeable pointer. + +.SH RETURN VALUE +None. + +.SH ERRORS +None. + +.SH SEE ALSO +.BR libcontacts.h (0), +.BR libcontacts (7), +.BR libcontacts_contact_destroy (3) diff --git a/libcontacts_chat_destroy.3 b/libcontacts_chat_destroy.3 new file mode 100644 index 0000000..e504b64 --- /dev/null +++ b/libcontacts_chat_destroy.3 @@ -0,0 +1,34 @@ +.TH LIBCONTACTS_CHAT_DESTROY 3 LIBCONTACTS +.SH NAME +libcontacts_chat_destroy \- Deallocate memory for a contact chat service address entry +.SH SYNOPSIS +.nf +#include <libcontacts.h> + +int libcontacts_chat_destroy(struct libcontacts_chat *\fIentry\fP); +.fi +.PP +Link with +.IR -lcontacts . + +.SH DESCRIPTION +The +.BR libcontacts_chat_destroy () +function deallocates the memory stored in +.IR *entry . +The caller must manually call +.BR free (3) +on the pointer +.I entry +afterwards if it a freeable pointer. + +.SH RETURN VALUE +None. + +.SH ERRORS +None. + +.SH SEE ALSO +.BR libcontacts.h (0), +.BR libcontacts (7), +.BR libcontacts_contact_destroy (3) diff --git a/libcontacts_contact_destroy.3 b/libcontacts_contact_destroy.3 new file mode 100644 index 0000000..910c245 --- /dev/null +++ b/libcontacts_contact_destroy.3 @@ -0,0 +1,44 @@ +.TH LIBCONTACTS_CONTACT_DESTROY 3 LIBCONTACTS +.SH NAME +libcontacts_contact_destroy \- Deallocate memory for a contact entry +.SH SYNOPSIS +.nf +#include <libcontacts.h> + +int libcontacts_contact_destroy(struct libcontacts_contact *\fIentry\fP); +.fi +.PP +Link with +.IR -lcontacts . + +.SH DESCRIPTION +The +.BR libcontacts_contact_destroy () +function deallocates the memory stored in +.IR *entry , +including any subentries that are deallocatable +with other functions provided by libcontacts. +The caller must manually call +.BR free (3) +on the pointer +.I entry +afterwards if it a freeable pointer. + +.SH RETURN VALUE +None. + +.SH ERRORS +None. + +.SH SEE ALSO +.BR libcontacts.h (0), +.BR libcontacts (7), +.BR libcontacts_address_destroy (3), +.BR libcontacts_birthday_destroy (3), +.BR libcontacts_block_destroy (3), +.BR libcontacts_chat_destroy (3), +.BR libcontacts_email_destroy (3), +.BR libcontacts_number_destroy (3), +.BR libcontacts_organisation_destroy (3), +.BR libcontacts_pgpkey_destroy (3), +.BR libcontacts_site_destroy (3) diff --git a/libcontacts_email_destroy.3 b/libcontacts_email_destroy.3 new file mode 100644 index 0000000..387bd18 --- /dev/null +++ b/libcontacts_email_destroy.3 @@ -0,0 +1,34 @@ +.TH LIBCONTACTS_EMAIL_DESTROY 3 LIBCONTACTS +.SH NAME +libcontacts_email_destroy \- Deallocate memory for a contact e-mail address entry +.SH SYNOPSIS +.nf +#include <libcontacts.h> + +int libcontacts_email_destroy(struct libcontacts_email *\fIentry\fP); +.fi +.PP +Link with +.IR -lcontacts . + +.SH DESCRIPTION +The +.BR libcontacts_email_destroy () +function deallocates the memory stored in +.IR *entry . +The caller must manually call +.BR free (3) +on the pointer +.I entry +afterwards if it a freeable pointer. + +.SH RETURN VALUE +None. + +.SH ERRORS +None. + +.SH SEE ALSO +.BR libcontacts.h (0), +.BR libcontacts (7), +.BR libcontacts_contact_destroy (3) diff --git a/libcontacts_format_contact.3 b/libcontacts_format_contact.3 new file mode 100644 index 0000000..59de67c --- /dev/null +++ b/libcontacts_format_contact.3 @@ -0,0 +1,52 @@ +.TH LIBCONTACTS_FORMAT_CONTACT 3 LIBCONTACTS +.SH NAME +libcontacts_format_contact \- Construct a contact file +.SH SYNOPSIS +.nf +#include <libcontacts.h> + +int libcontacts_format_contact(const struct libcontacts_contact *\fIcontact\fP, char **\fIdatap\fP); +.fi +.PP +Link with +.IR -lcontacts . + +.SH DESCRIPTION +The +.BR libcontacts_format_contact () +function formats the content that shall be stored +the a contact file, for the contact in the +.I contact +parameter. The resulting content will be NUL-terminated +and, upon successful completion, stored in +.IR *datap . +The caller must manually deallocate the content with the +.BR free (3) +function when it's no longer needed. + +.SH RETURN VALUE +The +.BR libcontacts_format_contact () +function returns 0 upon successful completion; +otherwise -1 is returned and +.I errno +is set appropriately to indicate the error. + +.SH ERRORS +The +.BR libcontacts_format_contact () +function may fail for any reason specified for the +.BR open_memstream (3) +and +.BR fprintf (3) +(other than +.IR EILSEQ ) +functions. + +.SH SEE ALSO +.BR libcontacts.h (0), +.BR libcontacts (7) +.BR libcontacts_save_contact (3), +.BR libcontacts_parse_contact (3), +.BR libcontacts_get_file (3), +.BR contacts (5), diff --git a/libcontacts_get_path.3 b/libcontacts_get_path.3 new file mode 100644 index 0000000..d1e62f2 --- /dev/null +++ b/libcontacts_get_path.3 @@ -0,0 +1,94 @@ +.TH LIBCONTACTS_GET_PATH 3 LIBCONTACTS +.SH NAME +libcontacts_get_path \- Get the file information for a contact is or would be stored in +.SH SYNOPSIS +.nf +#include <libcontacts.h> + +char *libcontacts_get_path(const char *\fIid\fP, const struct passwd *\fIuser\fP); +.fi +.PP +Link with +.IR -lcontacts . + +.SH DESCRIPTION +The +.BR libcontacts_get_path () +function get the path to the file for the contact with +the ID specified in the +.I id +parameter, neither this file nor its directory need exist +for successful completion to the place. If +.I id +is the empty string, the directory where all contacts is +returned with a trailing slash +.RB ( / ). +.PP +.I user +shall be the user's entry in the password database (not +the shadow database). This is used for the get user's +home directory. + +.SH RETURN VALUE +The +.BR libcontacts_get_path () +function returns the path the file where the information +for the specified contact is stored (or if requested, +the directory where contact files are stored) upon successful +completion; on failure +.I NULL +is returned and +.I errno +is set appropriately to indicate the error. + +.SH ERRORS +The +.BR libcontacts_get_path () +function will fail if: +.TP +.B EINVAL +Either parameter is +.I NULL +or the home directory field in +.I user +is +.I NULL +or the empty string. +.PP +The +.BR libcontacts_get_path () +function may also fail for any reason specified for the +.BR malloc (3) +function. + +.SH EXTENDED DESCRIPTION +All contact file shall be stored in +.I .config/contacts/ +within the user's home directory. All environment variables +shall be ignored. +.PP +The contact ID +.RI ( id ) +must not contain slashes, and should ideally only contain +lower case ASCII letters, ASCII digits, and ASCII hyphens. +Contact ID's starting with a dot have special meaning, +currently define ones are: +.TP +.B .me +Contact information for the user. +.TP +.B .groups +Pseudo-contact where groups that how no members can be +stored. +.PP +The contact ID +.RI ( id ) +must end with a tilde, these are used to write to until +file system synchronisation has takes place for the file, +and the file is subsequently renamed. + +.SH SEE ALSO +.BR libcontacts.h (0), +.BR libcontacts (7), +.BR libcontacts_load_contact (7), +.BR libcontacts_save_contact (7) diff --git a/libcontacts_list_contacts.3 b/libcontacts_list_contacts.3 new file mode 100644 index 0000000..abe4365 --- /dev/null +++ b/libcontacts_list_contacts.3 @@ -0,0 +1,67 @@ +.TH LIBCONTACTS_LIST_CONTACTS 3 LIBCONTACTS +.SH NAME +libcontacts_list_contacts \- Get a list of all contacts +.SH SYNOPSIS +.nf +#include <libcontacts.h> + +int libcontacts_list_contacts(char ***\fIidsp\fP, const struct passwd *\fIuser\fP, int \fIwith_me\fP); +.fi +.PP +Link with +.IR -lcontacts . + +.SH DESCRIPTION +The +.BR libcontacts_list_contacts () +function create a +.IR NULL -termianted +list of all regular contact entries and stores it in +.I *idsp +upon successful completion. If +.I with_me +is non-zero, the +.B .me +entry will also be included, if it exists. +.PP +.I user +shall be the user's entry in the password database (not +the shadow database). This is used for the get user's +home directory. +.PP +When no longer needed, the caller shall manually +deallocate all elements in +.I *idsp +along with +.I *idsp +itself, using the +.BR free (3) +function. + +.SH RETURN VALUE +The +.BR libcontacts_list_contacts () +function returns 0 upon successful completion; +otherwise -1 is returned and +.I errno +is set appropriately to indicate the error. + +.SH ERRORS +The +.BR libcontacts_list_contacts () +function may fail for any reason specified for the +.BR libcontacts_get_path (3), +.BR opendir (3) +(other than +.IR ENOENT ), +.BR realloc (3), +and +.BR readdir (3) +functions. + +.SH SEE ALSO +.BR libcontacts.h (0), +.BR libcontacts (7), +.BR libcontacts_get_path (3), +.BR libcontacts_load_contact (3), +.BR libcontacts_load_contacts (3) diff --git a/libcontacts_load_contact.3 b/libcontacts_load_contact.3 new file mode 100644 index 0000000..e6f5521 --- /dev/null +++ b/libcontacts_load_contact.3 @@ -0,0 +1,75 @@ +.TH LIBCONTACTS_LOAD_CONTACT 3 LIBCONTACTS +.SH NAME +libcontacts_load_contact \- Load a contact +.SH SYNOPSIS +.nf +#include <libcontacts.h> + +int libcontacts_load_contact(const char *\fIid\fP, struct libcontacts_contact *\fIcontactp\fP, const struct passwd *\fIuser\fP); +.fi +.PP +Link with +.IR -lcontacts . + +.SH DESCRIPTION +The +.BR libcontacts_load_contact () +function loads the entry of the contact, whose ID +is specified in the +.I id +parameter, and store it in +.I *contactp +upon successful completion. +.PP +.I user +shall be the user's entry in the password database (not +the shadow database). This is used for the get user's +home directory. +.PP +When no longer needed, the caller shall manually +deallocate all member stored in +.I *contactp +using the +.BR libcontacts_contact_destroy (3) +function. +.PP +The pointer +.I id +will be copied to +.IR contactp->id . + +.SH RETURN VALUE +The +.BR libcontacts_load_contact () +function returns 0 upon successful completion; +otherwise -1 is returned and +.I errno +is set appropriately to indicate the error. + +.SH ERRORS +The +.BR libcontacts_load_contact () +function will fail if: +.TP +.B 0 +The file it loads contains a NUL byte. +.PP +The +.BR libcontacts_load_contact () +function may fail for any reason specified for the +.BR libcontacts_get_path (3), +.BR libcontacts_parse_contact (3), +.BR open (3), +.BR realloc (3), +and +.BR read (3) +functions. + +.SH SEE ALSO +.BR libcontacts.h (0), +.BR libcontacts (7), +.BR libcontacts_loads_contact (3), +.BR libcontacts_save_contact (3), +.BR libcontacts_contact_destroy (3), +.BR libcontacts_list_contacts (3), +.BR libcontacts_parse_contact (3) diff --git a/libcontacts_load_contact.c b/libcontacts_load_contact.c index 0821871..af931f9 100644 --- a/libcontacts_load_contact.c +++ b/libcontacts_load_contact.c @@ -3,7 +3,7 @@ int -libcontacts_load_contact(const char *id, struct libcontacts_contact *contact, const struct passwd *user) +libcontacts_load_contact(const char *id, struct libcontacts_contact *contactp, const struct passwd *user) { int ret, fd, saved_errno; char *data = NULL, *path; @@ -11,7 +11,7 @@ libcontacts_load_contact(const char *id, struct libcontacts_contact *contact, co ssize_t r; void *new; - if (!contact) { + if (!contactp) { errno = EINVAL; return -1; } @@ -48,11 +48,11 @@ libcontacts_load_contact(const char *id, struct libcontacts_contact *contact, co } close(fd); - ret = libcontacts_parse_contact(data, contact); + ret = libcontacts_parse_contact(data, contactp); free(data); - if (!ret && !(contact->id = strdup(id))) { - libcontacts_contact_destroy(contact); - memset(contact, 0, sizeof(*contact)); + if (!ret && !(contactp->id = strdup(id))) { + libcontacts_contact_destroy(contactp); + memset(contactp, 0, sizeof(*contactp)); return -1; } return ret; diff --git a/libcontacts_load_contacts.3 b/libcontacts_load_contacts.3 new file mode 100644 index 0000000..6b0649b --- /dev/null +++ b/libcontacts_load_contacts.3 @@ -0,0 +1,74 @@ +.TH LIBCONTACTS_LOAD_CONTACTS 3 LIBCONTACTS +.SH NAME +libcontacts_load_contacts \- Load all contacts +.SH SYNOPSIS +.nf +#include <libcontacts.h> + +int libcontacts_load_contacts(struct libcontacts_contact ***\fIcontactsp\fP, const struct passwd *\fIuser\fP, int \fIwith_me\fP); +.fi +.PP +Link with +.IR -lcontacts . + +.SH DESCRIPTION +The +.BR libcontacts_load_contacts () +function loads all regular contact entries and stores +them as a +.IR NULL -termianted +list in +.I *contactsp +upon successful completion. If +.I with_me +is non-zero, the +.B .me +entry will also be included, if it exists. +.PP +.I user +shall be the user's entry in the password database (not +the shadow database). This is used for the get user's +home directory. +.PP +When no longer needed, the caller shall manually +deallocate all elements in +.IR *contactsp , +using the +.BR libcontacts_contact_destroy (3) +and +.BR free (3) +functions, along with +.I *contactsp +itself, using the +.BR free (3) +function. + +.SH RETURN VALUE +The +.BR libcontacts_load_contacts () +function returns 0 upon successful completion; +otherwise -1 is returned and +.I errno +is set appropriately to indicate the error. + +.SH ERRORS +The +.BR libcontacts_load_contacts () +function may fail for any reason specified for the +.BR libcontacts_list_contacts (3), +.BR libcontacts_load_contacts (3) +(other than +.I ENOENT +and +.IR EACCES ), +and +.BR calloc (3) +functions. + +.SH SEE ALSO +.BR libcontacts.h (0), +.BR libcontacts (7), +.BR libcontacts_load_contact (3), +.BR libcontacts_save_contact (3), +.BR libcontacts_contact_destroy (3), +.BR libcontacts_list_contacts (3) diff --git a/libcontacts_number_destroy.3 b/libcontacts_number_destroy.3 new file mode 100644 index 0000000..5f3cafc --- /dev/null +++ b/libcontacts_number_destroy.3 @@ -0,0 +1,34 @@ +.TH LIBCONTACTS_NUMBER_DESTROY 3 LIBCONTACTS +.SH NAME +libcontacts_number_destroy \- Deallocate memory for a contact telephone number entry +.SH SYNOPSIS +.nf +#include <libcontacts.h> + +int libcontacts_number_destroy(struct libcontacts_number *\fIentry\fP); +.fi +.PP +Link with +.IR -lcontacts . + +.SH DESCRIPTION +The +.BR libcontacts_number_destroy () +function deallocates the memory stored in +.IR *entry . +The caller must manually call +.BR free (3) +on the pointer +.I entry +afterwards if it a freeable pointer. + +.SH RETURN VALUE +None. + +.SH ERRORS +None. + +.SH SEE ALSO +.BR libcontacts.h (0), +.BR libcontacts (7), +.BR libcontacts_contact_destroy (3) diff --git a/libcontacts_organisation_destroy.3 b/libcontacts_organisation_destroy.3 new file mode 100644 index 0000000..f192eb1 --- /dev/null +++ b/libcontacts_organisation_destroy.3 @@ -0,0 +1,34 @@ +.TH LIBCONTACTS_ORGANISATION_DESTROY 3 LIBCONTACTS +.SH NAME +libcontacts_organisation_destroy \- Deallocate memory for a contact organisation membership entry +.SH SYNOPSIS +.nf +#include <libcontacts.h> + +int libcontacts_organisation_destroy(struct libcontacts_organisation *\fIentry\fP); +.fi +.PP +Link with +.IR -lcontacts . + +.SH DESCRIPTION +The +.BR libcontacts_organisation_destroy () +function deallocates the memory stored in +.IR *entry . +The caller must manually call +.BR free (3) +on the pointer +.I entry +afterwards if it a freeable pointer. + +.SH RETURN VALUE +None. + +.SH ERRORS +None. + +.SH SEE ALSO +.BR libcontacts.h (0), +.BR libcontacts (7), +.BR libcontacts_contact_destroy (3) diff --git a/libcontacts_parse_contact.3 b/libcontacts_parse_contact.3 new file mode 100644 index 0000000..f2474d6 --- /dev/null +++ b/libcontacts_parse_contact.3 @@ -0,0 +1,80 @@ +.TH LIBCONTACTS_PARSE_CONTACT 3 LIBCONTACTS +.SH NAME +libcontacts_parse_contact \- Parse a contact file +.SH SYNOPSIS +.nf +#include <libcontacts.h> + +int libcontacts_parse_contact(char *\fIdata\fP, struct libcontacts_contact *\fIcontact\fP); +.fi +.PP +Link with +.IR -lcontacts . + +.SH DESCRIPTION +The +.BR libcontacts_parse_contact () +function parses the content of a contact file. +The file content shall be NUL-terminated and +given in the +.I data +parameter. The resulting contact information +will be stored in the +.IR *contact . +The user is responsable for deallocating the +result when it's no longer needed, using the +.BR libcontacts_contact_destroy (3) +function, or manually with +.BR free (3), +and the various functions references in the +.B SEE ALSO +section. +.PP +Note that the file contents do not contain the +contact ID, so +.I contact->id +will be set to +.IR NULL . +.PP +Also note that the contents of +.I data +may be modified by the function during the +execution of the function, it will however be +restored before the function returns. + +.SH RETURN VALUE +The +.BR libcontacts_parse_contact () +function returns 0 upon successful completion; +otherwise -1 is returned and +.I errno +is set appropriately to indicate the error. + +.SH ERRORS +The +.BR libcontacts_parse_contact () +function may fail for any reason specified for the +.BR open_memstream (3) +and +.BR fprintf (3) +(other than +.IR EILSEQ ) +functions. + +.SH SEE ALSO +.BR libcontacts.h (0), +.BR libcontacts (7) +.BR libcontacts_load_contact (3), +.BR libcontacts_format_contact (3), +.BR libcontacts_get_file (3), +.BR libcontacts_contact_destroy (3), +.BR libcontacts_address_destroy (3), +.BR libcontacts_birthday_destroy (3), +.BR libcontacts_block_destroy (3), +.BR libcontacts_chat_destroy (3), +.BR libcontacts_email_destroy (3), +.BR libcontacts_number_destroy (3), +.BR libcontacts_organisation_destroy (3), +.BR libcontacts_pgpkey_destroy (3), +.BR libcontacts_site_destroy (3), +.BR contacts (5), diff --git a/libcontacts_parse_contact.c b/libcontacts_parse_contact.c index f16ee94..f081c54 100644 --- a/libcontacts_parse_contact.c +++ b/libcontacts_parse_contact.c @@ -129,7 +129,7 @@ appendstr(char **strp, char *new) } static int -parse_coord(char *s, double *lat, double *lon) +parse_coord(const char *s, double *lat, double *lon) { int withsign = 0; int saved_errno = errno; @@ -139,7 +139,7 @@ parse_coord(char *s, double *lat, double *lon) withsign = (s[0] == '-' || s[0] == '+'); if (s[withsign] != '.' && !isdigit(s[withsign])) goto bad; - *lat = strtod(s, &s); + *lat = strtod(s, (char **)(void *)&s); if (errno) return -1; if (!withsign && (s[0] == 'N' || s[0] == 'S')) { @@ -155,7 +155,7 @@ parse_coord(char *s, double *lat, double *lon) withsign = (s[0] == '-' || s[0] == '+'); if (s[withsign] != '.' && !isdigit(s[withsign])) goto bad; - *lon = strtod(s, &s); + *lon = strtod(s, (char **)(void *)&s); if (errno) return -1; if (!withsign && (s[0] == 'E' || s[0] == 'W')) { @@ -177,7 +177,7 @@ bad: int -libcontacts_parse_contact(char *data, struct libcontacts_contact *contact) +libcontacts_parse_contact(char *data, struct libcontacts_contact *contactp) { #define TEST(S, L)\ (!strncmp((test_tmp = (S)), L, sizeof(L) - 1) &&\ @@ -208,258 +208,261 @@ libcontacts_parse_contact(char *data, struct libcontacts_contact *contact) int state = 0; unsigned int u; unsigned char uc; + char c = 0; - memset(contact, 0, sizeof(*contact)); + memset(contactp, 0, sizeof(*contactp)); - for (p = data; p; p = q) { + for (p = data; p; p = q ? (*q = c, &q[1]) : NULL) { q = strpbrk(p, "\n\r\f"); - if (q) - *q++ = '\0'; + if (q) { + c = *q; + *q = '\0'; + } switch ((*p == ' ' || *p == '\t') ? state : 0) { default: state = 0; if (!*p); - else if (TEST(p, "NAME") && !contact->name) { - if (!(contact->name = strdup(getstr(p)))) + else if (TEST(p, "NAME") && !contactp->name) { + if (!(contactp->name = strdup(getstr(p)))) goto fail; - } else if (TEST(p, "FNAME") && !contact->first_name) { - if (!(contact->first_name = strdup(getstr(p)))) + } else if (TEST(p, "FNAME") && !contactp->first_name) { + if (!(contactp->first_name = strdup(getstr(p)))) goto fail; - } else if (TEST(p, "LNAME") && !contact->last_name) { - if (!(contact->last_name = strdup(getstr(p)))) + } else if (TEST(p, "LNAME") && !contactp->last_name) { + if (!(contactp->last_name = strdup(getstr(p)))) goto fail; - } else if (TEST(p, "FLNAME") && !contact->full_name) { - if (!(contact->full_name = strdup(getstr(p)))) + } else if (TEST(p, "FLNAME") && !contactp->full_name) { + if (!(contactp->full_name = strdup(getstr(p)))) goto fail; - } else if (TEST(p, "NICK") && !contact->nickname) { - if (!(contact->nickname = strdup(getstr(p)))) + } else if (TEST(p, "NICK") && !contactp->nickname) { + if (!(contactp->nickname = strdup(getstr(p)))) goto fail; } else if (TEST(p, "PHOTO")) { - if (addstr(&contact->photos, getstr(p))) + if (addstr(&contactp->photos, getstr(p))) goto fail; } else if (TEST(p, "GROUP")) { - if (addstr(&contact->groups, getstr(p))) + if (addstr(&contactp->groups, getstr(p))) goto fail; } else if (TEST(p, "NOTES")) { - if (appendstr(&contact->notes, getstr(p))) + if (appendstr(&contactp->notes, getstr(p))) goto fail; } else if (!strcmp(p, "ORG:")) { - ADD(contact->organisations); + ADD(contactp->organisations); state = 1; break; case 1: - if (TEST(unindent(p), "ORG") && !contact->organisations[i]->organisation) { - if (!(contact->organisations[i]->organisation = strdup(getstr(p)))) + if (TEST(unindent(p), "ORG") && !contactp->organisations[i]->organisation) { + if (!(contactp->organisations[i]->organisation = strdup(getstr(p)))) goto fail; - } else if (TEST(unindent(p), "TITLE") && !contact->organisations[i]->title) { - if (!(contact->organisations[i]->title = strdup(getstr(p)))) + } else if (TEST(unindent(p), "TITLE") && !contactp->organisations[i]->title) { + if (!(contactp->organisations[i]->title = strdup(getstr(p)))) goto fail; } else { - if (addstr(&contact->organisations[i]->unrecognised_data, unindent(p))) + if (addstr(&contactp->organisations[i]->unrecognised_data, unindent(p))) goto fail; } break; } else if (!strcmp(p, "EMAIL:")) { - ADD(contact->emails); + ADD(contactp->emails); state = 2; break; case 2: - if (TEST(unindent(p), "CTX") && !contact->emails[i]->context) { - if (!(contact->emails[i]->context = strdup(getstr(p)))) + if (TEST(unindent(p), "CTX") && !contactp->emails[i]->context) { + if (!(contactp->emails[i]->context = strdup(getstr(p)))) goto fail; - } else if (TEST(unindent(p), "ADDR") && !contact->emails[i]->address) { - if (!(contact->emails[i]->address = strdup(getstr(p)))) + } else if (TEST(unindent(p), "ADDR") && !contactp->emails[i]->address) { + if (!(contactp->emails[i]->address = strdup(getstr(p)))) goto fail; } else { - if (addstr(&contact->emails[i]->unrecognised_data, unindent(p))) + if (addstr(&contactp->emails[i]->unrecognised_data, unindent(p))) goto fail; } break; } else if (!strcmp(p, "KEY:")) { - ADD(contact->pgpkeys); + ADD(contactp->pgpkeys); state = 3; break; case 3: - if (TEST(unindent(p), "CTX") && !contact->pgpkeys[i]->context) { - if (!(contact->pgpkeys[i]->context = strdup(getstr(p)))) + if (TEST(unindent(p), "CTX") && !contactp->pgpkeys[i]->context) { + if (!(contactp->pgpkeys[i]->context = strdup(getstr(p)))) goto fail; - } else if (TEST(unindent(p), "ID") && !contact->pgpkeys[i]->id) { - if (!(contact->pgpkeys[i]->id = strdup(getstr(p)))) + } else if (TEST(unindent(p), "ID") && !contactp->pgpkeys[i]->id) { + if (!(contactp->pgpkeys[i]->id = strdup(getstr(p)))) goto fail; } else { - if (addstr(&contact->pgpkeys[i]->unrecognised_data, unindent(p))) + if (addstr(&contactp->pgpkeys[i]->unrecognised_data, unindent(p))) goto fail; } break; } else if (!strcmp(p, "PHONE:")) { - ADD(contact->numbers); + ADD(contactp->numbers); state = 4; break; case 4: - if (TEST(unindent(p), "CTX") && !contact->numbers[i]->context) { - if (!(contact->numbers[i]->context = strdup(getstr(p)))) + if (TEST(unindent(p), "CTX") && !contactp->numbers[i]->context) { + if (!(contactp->numbers[i]->context = strdup(getstr(p)))) goto fail; - } else if (TEST(unindent(p), "NUMBER") && !contact->numbers[i]->number) { - if (!(contact->numbers[i]->number = strdup(getstr(p)))) + } else if (TEST(unindent(p), "NUMBER") && !contactp->numbers[i]->number) { + if (!(contactp->numbers[i]->number = strdup(getstr(p)))) goto fail; } else if (!strcmp(unindent(p), "MOBILE")) { - contact->numbers[i]->is_mobile = 1; + contactp->numbers[i]->is_mobile = 1; } else if (!strcmp(unindent(p), "FAX")) { - contact->numbers[i]->is_facsimile = 1; + contactp->numbers[i]->is_facsimile = 1; } else { - if (addstr(&contact->numbers[i]->unrecognised_data, unindent(p))) + if (addstr(&contactp->numbers[i]->unrecognised_data, unindent(p))) goto fail; } break; } else if (!strcmp(p, "ADDR:")) { - ADD(contact->addresses); + ADD(contactp->addresses); state = 5; break; case 5: - if (TEST(unindent(p), "CTX") && !contact->addresses[i]->context) { - if (!(contact->addresses[i]->context = strdup(getstr(p)))) + if (TEST(unindent(p), "CTX") && !contactp->addresses[i]->context) { + if (!(contactp->addresses[i]->context = strdup(getstr(p)))) goto fail; - } else if (TEST(unindent(p), "COUNTRY") && !contact->addresses[i]->country) { - if (!(contact->addresses[i]->country = strdup(getstr(p)))) + } else if (TEST(unindent(p), "COUNTRY") && !contactp->addresses[i]->country) { + if (!(contactp->addresses[i]->country = strdup(getstr(p)))) goto fail; - } else if (TEST(unindent(p), "C/O") && !contact->addresses[i]->care_of) { - if (!(contact->addresses[i]->care_of = strdup(getstr(p)))) + } else if (TEST(unindent(p), "C/O") && !contactp->addresses[i]->care_of) { + if (!(contactp->addresses[i]->care_of = strdup(getstr(p)))) goto fail; - } else if (TEST(unindent(p), "ADDR") && !contact->addresses[i]->address) { - if (!(contact->addresses[i]->address = strdup(getstr(p)))) + } else if (TEST(unindent(p), "ADDR") && !contactp->addresses[i]->address) { + if (!(contactp->addresses[i]->address = strdup(getstr(p)))) goto fail; - } else if (TEST(unindent(p), "CODE") && !contact->addresses[i]->postcode) { - if (!(contact->addresses[i]->postcode = strdup(getstr(p)))) + } else if (TEST(unindent(p), "CODE") && !contactp->addresses[i]->postcode) { + if (!(contactp->addresses[i]->postcode = strdup(getstr(p)))) goto fail; - } else if (TEST(unindent(p), "CITY") && !contact->addresses[i]->city) { - if (!(contact->addresses[i]->city = strdup(getstr(p)))) + } else if (TEST(unindent(p), "CITY") && !contactp->addresses[i]->city) { + if (!(contactp->addresses[i]->city = strdup(getstr(p)))) goto fail; - } else if (TEST(unindent(p), "COORD") && !contact->addresses[i]->have_coordinates) { + } else if (TEST(unindent(p), "COORD") && !contactp->addresses[i]->have_coordinates) { if (!parse_coord(getstr(p), - &contact->addresses[i]->latitude, - &contact->addresses[i]->longitude)) { - contact->addresses[i]->have_coordinates = 1; + &contactp->addresses[i]->latitude, + &contactp->addresses[i]->longitude)) { + contactp->addresses[i]->have_coordinates = 1; } else { - if (addstr(&contact->addresses[i]->unrecognised_data, unindent(p))) + if (addstr(&contactp->addresses[i]->unrecognised_data, unindent(p))) goto fail; } } else { - if (addstr(&contact->addresses[i]->unrecognised_data, unindent(p))) + if (addstr(&contactp->addresses[i]->unrecognised_data, unindent(p))) goto fail; } break; } else if (!strcmp(p, "SITE:")) { - ADD(contact->sites); + ADD(contactp->sites); state = 6; break; case 6: - if (TEST(unindent(p), "CTX") && !contact->sites[i]->context) { - if (!(contact->sites[i]->context = strdup(getstr(p)))) + if (TEST(unindent(p), "CTX") && !contactp->sites[i]->context) { + if (!(contactp->sites[i]->context = strdup(getstr(p)))) goto fail; - } else if (TEST(unindent(p), "ADDR") && !contact->sites[i]->address) { - if (!(contact->sites[i]->address = strdup(getstr(p)))) + } else if (TEST(unindent(p), "ADDR") && !contactp->sites[i]->address) { + if (!(contactp->sites[i]->address = strdup(getstr(p)))) goto fail; } else { - if (addstr(&contact->sites[i]->unrecognised_data, unindent(p))) + if (addstr(&contactp->sites[i]->unrecognised_data, unindent(p))) goto fail; } break; } else if (!strcmp(p, "CHAT:")) { - ADD(contact->chats); + ADD(contactp->chats); state = 7; break; case 7: - if (TEST(unindent(p), "CTX") && !contact->chats[i]->context) { - if (!(contact->chats[i]->context = strdup(getstr(p)))) + if (TEST(unindent(p), "CTX") && !contactp->chats[i]->context) { + if (!(contactp->chats[i]->context = strdup(getstr(p)))) goto fail; - } else if (TEST(unindent(p), "SRV") && !contact->chats[i]->service) { - if (!(contact->chats[i]->service = strdup(getstr(p)))) + } else if (TEST(unindent(p), "SRV") && !contactp->chats[i]->service) { + if (!(contactp->chats[i]->service = strdup(getstr(p)))) goto fail; - } else if (TEST(unindent(p), "ADDR") && !contact->chats[i]->address) { - if (!(contact->chats[i]->address = strdup(getstr(p)))) + } else if (TEST(unindent(p), "ADDR") && !contactp->chats[i]->address) { + if (!(contactp->chats[i]->address = strdup(getstr(p)))) goto fail; } else { - if (addstr(&contact->chats[i]->unrecognised_data, unindent(p))) + if (addstr(&contactp->chats[i]->unrecognised_data, unindent(p))) goto fail; } break; } else if (!strcmp(p, "BLOCK:")) { - ADD(contact->blocks); + ADD(contactp->blocks); state = 8; break; case 8: - if (TEST(unindent(p), "SRV") && !contact->blocks[i]->service) { - if (!(contact->blocks[i]->service = strdup(getstr(p)))) + if (TEST(unindent(p), "SRV") && !contactp->blocks[i]->service) { + if (!(contactp->blocks[i]->service = strdup(getstr(p)))) goto fail; - } else if (!strcmp(unindent(p), "OFF") && !contact->blocks[i]->shadow_block) { - contact->blocks[i]->shadow_block = LIBCONTACTS_BLOCK_OFF; - } else if (!strcmp(unindent(p), "BUSY") && !contact->blocks[i]->shadow_block) { - contact->blocks[i]->shadow_block = LIBCONTACTS_BLOCK_BUSY; - } else if (!strcmp(unindent(p), "IGNORE") && !contact->blocks[i]->shadow_block) { - contact->blocks[i]->shadow_block = LIBCONTACTS_BLOCK_IGNORE; + } else if (!strcmp(unindent(p), "OFF") && !contactp->blocks[i]->shadow_block) { + contactp->blocks[i]->shadow_block = LIBCONTACTS_BLOCK_OFF; + } else if (!strcmp(unindent(p), "BUSY") && !contactp->blocks[i]->shadow_block) { + contactp->blocks[i]->shadow_block = LIBCONTACTS_BLOCK_BUSY; + } else if (!strcmp(unindent(p), "IGNORE") && !contactp->blocks[i]->shadow_block) { + contactp->blocks[i]->shadow_block = LIBCONTACTS_BLOCK_IGNORE; } else if (!strcmp(unindent(p), "EXPLICIT")) { - contact->blocks[i]->explicit = 1; - } else if (TEST(unindent(p), "ASK") && !contact->blocks[i]->soft_unblock && (t = gettime(p))) { - contact->blocks[i]->soft_unblock = t; - } else if (TEST(unindent(p), "REMOVE") && !contact->blocks[i]->hard_unblock && (t = gettime(p))) { - contact->blocks[i]->hard_unblock = t; + contactp->blocks[i]->explicit = 1; + } else if (TEST(unindent(p), "ASK") && !contactp->blocks[i]->soft_unblock && (t = gettime(p))) { + contactp->blocks[i]->soft_unblock = t; + } else if (TEST(unindent(p), "REMOVE") && !contactp->blocks[i]->hard_unblock && (t = gettime(p))) { + contactp->blocks[i]->hard_unblock = t; } else { - if (addstr(&contact->blocks[i]->unrecognised_data, unindent(p))) + if (addstr(&contactp->blocks[i]->unrecognised_data, unindent(p))) goto fail; } break; - } else if (!strcmp(p, "BIRTH:") && !contact->birthday) { - contact->birthday = calloc(1, sizeof(*contact->birthday)); - if (!contact->birthday) + } else if (!strcmp(p, "BIRTH:") && !contactp->birthday) { + contactp->birthday = calloc(1, sizeof(*contactp->birthday)); + if (!contactp->birthday) goto fail; state = 9; break; case 9: - if (TEST(unindent(p), "YEAR") && !contact->birthday->year && (u = getposuint(p))) { - contact->birthday->year = u; - } else if (TEST(unindent(p), "MONTH") && !contact->birthday->month && (uc = getposuchar(p))) { - contact->birthday->month = uc; - } else if (TEST(unindent(p), "DAY") && !contact->birthday->day && (uc = getposuchar(p))) { - contact->birthday->day = uc; + if (TEST(unindent(p), "YEAR") && !contactp->birthday->year && (u = getposuint(p))) { + contactp->birthday->year = u; + } else if (TEST(unindent(p), "MONTH") && !contactp->birthday->month && (uc = getposuchar(p))) { + contactp->birthday->month = uc; + } else if (TEST(unindent(p), "DAY") && !contactp->birthday->day && (uc = getposuchar(p))) { + contactp->birthday->day = uc; } else if (!strcmp(unindent(p), "EARLY")) { - contact->birthday->before_on_common = 1; + contactp->birthday->before_on_common = 1; } else { - if (addstr(&contact->birthday->unrecognised_data, unindent(p))) + if (addstr(&contactp->birthday->unrecognised_data, unindent(p))) goto fail; } break; } else if (!strcmp(p, "ICE")) { - contact->in_case_of_emergency = 1; + contactp->in_case_of_emergency = 1; - } else if (!strcmp(p, "NPERSON") && !contact->gender) { - contact->gender = LIBCONTACTS_NOT_A_PERSON; + } else if (!strcmp(p, "NPERSON") && !contactp->gender) { + contactp->gender = LIBCONTACTS_NOT_A_PERSON; - } else if (!strcmp(p, "MALE") && !contact->gender) { - contact->gender = LIBCONTACTS_MALE; + } else if (!strcmp(p, "MALE") && !contactp->gender) { + contactp->gender = LIBCONTACTS_MALE; - } else if (!strcmp(p, "FEMALE") && !contact->gender) { - contact->gender = LIBCONTACTS_FEMALE; + } else if (!strcmp(p, "FEMALE") && !contactp->gender) { + contactp->gender = LIBCONTACTS_FEMALE; } else { - if (addstr(&contact->unrecognised_data, p)) + if (addstr(&contactp->unrecognised_data, p)) goto fail; } } @@ -468,8 +471,8 @@ libcontacts_parse_contact(char *data, struct libcontacts_contact *contact) return 0; fail: - libcontacts_contact_destroy(contact); - memset(contact, 0, sizeof(*contact)); + libcontacts_contact_destroy(contactp); + memset(contactp, 0, sizeof(*contactp)); return -1; #undef TEST diff --git a/libcontacts_pgpkey_destroy.3 b/libcontacts_pgpkey_destroy.3 new file mode 100644 index 0000000..2e88507 --- /dev/null +++ b/libcontacts_pgpkey_destroy.3 @@ -0,0 +1,34 @@ +.TH LIBCONTACTS_PGP_DESTROY 3 LIBCONTACTS +.SH NAME +libcontacts_pgp_destroy \- Deallocate memory for a contact PGP-key fingerprint entry +.SH SYNOPSIS +.nf +#include <libcontacts.h> + +int libcontacts_pgp_destroy(struct libcontacts_pgp *\fIentry\fP); +.fi +.PP +Link with +.IR -lcontacts . + +.SH DESCRIPTION +The +.BR libcontacts_pgp_destroy () +function deallocates the memory stored in +.IR *entry . +The caller must manually call +.BR free (3) +on the pointer +.I entry +afterwards if it a freeable pointer. + +.SH RETURN VALUE +None. + +.SH ERRORS +None. + +.SH SEE ALSO +.BR libcontacts.h (0), +.BR libcontacts (7), +.BR libcontacts_contact_destroy (3) diff --git a/libcontacts_same_number.3 b/libcontacts_same_number.3 new file mode 100644 index 0000000..3b30a89 --- /dev/null +++ b/libcontacts_same_number.3 @@ -0,0 +1,74 @@ +.TH LIBCONTACTS_SAME_NUMBER 3 LIBCONTACTS +.SH NAME +libcontacts_same_number \- Save a contact +.SH SYNOPSIS +.nf +#include <libcontacts.h> + +int libcontacts_same_number(const char *\fIa\fP, const char *\fIa_country\fP, const char *\fIb\fP, const char *\fIb_country\fP); +.fi +.PP +Link with +.IR -lcontacts . + +.SH DESCRIPTION +The +.BR libcontacts_same_number () +function checks whether the telephone numbers specified +in the +.I a +and +.I b +parameters are the same number. +.PP +The country calling code for +.I a +and +.I b +may be specified in the +.I a_country +and +.I b_country +parameters respectively. If the empty string is specified +as a country calling code, it is treated as unspecified. +.B \(dq00\(dq +will be added automatically if it, or its alternative +.B \(dq+\(dq +is missing. + +.SH RETURN VALUE +The +.BR libcontacts_same_number () +function returns 1 or 0 upon successful completion; +otherwise -1 is returned and +.I errno +is set appropriately to indicate the error. +If the returned value is 1, the numbers match, +if the returned value is 0, the numbers do not match. + +.SH ERRORS +The +.BR libcontacts_same_number () +function will fail if: +.TP +.B EINVAL +The +.I a +or +.I b +is +.I NULL +or the empty string. +.PP +The +.BR libcontacts_same_number () +function may fail for any reason specified for the +.BR malloc (3) +function. + +.SH FUTURE DIRECTIONS +This function may be removed in the future. + +.SH SEE ALSO +.BR libcontacts.h (0), +.BR libcontacts (7) diff --git a/libcontacts_save_contact.3 b/libcontacts_save_contact.3 new file mode 100644 index 0000000..161e190 --- /dev/null +++ b/libcontacts_save_contact.3 @@ -0,0 +1,78 @@ +.TH LIBCONTACTS_SAVE_CONTACT 3 LIBCONTACTS +.SH NAME +libcontacts_save_contact \- Save a contact +.SH SYNOPSIS +.nf +#include <libcontacts.h> + +int libcontacts_save_contact(struct libcontacts_contact *\fIcontact\fP, const struct passwd *\fIuser\fP); +.fi +.PP +Link with +.IR -lcontacts . + +.SH DESCRIPTION +The +.BR libcontacts_save_contact () +function saves the contact entry that is specified in the +.I contact +parameter. +.PP +If +.I contact->id +is +.I NULL +an ID will be assigned to it, and stored in +.IR contact->id . +If the call is successful, the caller must manually +free this ID, if the function +assignee's it, using the +.BR free (3) +function. +.PP +.I user +shall be the user's entry in the password database (not +the shadow database). This is used for the get user's +home directory. + +.SH RETURN VALUE +The +.BR libcontacts_save_contact () +function returns 0 upon successful completion; +otherwise -1 is returned and +.I errno +is set appropriately to indicate the error. + +.SH ERRORS +The +.BR libcontacts_save_contact () +function will fail if: +.TP +.B 0 +The file it saves contains a NUL byte. +.PP +The +.BR libcontacts_save_contact () +function may fail for any reason specified for the +.BR libcontacts_format_contact (3), +.BR libcontacts_get_path (3), +.BR malloc (3), +.BR open (3) +(other than +.IR EEXIST ), +.BR mkdir (3) +(other than +.IR EEXIST ), +.BR write (3), +.BR fsync (3), +and +.BR rename (3) +functions. + +.SH SEE ALSO +.BR libcontacts.h (0), +.BR libcontacts (7), +.BR libcontacts_load_contact (3), +.BR libcontacts_loads_contact (3), +.BR libcontacts_contact_destroy (3), +.BR libcontacts_format_contact (3) diff --git a/libcontacts_save_contact.c b/libcontacts_save_contact.c index b373a46..6c653f9 100644 --- a/libcontacts_save_contact.c +++ b/libcontacts_save_contact.c @@ -32,7 +32,7 @@ int libcontacts_save_contact(struct libcontacts_contact *contact, const struct passwd *user) { char *data = NULL, *path = NULL, *tmppath = NULL; - int oflags = O_WRONLY | O_CREAT | O_TRUNC; + int oflags = O_WRONLY | O_CREAT | O_TRUNC, newid = 0; int fd = -1, saved_errno = errno, dirs_created = 0; ssize_t r; size_t p, n, num = 0; @@ -49,10 +49,12 @@ libcontacts_save_contact(struct libcontacts_contact *contact, const struct passw contact->id = strdup("unnamed"); if (!contact->id) goto fail; + newid = 1; } else { contact->id = strdup(contact->name); if (!contact->id) goto fail; + newid = 1; for (p = 0; contact->id[p]; p++) { if (isalpha(contact->id[p])) contact->id[p] = (char)tolower(contact->id[p]); @@ -147,6 +149,10 @@ fail: free(path); free(tmppath); free(basenam); + if (newid) { + free(contact->id); + contact->id = NULL; + } errno = saved_errno; return -1; } diff --git a/libcontacts_site_destroy.3 b/libcontacts_site_destroy.3 new file mode 100644 index 0000000..5e4a0ac --- /dev/null +++ b/libcontacts_site_destroy.3 @@ -0,0 +1,34 @@ +.TH LIBCONTACTS_SITE_DESTROY 3 LIBCONTACTS +.SH NAME +libcontacts_site_destroy \- Deallocate memory for a contact Internet site entry +.SH SYNOPSIS +.nf +#include <libcontacts.h> + +int libcontacts_site_destroy(struct libcontacts_site *\fIentry\fP); +.fi +.PP +Link with +.IR -lcontacts . + +.SH DESCRIPTION +The +.BR libcontacts_site_destroy () +function deallocates the memory stored in +.IR *entry . +The caller must manually call +.BR free (3) +on the pointer +.I entry +afterwards if it a freeable pointer. + +.SH RETURN VALUE +None. + +.SH ERRORS +None. + +.SH SEE ALSO +.BR libcontacts.h (0), +.BR libcontacts (7), +.BR libcontacts_contact_destroy (3) @@ -99,6 +99,7 @@ main(void) /* TODO test libcontacts_load_contacts */ /* TODO test libcontacts_format_contact */ /* TODO test libcontacts_save_contact */ + /* TODO test libcontacts_contact_destroy */ /* TODO check for memory leaks */ /* TODO check for file descriptor leaks */ |