1 /*
2 *
3 * Copyright (c) International Business Machines Corp., 2002
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
13 * the GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20 /* 12/20/2002 Port to LTP robbiew@us.ibm.com */
21 /* 06/30/2001 Port to Linux nsharoff@us.ibm.com */
22
23 /*
24 * NAME
25 * shmt06
26 *
27 * CALLS
28 * shmctl(2) shmget(2) shmat(2)
29 *
30 * ALGORITHM
31 * Parent process forks a child. Child pauses until parent has created
32 * a shared memory segment, attached to it and written to it too. At that
33 * time child gets the shared memory segment id, attaches to it at two
34 * different addresses than the parents and verifies that their contents
35 * are the same as the contents of the parent attached segment.
36 *
37 */
38
39 #include <stdio.h>
40 #include <sys/types.h>
41 #include <sys/wait.h>
42 #include <sys/ipc.h>
43 #include <sys/shm.h>
44 #include <sys/utsname.h>
45 #include <signal.h>
46 #include <errno.h>
47 #include <stdlib.h>
48 #include <unistd.h>
49
50 #define SIZE 16*1024
51
52 /** LTP Port **/
53 #include "test.h"
54
55 char *TCID = "shmt06"; /* Test program identifier. */
56 int TST_TOTAL = 2; /* Total number of test cases. */
57 /**************/
58
59 key_t key;
60 sigset_t set;
61
62 int child();
63 static int rm_shm(int);
64
main(void)65 int main(void)
66 {
67 char *cp = NULL;
68 int pid, pid1, shmid;
69 int status;
70
71 key = (key_t) getpid();
72
73 sigemptyset(&set);
74 sigaddset(&set, SIGUSR1);
75 sigprocmask(SIG_BLOCK, &set, NULL);
76
77 pid = fork();
78 switch (pid) {
79 case -1:
80 tst_brkm(TBROK, NULL, "fork failed");
81 case 0:
82 child();
83 }
84
85 /*------------------------------------------------------*/
86
87 if ((shmid = shmget(key, SIZE, IPC_CREAT | 0666)) < 0) {
88 perror("shmget");
89 tst_resm(TFAIL, "Error: shmget: shmid = %d, errno = %d",
90 shmid, errno);
91 /*
92 * kill the child if parent failed to do the attach
93 */
94 (void)kill(pid, SIGINT);
95 } else {
96 cp = shmat(shmid, NULL, 0);
97
98 if (cp == (char *)-1) {
99 perror("shmat");
100 tst_resm(TFAIL,
101 "Error: shmat: shmid = %d, errno = %d",
102 shmid, errno);
103
104 /* kill the child if parent failed to do the attch */
105
106 kill(pid, SIGINT);
107
108 /* remove shared memory segment */
109
110 rm_shm(shmid);
111
112 tst_exit();
113 }
114 *cp = 'A';
115 *(cp + 1) = 'B';
116 *(cp + 2) = 'C';
117
118 kill(pid, SIGUSR1);
119 while ((pid1 = wait(&status)) < 0 && (errno == EINTR)) ;
120 if (pid1 != pid) {
121 tst_resm(TFAIL, "Waited on the wrong child");
122 tst_resm(TFAIL,
123 "Error: wait_status = %d, pid1= %d", status,
124 pid1);
125 }
126 }
127
128 tst_resm(TPASS, "shmget,shmat");
129
130 /*---------------------------------------------------------------*/
131
132 if (shmdt(cp) < 0) {
133 tst_resm(TFAIL, "shmdt");
134 }
135
136 tst_resm(TPASS, "shmdt");
137
138 /*-------------------------------------------------------------*/
139
140 rm_shm(shmid);
141 tst_exit();
142 }
143
child(void)144 int child(void)
145 {
146 int shmid, chld_pid;
147 char *cp;
148 int sig;
149
150 sigwait(&set, &sig);
151 chld_pid = getpid();
152
153 if ((shmid = shmget(key, SIZE, 0)) < 0) {
154 perror("shmget:child process");
155 tst_resm(TFAIL,
156 "Error: shmget: errno=%d, shmid=%d, child_pid=%d",
157 errno, shmid, chld_pid);
158 } else {
159 cp = shmat(shmid, NULL, 0);
160
161 if (cp == (char *)-1) {
162 perror("shmat:child process");
163 tst_resm(TFAIL,
164 "Error: shmat: errno=%d, shmid=%d, child_pid=%d",
165 errno, shmid, chld_pid);
166 } else {
167 if (*cp != 'A') {
168 tst_resm(TFAIL, "child: not A");
169 }
170 if (*(cp + 1) != 'B') {
171 tst_resm(TFAIL, "child: not B");
172 }
173 if (*(cp + 2) != 'C') {
174 tst_resm(TFAIL, "child: not C");
175 }
176 if (*(cp + 8192) != 0) {
177 tst_resm(TFAIL, "child: not 0");
178 }
179 }
180
181 /*
182 * Attach the segment to a different addresse
183 * and verify it's contents again.
184 */
185 cp = shmat(shmid, NULL, 0);
186
187 if (cp == (char *)-1) {
188 perror("shmat:child process");
189 tst_resm(TFAIL,
190 "Error: shmat: errno=%d, shmid=%d, child_pid=%d",
191 errno, shmid, chld_pid);
192 } else {
193 if (*cp != 'A') {
194 tst_resm(TFAIL, "child: not A");
195 }
196 if (*(cp + 1) != 'B') {
197 tst_resm(TFAIL, "child: not B");
198 }
199 if (*(cp + 2) != 'C') {
200 tst_resm(TFAIL, "child: not C");
201 }
202 if (*(cp + 8192) != 0) {
203 tst_resm(TFAIL, "child: not 0");
204 }
205 }
206 }
207 tst_exit();
208 }
209
rm_shm(int shmid)210 static int rm_shm(int shmid)
211 {
212 if (shmctl(shmid, IPC_RMID, NULL) == -1) {
213 perror("shmctl");
214 tst_brkm(TFAIL,
215 NULL,
216 "shmctl Failed to remove: shmid = %d, errno = %d",
217 shmid, errno);
218 }
219 return (0);
220 }
221