rcmd.c 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. /* posix */
  2. #include <sys/types.h>
  3. #include <unistd.h>
  4. #include <stdlib.h>
  5. #include <stdio.h>
  6. #include <string.h>
  7. #include <errno.h>
  8. #include <signal.h>
  9. /* socket extensions */
  10. #include <sys/socket.h>
  11. #include <netinet/in.h>
  12. #include <sys/un.h>
  13. #include <netdb.h>
  14. #include "priv.h"
  15. static char pbotch[] = "rcmd: protocol botch\n";
  16. static char lbotch[] = "rcmd: botch starting error stream\n";
  17. static void
  18. ding(int x)
  19. {
  20. }
  21. int
  22. rcmd(char **dst, int port, char *luser, char *ruser, char *cmd, int *fd2p)
  23. {
  24. char c;
  25. int i, fd, lfd, fd2, port2;
  26. struct hostent *h;
  27. Rock *r;
  28. struct sockaddr_in in;
  29. char buf[128];
  30. void (*x)(int);
  31. h = gethostbyname(*dst);
  32. if(h == 0)
  33. return -1;
  34. *dst = h->h_name;
  35. /* connect using a reserved tcp port */
  36. fd = socket(PF_INET, SOCK_STREAM, 0);
  37. if(fd < 0)
  38. return -1;
  39. r = _sock_findrock(fd, 0);
  40. if(r == 0){
  41. errno = ENOTSOCK;
  42. return -1;
  43. }
  44. r->reserved = 1;
  45. in.sin_family = AF_INET;
  46. in.sin_port = htons(port);
  47. memmove(&in.sin_addr, h->h_addr_list[0], sizeof(in.sin_addr));
  48. if(connect(fd, &in, sizeof(in)) < 0){
  49. close(fd);
  50. return -1;
  51. }
  52. /* error stream */
  53. if(fd2p){
  54. /* create an error stream and wait for a call in */
  55. for(i = 0; i < 10; i++){
  56. lfd = rresvport(&port2);
  57. if(lfd < 0)
  58. continue;
  59. if(listen(lfd, 1) == 0)
  60. break;
  61. close(lfd);
  62. }
  63. if(i >= 10){
  64. fprintf(stderr, pbotch);
  65. return -1;
  66. }
  67. snprintf(buf, sizeof buf, "%d", port2);
  68. if(write(fd, buf, strlen(buf)+1) < 0){
  69. close(fd);
  70. close(lfd);
  71. fprintf(stderr, lbotch);
  72. return -1;
  73. }
  74. } else {
  75. if(write(fd, "", 1) < 0){
  76. fprintf(stderr, pbotch);
  77. return -1;
  78. }
  79. }
  80. /* pass id's and command */
  81. if(write(fd, luser, strlen(luser)+1) < 0
  82. || write(fd, ruser, strlen(ruser)+1) < 0
  83. || write(fd, cmd, strlen(cmd)+1) < 0){
  84. if(fd2p)
  85. close(fd2);
  86. fprintf(stderr, pbotch);
  87. return -1;
  88. }
  89. if(fd2p){
  90. x = signal(SIGALRM, ding);
  91. alarm(15);
  92. fd2 = accept(lfd, &in, &i);
  93. alarm(0);
  94. close(lfd);
  95. signal(SIGALRM, x);
  96. if(fd2 < 0){
  97. close(fd);
  98. close(lfd);
  99. fprintf(stderr, lbotch);
  100. return -1;
  101. }
  102. *fd2p = fd2;
  103. }
  104. /* get reply */
  105. if(read(fd, &c, 1) != 1){
  106. if(fd2p)
  107. close(fd2);
  108. fprintf(stderr, pbotch);
  109. return -1;
  110. }
  111. if(c == 0)
  112. return fd;
  113. i = 0;
  114. while(c){
  115. buf[i++] = c;
  116. if(read(fd, &c, 1) != 1)
  117. break;
  118. if(i >= sizeof(buf)-1)
  119. break;
  120. }
  121. buf[i] = 0;
  122. fprintf(stderr, "rcmd: %s\n", buf);
  123. close(fd);
  124. return -1;
  125. }