PageRenderTime 45ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/multiwinia/contrib/loki_setup/network.c

https://gitlab.com/matt81093/Darwinia-and-Multiwinia-Source-Code
C | 278 lines | 222 code | 34 blank | 22 comment | 39 complexity | bc8b2a75c5629e85a1ba7e52855cb08d MD5 | raw file
  1. /* Network functions for the Loki Setup program */
  2. #include "config.h"
  3. #include <stdlib.h>
  4. #include <stdio.h>
  5. #include <sys/types.h>
  6. #include <sys/time.h>
  7. #include <sys/wait.h>
  8. #include <sys/socket.h>
  9. #include <netinet/in.h>
  10. #include <arpa/inet.h>
  11. #include <netdb.h>
  12. #include <unistd.h>
  13. #include <string.h>
  14. #include <errno.h>
  15. #ifdef HAVE_STRINGS_H
  16. # include <strings.h>
  17. #endif
  18. #include <signal.h>
  19. #ifndef TEST_MAIN
  20. #include "install.h"
  21. #include "install_log.h"
  22. #endif
  23. #include "network.h"
  24. /* This is the structure we pass back as a lookup handle */
  25. struct _URLlookup {
  26. int pid;
  27. int fd;
  28. };
  29. /* Utility function to connect to a URL and return a status */
  30. int connect_url(const char *url)
  31. {
  32. int rc;
  33. char *proto;
  34. char *host;
  35. char *string;
  36. char *bufp;
  37. int sock;
  38. struct sockaddr_in socka;
  39. short portnum;
  40. /* Copy the string */
  41. string = strdup(url);
  42. /* Check for protocol and set default ports */
  43. proto = NULL;
  44. bufp = strstr(string, "://");
  45. portnum = 0;
  46. if ( bufp ) {
  47. proto = string;
  48. *bufp = '\0';
  49. string = bufp+3;
  50. if ( strcasecmp(proto, "ftp") == 0 ) {
  51. portnum = 21;
  52. }
  53. }
  54. /* We can always read files ... */
  55. if ( (string[0] == '/') ||
  56. (proto && (strcasecmp(proto, "file") == 0)) ) {
  57. return(0);
  58. }
  59. /* Strip the file part of the URL */
  60. bufp = strchr(string, '/');
  61. if ( bufp ) {
  62. *bufp = '\0';
  63. }
  64. /* Extract any port number */
  65. bufp = strchr(string, ':');
  66. if ( bufp ) {
  67. *bufp++ = '\0';
  68. portnum = atoi(bufp);
  69. }
  70. if ( portnum == 0 ) {
  71. portnum = 80;
  72. }
  73. /* The rest of the string should be the hostname - resolve it */
  74. host = string;
  75. #ifdef TEST_MAIN
  76. printf("Resolving %s port %d\n", host, portnum);
  77. #endif
  78. socka.sin_addr.s_addr = inet_addr(host);
  79. if ( inet_aton(host, &socka.sin_addr) == 0 ) {
  80. struct hostent *hp;
  81. hp = gethostbyname(host);
  82. if ( hp ) {
  83. memcpy(&socka.sin_addr.s_addr,hp->h_addr,hp->h_length);
  84. } else {
  85. #ifdef TEST_MAIN
  86. printf("Resolving failed! %s\n", strerror(errno));
  87. #endif
  88. return(-1);
  89. }
  90. }
  91. socka.sin_port = htons(portnum);
  92. socka.sin_family = AF_INET;
  93. /* Now try to create a socket and connect */
  94. #ifdef TEST_MAIN
  95. printf("Connecting to remote host [%s]\n", host);
  96. #endif
  97. sock = socket(AF_INET, SOCK_STREAM, 0);
  98. if ( sock < 0 ) {
  99. #ifdef TEST_MAIN
  100. printf("socket() failed! %s\n", strerror(errno));
  101. #endif
  102. return(-1);
  103. }
  104. rc = connect(sock, (struct sockaddr *)&socka, sizeof(socka));
  105. #ifdef TEST_MAIN
  106. if (rc < 0)
  107. printf("Connect failed! %s\n", strerror(errno));
  108. #endif
  109. close(sock);
  110. if (rc < 0)
  111. return(-1);
  112. /* Hey, we successfully connected! */
  113. #ifdef TEST_MAIN
  114. printf("Connect succeeded!\n");
  115. #endif
  116. return(0);
  117. }
  118. /* This does a non-blocking network check of a URL
  119. It returns a socket file descriptor which is passed to wait_network(),
  120. or -1 if an error occurred while setting up the network check.
  121. */
  122. #ifdef TEST_MAIN
  123. URLlookup *open_lookup(const char *url)
  124. #else
  125. URLlookup *open_lookup(install_info *info, const char *url)
  126. #endif
  127. {
  128. URLlookup *lookup;
  129. int pipe_fds[2];
  130. /* Allocate a network lookup handle */
  131. lookup = (URLlookup *)malloc(sizeof *lookup);
  132. if ( lookup == NULL ) {
  133. #ifdef TEST_MAIN
  134. fprintf(stderr, "Out of memory, no network check\n");
  135. #else
  136. log_warning(_("Out of memory, no network check"));
  137. #endif
  138. return(NULL);
  139. }
  140. /* Create a pipe for IPC */
  141. if ( pipe(pipe_fds) < 0 ) {
  142. #ifdef TEST_MAIN
  143. fprintf(stderr, "Unable to create pipe, no network check\n");
  144. #else
  145. log_warning(_("Unable to create pipe, no network check"));
  146. #endif
  147. free(lookup);
  148. return(NULL);
  149. }
  150. lookup->fd = pipe_fds[0];
  151. /* Fork and do a lookup and connect */
  152. lookup->pid = fork();
  153. switch (lookup->pid) {
  154. case -1: /* Error... */
  155. #ifdef TEST_MAIN
  156. fprintf(stderr, "Fork failed, no network check\n");
  157. #else
  158. log_warning(_("Fork failed, no network check"));
  159. #endif
  160. close(pipe_fds[0]);
  161. close(pipe_fds[1]);
  162. lookup->fd = -1;
  163. break;
  164. case 0: /* Child, do lookup and connect */
  165. close(pipe_fds[0]);
  166. if ( connect_url(url) < 0 ) {
  167. write(pipe_fds[1], "n", 1);
  168. } else {
  169. write(pipe_fds[1], "y", 1);
  170. }
  171. exit(0);
  172. default: /* Parent, return okay */
  173. close(pipe_fds[1]);
  174. break;
  175. }
  176. if ( lookup->fd < 0 ) {
  177. free(lookup);
  178. lookup = NULL;
  179. }
  180. return lookup;
  181. }
  182. /* This checks the status of a URL lookup */
  183. int poll_lookup(URLlookup *handle)
  184. {
  185. char response;
  186. fd_set fdset;
  187. struct timeval tv;
  188. int ready;
  189. int status;
  190. /* Check to see if the child process is ready */
  191. FD_ZERO(&fdset);
  192. FD_SET(handle->fd, &fdset);
  193. memset(&tv, 0, (sizeof tv));
  194. if ( select(handle->fd+1, &fdset, NULL, NULL, &tv) == 1 ) {
  195. ready = 1;
  196. } else {
  197. ready = 0;
  198. }
  199. #ifdef TEST_MAIN
  200. printf("URL check is %s\n", ready ? "ready" : "not ready");
  201. #endif
  202. status = 0;
  203. /* See whether the lookup has succeeded */
  204. if ( ready ) {
  205. if ( read(handle->fd, &response, 1) == 1 ) {
  206. if ( response == 'y' ) {
  207. status = 1;
  208. }
  209. }
  210. }
  211. return status;
  212. }
  213. /* This closes a previously opened URL lookup */
  214. void close_lookup(URLlookup *handle)
  215. {
  216. close(handle->fd);
  217. kill(handle->pid, SIGTERM);
  218. wait(NULL);
  219. free(handle);
  220. }
  221. #ifdef TEST_MAIN
  222. int main(int argc, char *argv[])
  223. {
  224. URLlookup *lookup;
  225. if ( argc != 3 ) {
  226. fprintf(stderr, "Usage: %s <delay> <url>\n", argv[0]);
  227. exit(1);
  228. }
  229. lookup = open_lookup(argv[2]);
  230. if ( lookup == NULL ) {
  231. fprintf(stderr, "Couldn't set up network check\n");
  232. exit(2);
  233. }
  234. sleep(atoi(argv[1]));
  235. printf("Checking URL... \n");
  236. if ( poll_lookup(lookup) ) {
  237. printf("URL okay\n");
  238. } else {
  239. printf("URL not okay\n");
  240. }
  241. close_lookup(lookup);
  242. exit(0);
  243. }
  244. #endif