423 * process get terminated. */ |
423 * process get terminated. */ |
424 fsetcloexec(fd); |
424 fsetcloexec(fd); |
425 |
425 |
426 struct sockaddr_un addr; |
426 struct sockaddr_un addr; |
427 addr.sun_family = AF_UNIX; |
427 addr.sun_family = AF_UNIX; |
428 strncpy(addr.sun_path, sockname, sizeof(addr.sun_path)); |
428 |
|
429 /* use chdir to workaround small sizeof(sun_path) */ |
|
430 int bakfd = -1; |
|
431 const char *basename = sockname; |
|
432 { |
|
433 const char *split = strrchr(sockname, '/'); |
|
434 if (split && split != sockname) { |
|
435 if (split[1] == '\0') |
|
436 abortmsg("sockname cannot end with a slash"); |
|
437 size_t len = split - sockname; |
|
438 char sockdir[len + 1]; |
|
439 memcpy(sockdir, sockname, len); |
|
440 sockdir[len] = '\0'; |
|
441 |
|
442 bakfd = open(".", O_DIRECTORY); |
|
443 if (bakfd == -1) |
|
444 abortmsgerrno("cannot open cwd"); |
|
445 |
|
446 int r = chdir(sockdir); |
|
447 if (r != 0) |
|
448 abortmsgerrno("cannot chdir %s", sockdir); |
|
449 |
|
450 basename = split + 1; |
|
451 } |
|
452 } |
|
453 if (strlen(basename) >= sizeof(addr.sun_path)) |
|
454 abortmsg("sockname is too long: %s", basename); |
|
455 strncpy(addr.sun_path, basename, sizeof(addr.sun_path)); |
429 addr.sun_path[sizeof(addr.sun_path) - 1] = '\0'; |
456 addr.sun_path[sizeof(addr.sun_path) - 1] = '\0'; |
430 |
457 |
|
458 /* real connect */ |
431 int r = connect(fd, (struct sockaddr *)&addr, sizeof(addr)); |
459 int r = connect(fd, (struct sockaddr *)&addr, sizeof(addr)); |
|
460 if (bakfd != -1) { |
|
461 fchdirx(bakfd); |
|
462 close(bakfd); |
|
463 } |
|
464 |
432 if (r < 0) { |
465 if (r < 0) { |
433 close(fd); |
466 close(fd); |
434 if (errno == ENOENT || errno == ECONNREFUSED) |
467 if (errno == ENOENT || errno == ECONNREFUSED) |
435 return NULL; |
468 return NULL; |
436 abortmsgerrno("cannot connect to %s", addr.sun_path); |
469 abortmsgerrno("cannot connect to %s", addr.sun_path); |