/* Public domain. */ /* #define _POSIX_C_SOURCE 2 */ #include #include #include #include #include #include #include #define PATH_OFFSET offsetof(struct sockaddr_un, sun_path) static int die(char *message) { perror(message); exit(1); } static void usage(const char *name) { printf("\ Usage: %s [options] \n\ \n\ Listen on a Unix domain socket at and for each accepted connection,\n\ print:\n\ \n\ - the length of the value in sun_path, as determined from the address\n\ length returned by accept()\n\ - the contents of sun_path up to that length, or to the length passed to\n\ accept(), whichever is smaller\n\ - the entire contents of the sun_path buffer\n\ \n\ The sun_path buffer is initially filled with the '=' character, and any null\n\ characters in the returned value are replaced with the '@' character.\n\ \n\ Options:\n\ \n\ -l N Call accept() with a sun_path buffer of size N, instead of the\n\ standard size.\n\ \n\ -b N Allocate the address buffer with a sun_path length of N, rather\n\ than the size which will be passed to accept().\n\ \n", name); exit(1); } int main(int argc, char *argv[]) { int listenfd, connfd; struct sockaddr_un *peeraddrp; struct sockaddr_un bindaddr; socklen_t realsize, acceptsize; int c; long i, peerlen, reallen = -1, acceptlen = -1; while ((c = getopt(argc, argv, "hl:b:")) != -1) { switch (c) { case 'l': acceptlen = atol(optarg); break; case 'b': reallen = atol(optarg); break; case 'h': case '?': usage(argv[0]); break; } } if (argc - optind != 1) usage(argv[0]); if (acceptlen < 0) acceptlen = sizeof(peeraddrp->sun_path); if (reallen < 0) reallen = acceptlen; memset(&bindaddr, 0, sizeof(bindaddr)); bindaddr.sun_family = AF_UNIX; strncpy(bindaddr.sun_path, argv[optind], sizeof(bindaddr.sun_path)); unlink(argv[optind]); if ((listenfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) die("socket"); if (bind(listenfd, (struct sockaddr *)&bindaddr, sizeof(bindaddr))) die("bind"); if (listen(listenfd, 1)) die("listen"); realsize = PATH_OFFSET + reallen; if (!(peeraddrp = malloc(realsize))) die("malloc"); for (;;) { memset(peeraddrp, 0, PATH_OFFSET); memset(peeraddrp->sun_path, '=', reallen); peeraddrp->sun_family = AF_UNIX; acceptsize = PATH_OFFSET + acceptlen; printf("Calling accept() with addrlen=%ld " "(sun_path size %ld)...\n", (long)acceptsize, (long)(acceptsize - PATH_OFFSET)); if ((connfd=accept(listenfd, (struct sockaddr *)peeraddrp, &acceptsize)) < 0) die("accept"); peerlen = acceptsize - PATH_OFFSET; printf("Received addrlen=%ld (sun_path size %ld)\n", (long)acceptsize, peerlen); for (i = 0; i < reallen; i++) if (peeraddrp->sun_path[i] == 0) peeraddrp->sun_path[i] = '@'; printf("%.*s\n", (int)(peerlen <= acceptlen ? peerlen : acceptlen), peeraddrp->sun_path); printf("%.*s\n", (int)reallen, peeraddrp->sun_path); close(connfd); } }

AltStyle によって変換されたページ (->オリジナル) /