| 1 | /* Tests for fork.
|
|---|
| 2 | Copyright (C) 2000 Free Software Foundation, Inc.
|
|---|
| 3 | This file is part of the GNU C Library.
|
|---|
| 4 | Contributed by Ulrich Drepper <[email protected]>, 2000.
|
|---|
| 5 |
|
|---|
| 6 | The GNU C Library is free software; you can redistribute it and/or
|
|---|
| 7 | modify it under the terms of the GNU Lesser General Public
|
|---|
| 8 | License as published by the Free Software Foundation; either
|
|---|
| 9 | version 2.1 of the License, or (at your option) any later version.
|
|---|
| 10 |
|
|---|
| 11 | The GNU C Library is distributed in the hope that it will be useful,
|
|---|
| 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|---|
| 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|---|
| 14 | Lesser General Public License for more details.
|
|---|
| 15 |
|
|---|
| 16 | You should have received a copy of the GNU Lesser General Public
|
|---|
| 17 | License along with the GNU C Library; if not, write to the Free
|
|---|
| 18 | Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
|---|
| 19 | 02111-1307 USA. */
|
|---|
| 20 |
|
|---|
| 21 | #include <errno.h>
|
|---|
| 22 | #include <error.h>
|
|---|
| 23 | #include <stdlib.h>
|
|---|
| 24 | #include <string.h>
|
|---|
| 25 | #include <unistd.h>
|
|---|
| 26 | #include <wait.h>
|
|---|
| 27 |
|
|---|
| 28 |
|
|---|
| 29 | static const char testdata[] = "This is a test";
|
|---|
| 30 | static const char testdata2[] = "And here we go again";
|
|---|
| 31 |
|
|---|
| 32 |
|
|---|
| 33 | int
|
|---|
| 34 | main (void)
|
|---|
| 35 | {
|
|---|
| 36 | const char *tmpdir = getenv ("TMPDIR");
|
|---|
| 37 | char buf[100];
|
|---|
| 38 | size_t tmpdirlen;
|
|---|
| 39 | char *name;
|
|---|
| 40 | int fd;
|
|---|
| 41 | pid_t pid;
|
|---|
| 42 | pid_t ppid;
|
|---|
| 43 | off_t off;
|
|---|
| 44 | int status;
|
|---|
| 45 |
|
|---|
| 46 | if (tmpdir == NULL || *tmpdir == '\0')
|
|---|
| 47 | tmpdir = "/tmp";
|
|---|
| 48 | tmpdirlen = strlen (tmpdir);
|
|---|
| 49 |
|
|---|
| 50 | name = (char *) malloc (tmpdirlen + strlen ("/forkXXXXXX") + 1);
|
|---|
| 51 | if (name == NULL)
|
|---|
| 52 | error (EXIT_FAILURE, errno, "cannot allocate file name");
|
|---|
| 53 |
|
|---|
| 54 | mempcpy (mempcpy (name, tmpdir, tmpdirlen),
|
|---|
| 55 | "/forkXXXXXX", sizeof ("/forkXXXXXX"));
|
|---|
| 56 |
|
|---|
| 57 | /* Open our test file. */
|
|---|
| 58 | fd = mkstemp (name);
|
|---|
| 59 | if (fd == -1)
|
|---|
| 60 | error (EXIT_FAILURE, errno, "cannot open test file `%s'", name);
|
|---|
| 61 |
|
|---|
| 62 | /* Make sure it gets removed. */
|
|---|
| 63 | unlink (name);
|
|---|
| 64 |
|
|---|
| 65 | /* Write some data. */
|
|---|
| 66 | if (write (fd, testdata, strlen (testdata)) != strlen (testdata))
|
|---|
| 67 | error (EXIT_FAILURE, errno, "cannot write test data");
|
|---|
| 68 |
|
|---|
| 69 | /* Get the position in the stream. */
|
|---|
| 70 | off = lseek (fd, 0, SEEK_CUR);
|
|---|
| 71 | if (off == (off_t) -1 || off != strlen (testdata))
|
|---|
| 72 | error (EXIT_FAILURE, errno, "wrong file position");
|
|---|
| 73 |
|
|---|
| 74 | /* Get the parent PID. */
|
|---|
| 75 | ppid = getpid ();
|
|---|
| 76 |
|
|---|
| 77 | /* Now fork of the process. */
|
|---|
| 78 | pid = fork ();
|
|---|
| 79 | if (pid == 0)
|
|---|
| 80 | {
|
|---|
| 81 | /* One little test first: the PID must have changed. */
|
|---|
| 82 | if (getpid () == ppid)
|
|---|
| 83 | error (EXIT_FAILURE, 0, "child and parent have same PID");
|
|---|
| 84 |
|
|---|
| 85 | /* Test the `getppid' function. */
|
|---|
| 86 | pid = getppid ();
|
|---|
| 87 | if (pid == (pid_t) -1 ? errno != ENOSYS : pid != ppid)
|
|---|
| 88 | error (EXIT_FAILURE, 0,
|
|---|
| 89 | "getppid returned wrong PID (%ld, should be %ld)",
|
|---|
| 90 | (long int) pid, (long int) ppid);
|
|---|
| 91 |
|
|---|
| 92 | /* This is the child. First get the position of the descriptor. */
|
|---|
| 93 | off = lseek (fd, 0, SEEK_CUR);
|
|---|
| 94 | if (off == (off_t) -1 || off != strlen (testdata))
|
|---|
| 95 | error (EXIT_FAILURE, errno, "wrong file position in child");
|
|---|
| 96 |
|
|---|
| 97 | /* Reset the position. */
|
|---|
| 98 | if (lseek (fd, 0, SEEK_SET) != 0)
|
|---|
| 99 | error (EXIT_FAILURE, errno, "cannot reset position in child");
|
|---|
| 100 |
|
|---|
| 101 | /* Read the data. */
|
|---|
| 102 | if (read (fd, buf, sizeof buf) != strlen (testdata))
|
|---|
| 103 | error (EXIT_FAILURE, errno, "cannot read data in child");
|
|---|
| 104 |
|
|---|
| 105 | /* Compare the data. */
|
|---|
| 106 | if (memcmp (buf, testdata, strlen (testdata)) != 0)
|
|---|
| 107 | error (EXIT_FAILURE, 0, "data comparison failed in child");
|
|---|
| 108 |
|
|---|
| 109 | /* Reset position again. */
|
|---|
| 110 | if (lseek (fd, 0, SEEK_SET) != 0)
|
|---|
| 111 | error (EXIT_FAILURE, errno, "cannot reset position again in child");
|
|---|
| 112 |
|
|---|
| 113 | /* Write new data. */
|
|---|
| 114 | if (write (fd, testdata2, strlen (testdata2)) != strlen (testdata2))
|
|---|
| 115 | error (EXIT_FAILURE, errno, "cannot write new data in child");
|
|---|
| 116 |
|
|---|
| 117 | /* Close the file. This must not remove it. */
|
|---|
| 118 | close (fd);
|
|---|
| 119 |
|
|---|
| 120 | _exit (0);
|
|---|
| 121 | }
|
|---|
| 122 | else if (pid < 0)
|
|---|
| 123 | /* Something went wrong. */
|
|---|
| 124 | error (EXIT_FAILURE, errno, "cannot fork");
|
|---|
| 125 |
|
|---|
| 126 | /* Wait for the child. */
|
|---|
| 127 | if (waitpid (pid, &status, 0) != pid)
|
|---|
| 128 | error (EXIT_FAILURE, 0, "Oops, wrong test program terminated");
|
|---|
| 129 |
|
|---|
| 130 | if (WTERMSIG (status) != 0)
|
|---|
| 131 | error (EXIT_FAILURE, 0, "Child terminated incorrectly");
|
|---|
| 132 | status = WEXITSTATUS (status);
|
|---|
| 133 |
|
|---|
| 134 | if (status == 0)
|
|---|
| 135 | {
|
|---|
| 136 | /* Test whether the child wrote the right data. First test the
|
|---|
| 137 | position. It must be the same as in the child. */
|
|---|
| 138 | if (lseek (fd, 0, SEEK_CUR) != strlen (testdata2))
|
|---|
| 139 | error (EXIT_FAILURE, 0, "file position not changed");
|
|---|
| 140 |
|
|---|
| 141 | if (lseek (fd, 0, SEEK_SET) != 0)
|
|---|
| 142 | error (EXIT_FAILURE, errno, "cannot reset file position");
|
|---|
| 143 |
|
|---|
| 144 | if (read (fd, buf, sizeof buf) != strlen (testdata2))
|
|---|
| 145 | error (EXIT_FAILURE, errno, "cannot read new data");
|
|---|
| 146 |
|
|---|
| 147 | if (memcmp (buf, testdata2, strlen (testdata2)) != 0)
|
|---|
| 148 | error (EXIT_FAILURE, 0, "new data not read correctly");
|
|---|
| 149 | }
|
|---|
| 150 |
|
|---|
| 151 | return status;
|
|---|
| 152 | }
|
|---|