No change in functionality, but in doc and code.
[iii.git] / wrapper.c
blobbb93878200ed9963d2574a780b3de4e54859f4e0
1 #include <sys/stat.h>
2 #include <sys/types.h>
4 #include <err.h>
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include <time.h>
9 #include <unistd.h>
11 int
12 main(int argc, char **argv)
14 const unsigned int uargc = (unsigned int)argc;
15 char *init = NULL;
16 size_t i, j, r, rv = 0, s;
17 pid_t pid, sid;
19 if (uargc % 2 != 0 || uargc < 4) {
20 (void)fprintf(stderr, "usage: wrapper \"ii args\" host1 port1"
21 " [host2 port2 ...]\n");
22 exit(1);
25 for (i = 0; i < strlen(argv[1]); i++)
26 if (argv[1][i] == '<' || argv[1][i] == '>'
27 || argv[1][i] == '|' || argv[1][i] == ';'
28 || argv[1][i] == '(' || argv[1][i] == ')'
29 || argv[1][i] == '&' || argv[1][i] == '"'
30 || argv[1][i] == '\'')
31 err(1, "sh(1) meta-characters and quotation marks are "
32 "not allowed in the `ii args'.\n");
34 for (i = 2; i < uargc; i++)
35 if (i % 2 == 1) {
37 * Permit port numbers that are in the range 0 < p <
38 * 65535.
40 if (atoi(argv[i]) < 1 || atoi(argv[i]) > 65535)
41 err(1, "Port number `%lu' is not in range.\n",
42 (unsigned long)i / 2);
43 for (j = 0; j < strlen(argv[i]); j++)
44 if (argv[i][j] < 0x30 || argv[i][j] > 0x39)
45 err(1, "Character `%lu' in port `%lu'"
46 " is not allowed.\n",
47 (unsigned long)j + 1,
48 (unsigned long)i / 2);
49 } else {
51 * Permitted characters in the hostname fields:
52 * a-z (0x61 < c < 0x7a)
53 * 0-9 (0x30 < c < 0x39)
54 * A-Z (0x41 < c < 0x5a)
55 * .-
57 for (j = 0; j < strlen(argv[i]); j++)
58 if (((argv[i][j] < 0x61 || argv[i][j] > 0x7a)
59 && (argv[i][j] < 0x30 || argv[i][j] > 0x39)
60 && (argv[i][j] < 0x41 || argv[i][j] > 0x5a))
61 && argv[i][j] != '.' && argv[i][j] != '-')
62 err(1, "Character `%lu' in hostname"
63 " `%lu' is not allowed.\n",
64 (unsigned long)j + 1,
65 (unsigned long)i / 2);
68 printf("arguments: `%s'\n", argv[1]);
69 for (i = 2; i < uargc; i += 2)
70 printf("[%lu]: %s:%d\n", (unsigned long)(i - 1) / 2, argv[i],
71 atoi(argv[i + 1]));
73 pid = fork();
74 if (pid < 0) {
75 rv = 1;
76 goto clean;
77 } else if (pid > 0)
78 goto clean;
80 umask(0);
82 sid = setsid();
83 if (sid < 0) {
84 rv = 1;
85 goto clean;
88 if ((chdir("/")) < 0) {
89 rv = 1;
90 goto clean;
93 close(STDIN_FILENO);
94 close(STDOUT_FILENO);
95 close(STDERR_FILENO);
97 srandom(time(NULL));
99 while (1) {
101 * Calculate a random number in the range 0-(i/2 - 1).
102 * http://eternallyconfuzzled.com/arts/jsw_art_rand.aspx
104 r = random() * 1.0 / ( RAND_MAX + 1.0 ) * (i / 2 - 1);
106 s = strlen(argv[1]) + strlen(argv[r * 2 + 2]) +
107 strlen(argv[r * 2 + 3]) + 10 + sizeof(EXECUTABLE);
109 if ((init = calloc(s, 1)) == NULL) {
110 rv = 1;
111 goto clean;
113 strlcpy(init, EXECUTABLE" ", s);
114 strlcat(init, argv[1], s);
115 strlcat(init, " -s ", s);
116 strlcat(init, argv[r * 2 + 2], s);
117 strlcat(init, " -p ", s);
118 strlcat(init, argv[r * 2 + 3], s);
120 system(init);
121 free(init);
124 clean:
125 if (init != NULL)
126 free(init);
127 return rv;