Index: uspace/app/contacts/contacts.c
===================================================================
--- uspace/app/contacts/contacts.c	(revision 7b87e1de3c9d777545389f4237d360d8ed0a9bf5)
+++ uspace/app/contacts/contacts.c	(revision 233a3a060e7a6264a136f0c102aaf29af13ae491)
@@ -58,6 +58,12 @@
 /** Contact entry */
 typedef struct {
-	/** Link to contacts_t.entries */
+	/** Containing contacts */
+	contacts_t *contacts;
+	/** Link to contacts->entries */
 	link_t lentries;
+	/** SIF node for this entry */
+	sif_node_t *nentry;
+	/** Contact name */
+	char *name;
 } contacts_entry_t;
 
@@ -71,4 +77,6 @@
 	ac_exit
 } contact_action_t;
+
+static errno_t contacts_unmarshal(sif_node_t *, contacts_t *);
 
 /** Open contacts repo or create it if it does not exist.
@@ -139,4 +147,8 @@
 		}
 
+		rc = contacts_unmarshal(node, contacts);
+		if (rc != EOK)
+			goto error;
+
 		contacts->nentries = node;
 	}
@@ -156,4 +168,50 @@
 }
 
+/** Unmarshal contact entries from SIF repository.
+ *
+ * @param nentries Entries node
+ * @param contacts Contacts object to unmarshal to
+ * @return EOK on success or error code
+ */
+static errno_t contacts_unmarshal(sif_node_t *nentries, contacts_t *contacts)
+{
+	sif_node_t *nentry;
+	contacts_entry_t *entry;
+	const char *name;
+
+	contacts->nentries = nentries;
+
+	nentry = sif_node_first_child(nentries);
+	while (nentry != NULL) {
+		if (str_cmp(sif_node_get_type(nentry), "entry") != 0)
+			return EIO;
+
+		entry = calloc(1, sizeof(contacts_entry_t));
+		if (entry == NULL)
+			return ENOMEM;
+
+		name = sif_node_get_attr(nentry, "name");
+		if (name == NULL) {
+			free(entry);
+			return EIO;
+		}
+
+		entry->name = str_dup(name);
+		if (entry->name == NULL) {
+			free(entry);
+			return ENOMEM;
+		}
+
+		entry->contacts = contacts;
+		entry->nentry = nentry;
+		list_append(&entry->lentries, &contacts->entries);
+
+		nentry = sif_node_next_child(nentry);
+	}
+
+	return EOK;
+}
+
+
 /** Interaction to create new contact.
  *
@@ -165,4 +223,5 @@
 	sif_trans_t *trans = NULL;
 	sif_node_t *nentry;
+	contacts_entry_t *entry = NULL;
 	errno_t rc;
 	char *cname = NULL;
@@ -182,4 +241,10 @@
 		goto error;
 
+	entry = calloc(1, sizeof(contacts_entry_t));
+	if (entry == NULL) {
+		rc = ENOMEM;
+		goto error;
+	}
+
 	rc = sif_trans_begin(contacts->repo, &trans);
 	if (rc != EOK)
@@ -199,6 +264,9 @@
 
 	trans = NULL;
-
-	free(cname);
+	entry->contacts = contacts;
+	entry->nentry = nentry;
+	entry->name = cname;
+	list_append(&entry->lentries, &contacts->entries);
+
 	tinput_destroy(tinput);
 	return EOK;
@@ -208,4 +276,6 @@
 	if (cname != NULL)
 		free(cname);
+	if (entry != NULL)
+		free(entry);
 	return rc;
 }
@@ -229,4 +299,51 @@
 	sif_close(contacts->repo);
 	free(contacts);
+}
+
+/** Get first contacts entry.
+ *
+ * @param contacts Contacts
+ * @return First entry or @c NULL if there is none
+ */
+static contacts_entry_t *contacts_first(contacts_t *contacts)
+{
+	link_t *link;
+
+	link = list_first(&contacts->entries);
+	if (link == NULL)
+		return NULL;
+
+	return list_get_instance(link, contacts_entry_t, lentries);
+}
+
+/** Get next contacts entry.
+ *
+ * @param cur Current entry
+ * @return Next entry or @c NULL if there is none
+ */
+static contacts_entry_t *contacts_next(contacts_entry_t *cur)
+{
+	link_t *link;
+
+	link = list_next(&cur->lentries, &cur->contacts->entries);
+	if (link == NULL)
+		return NULL;
+
+	return list_get_instance(link, contacts_entry_t, lentries);
+}
+
+/** List all contacts.
+ *
+ * @param contacts Contacts
+ */
+static void contacts_list_all(contacts_t *contacts)
+{
+	contacts_entry_t *entry;
+
+	entry = contacts_first(contacts);
+	while (entry != NULL) {
+		printf(" * %s\n", entry->name);
+		entry = contacts_next(entry);
+	}
 }
 
@@ -282,4 +399,6 @@
 
 	while (!quit) {
+		contacts_list_all(contacts);
+
 		rc = nchoice_get(choice, &sel);
 		if (rc != EOK) {
