~ubuntu-branches/ubuntu/oneiric/nspr/oneiric-security

1 by Mike Hommey
Import upstream version 4.6.6
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
1.2.4 by Jamie Strandboge
Import upstream version 4.9.4
2
/* This Source Code Form is subject to the terms of the Mozilla Public
3
 * License, v. 2.0. If a copy of the MPL was not distributed with this
4
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
1 by Mike Hommey
Import upstream version 4.6.6
5
6
/***********************************************************************
7
**
8
** Name: forktest.c
9
**
10
** Description: UNIX test for fork functions.
11
**
12
** Modification History:
13
** 15-May-97 AGarcia- Converted the test to accomodate the debug_mode flag.
14
**                 The debug mode will print all of the printfs associated with this test.
15
**                         The regress mode will be the default mode. Since the regress tool limits
16
**           the output to a one line status:PASS or FAIL,all of the printf statements
17
**                         have been handled with an if (debug_mode) statement.
18
** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to
19
**                        recognize the return code from tha main program.
20
** 12-June-97 AGarcic - Revert to return code 0 and 1, remove debug option (obsolete).
21
***********************************************************************/
22
23
/***********************************************************************
24
** Includes
25
***********************************************************************/
26
/* Used to get the command line option */
27
#include "plgetopt.h"
28
29
#include "nspr.h"
30
#include <string.h>
31
#include <stdio.h>
32
#include <stdlib.h>
33
34
PRIntn failed_already=0;
35
36
#ifdef XP_UNIX
37
38
#include <sys/types.h>
39
#include <sys/wait.h>
40
#include <unistd.h>
41
#include <errno.h>
42
43
static char *message = "Hello world!";
44
45
static void
46
ClientThreadFunc(void *arg)
47
{
48
    PRNetAddr addr;
49
    PRFileDesc *sock = NULL;
50
    PRInt32 tmp = (PRInt32)arg;
51
52
    /*
53
     * Make sure the PR_Accept call will block
54
     */
55
56
    printf("Wait one second before connect\n");
57
    fflush(stdout);
58
    PR_Sleep(PR_SecondsToInterval(1));
59
60
    addr.inet.family = AF_INET;
61
    addr.inet.ip = PR_htonl(INADDR_ANY);
62
    addr.inet.port = 0;
63
    if ((sock = PR_NewTCPSocket()) == NULL) {
64
        fprintf(stderr, "failed to create TCP socket: error code %d\n",
65
            PR_GetError());
66
        failed_already = 1;
67
        goto finish;
68
    }
69
    if (PR_Bind(sock, &addr) != PR_SUCCESS) {
70
        fprintf(stderr, "PR_Bind failed: error code %d\n",
71
            PR_GetError());
72
        failed_already = 1;
73
        goto finish;
74
    }
75
    addr.inet.ip = PR_htonl(INADDR_LOOPBACK);
76
    addr.inet.port = PR_htons((PRInt16)tmp);
77
    printf("Connecting to port %hu\n", PR_ntohs(addr.inet.port));
78
    fflush(stdout);
79
    if (PR_Connect(sock, &addr, PR_SecondsToInterval(5)) !=
80
        PR_SUCCESS) {
81
        fprintf(stderr, "PR_Connect failed: error code %d\n",
82
            PR_GetError());
83
        failed_already = 1;
84
        goto finish;
85
    }
86
    printf("Writing message \"%s\"\n", message);
87
    fflush(stdout);
88
    if (PR_Send(sock, message, strlen(message) + 1, 0, PR_INTERVAL_NO_TIMEOUT) ==
89
        -1) {
90
        fprintf(stderr, "PR_Send failed: error code %d\n",
91
            PR_GetError());
92
        failed_already = 1;
93
        goto finish;
94
    }
95
finish:
96
    if (sock) {
97
        PR_Close(sock);
98
    }
99
    return;
100
}
101
102
/*
103
 * DoIO --
104
 *     This function creates a thread that acts as a client and itself.
105
 *     acts as a server.  Then it joins the client thread.
106
 */
107
static void
108
DoIO(void)
109
{
110
    PRThread *clientThread;
111
    PRFileDesc *listenSock = NULL;
112
    PRFileDesc *sock = NULL;
113
    PRNetAddr addr;
114
    PRInt32 nBytes;
115
    char buf[128];
116
117
    listenSock = PR_NewTCPSocket();
118
    if (!listenSock) {
119
        fprintf(stderr, "failed to create a TCP socket: error code %d\n",
120
            PR_GetError());
121
        failed_already = 1;
122
        goto finish;
123
    }
124
    addr.inet.family = AF_INET;
125
    addr.inet.ip = PR_htonl(INADDR_ANY);
126
    addr.inet.port = 0;
127
    if (PR_Bind(listenSock, &addr) == PR_FAILURE) {
128
        fprintf(stderr, "failed to bind socket: error code %d\n",
129
            PR_GetError());
130
        failed_already = 1;
131
        goto finish;
132
    }
133
    if (PR_GetSockName(listenSock, &addr) == PR_FAILURE) {
134
        fprintf(stderr, "failed to get socket port number: error code %d\n",
135
            PR_GetError());
136
        failed_already = 1;
137
        goto finish;
138
    }
139
    if (PR_Listen(listenSock, 5) == PR_FAILURE) {
140
        fprintf(stderr, "PR_Listen failed: error code %d\n",
141
            PR_GetError());
142
        failed_already = 1;
143
        goto finish;
144
    }
145
    clientThread = PR_CreateThread( PR_USER_THREAD, ClientThreadFunc,
146
        (void *) PR_ntohs(addr.inet.port), PR_PRIORITY_NORMAL, PR_LOCAL_THREAD,
147
        PR_JOINABLE_THREAD, 0);
148
    if (clientThread == NULL) {
149
        fprintf(stderr, "Cannot create client thread: (%d, %d)\n",
150
            PR_GetError(), PR_GetOSError());
151
        failed_already = 1;
152
        goto finish;
153
    }
154
    printf("Accepting connection at port %hu\n", PR_ntohs(addr.inet.port));
155
    fflush(stdout);
156
    sock = PR_Accept(listenSock, &addr, PR_SecondsToInterval(5));
157
    if (!sock) {
158
        fprintf(stderr, "PR_Accept failed: error code %d\n",
159
            PR_GetError());
160
        failed_already = 1;
161
        goto finish;
162
    }
163
    nBytes = PR_Recv(sock, buf, sizeof(buf), 0, PR_INTERVAL_NO_TIMEOUT);
164
    if (nBytes == -1) {
165
        fprintf(stderr, "PR_Recv failed: error code %d\n",
166
            PR_GetError());
167
        failed_already = 1;
168
        goto finish;
169
    }
170
171
    /*
172
     * Make sure it has proper null byte to mark end of string 
173
     */
174
175
    buf[sizeof(buf) - 1] = '\0';
176
    printf("Received \"%s\" from the client\n", buf);
177
    fflush(stdout);
178
    if (!strcmp(buf, message)) {
179
        PR_JoinThread(clientThread);
180
181
        printf("The message is received correctly\n");
182
        fflush(stdout);
183
    } else {
184
        fprintf(stderr, "The message should be \"%s\"\n",
185
            message);
186
        failed_already = 1;
187
    }
188
189
finish:
190
    if (listenSock) {
191
        PR_Close(listenSock);
192
    }
193
    if (sock) {
194
        PR_Close(sock);
195
    }
196
    return;
197
}
198
199
#ifdef _PR_DCETHREADS
200
201
#include <syscall.h>
202
203
pid_t PR_UnixFork1(void)
204
{
205
    pid_t parent = getpid();
206
    int rv = syscall(SYS_fork);
207
208
    if (rv == -1) {
209
        return (pid_t) -1;
210
    } else {
211
        /* For each process, rv is the pid of the other process */
212
        if (rv == parent) {
213
            /* the child */
214
            return 0;
215
        } else {
216
            /* the parent */
217
            return rv;
218
        }
219
    }
220
}
221
222
#elif defined(SOLARIS)
223
224
/*
225
 * It seems like that in Solaris 2.4 one must call fork1() if the
226
 * the child process is going to use thread functions.  Solaris 2.5
227
 * doesn't have this problem. Calling fork() also works. 
228
 */
229
230
pid_t PR_UnixFork1(void)
231
{
232
    return fork1();
233
}
234
235
#else
236
237
pid_t PR_UnixFork1(void)
238
{
239
    return fork();
240
}
241
242
#endif  /* PR_DCETHREADS */
243
1.1.10 by Alexander Sack
Import upstream version 4.8
244
int main(int argc, char **argv)
1 by Mike Hommey
Import upstream version 4.6.6
245
{
246
    pid_t pid;
247
	int rv;
248
249
    /* main test program */
250
251
    DoIO();
252
253
    pid = PR_UnixFork1();
254
255
    if (pid  == (pid_t) -1) {
256
        fprintf(stderr, "Fork failed: errno %d\n", errno);
257
        failed_already=1;
258
        return 1;
259
    } else if (pid > 0) {
260
        int childStatus;
261
262
        printf("Fork succeeded.  Parent process continues.\n");
263
        DoIO();
264
        if ((rv = waitpid(pid, &childStatus, 0)) != pid) {
265
#if defined(IRIX) && !defined(_PR_PTHREADS)
266
			/*
267
			 * nspr may handle SIGCLD signal
268
			 */
269
			if ((rv < 0) && (errno == ECHILD)) {
270
			} else 
271
#endif
272
			{
273
				fprintf(stderr, "waitpid failed: %d\n", errno);
274
				failed_already = 1;
275
			}
276
        } else if (!WIFEXITED(childStatus)
277
                || WEXITSTATUS(childStatus) != 0) {
278
            failed_already = 1;
279
        }
280
        printf("Parent process exits.\n");
281
        if (!failed_already) {
282
            printf("PASSED\n");
283
        } else {
284
            printf("FAILED\n");
285
        }
286
        return failed_already;
287
    } else {
288
#if defined(IRIX) && !defined(_PR_PTHREADS)
289
		extern void _PR_IRIX_CHILD_PROCESS(void);
290
		_PR_IRIX_CHILD_PROCESS();
291
#endif
292
        printf("Fork succeeded.  Child process continues.\n");
293
        DoIO();
294
        printf("Child process exits.\n");
295
        return failed_already;
296
    }
297
}
298
299
#else  /* XP_UNIX */
300
301
int main(    int     argc,
302
char   *argv[]
303
)
304
{
305
306
    printf("The fork test is applicable to Unix only.\n");
307
    return 0;
308
309
}
310
311
#endif  /* XP_UNIX */