/**
 *
 * to build 
 *
 *   $ gcc -Wall -O2 unix-getsockname.c -o unix-getsocketname && ./unix-getsocketname
 *
 * should display
 * 
 *   our family:   1 
 *   their family: 1
 */

#include <sys/types.h>
#include <sys/un.h>
#include <sys/socket.h>
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <assert.h>
#include <string.h>

#define C(x) x

void *s(void *naaa) {
	int fd, cfd;
	struct sockaddr_un addr;
	struct sockaddr_un caddr;
	socklen_t addr_len = sizeof(addr);
	socklen_t caddr_len = sizeof(caddr);
	char b[2];

	unlink( C("/tmp/foobar.socket") );
	assert(-1 != (fd = socket(AF_UNIX, SOCK_STREAM, 0)));
	addr.sun_len = sizeof(addr);
	addr.sun_family = AF_UNIX;
	strcpy(addr.sun_path, C("/tmp/foobar.socket"));
	if (0 != bind(fd, (struct sockaddr *)&addr, addr_len)) {
		perror(__FILE__);
	}
	listen(fd, 128);
	if (-1 == (cfd = accept(fd, (struct sockaddr *)&caddr, &caddr_len))) {
		perror(__FILE__);
	}
	read(cfd, b, 1);
	close(cfd);

	close(fd);

	return NULL;
}

int main() {
	struct sockaddr_un addr;
	struct sockaddr    naddr;
	socklen_t addr_len = sizeof(addr);
	socklen_t naddr_len;
	int fd;
	char b[2] = ".";
	pthread_t t;

	assert(0 == pthread_create(&t, NULL, s, NULL));

	sleep(1);

	assert(-1 != (fd = socket(AF_UNIX, SOCK_STREAM, 0)));

	addr.sun_len = sizeof(addr);
	addr.sun_family = AF_UNIX;
	strcpy(addr.sun_path, C("/tmp/foobar.socket"));

	if (-1 == (connect(fd, (struct sockaddr *)&addr, addr_len))) {
		perror(__FILE__);
	}

	naddr_len = sizeof(naddr);
	assert(-1 != getsockname(fd, &naddr, &naddr_len));
	printf("our family: %d\n", naddr.sa_family);
	naddr_len = sizeof(naddr);
	assert(-1 != getpeername(fd, &naddr, &naddr_len));
	printf("their family: %d\n", naddr.sa_family);

	write(fd, b, 1);

	close(fd);

	return 0;
}
