fb3e2430c6fdad800e8468eae8be32c4e33f65ac
[perl.git] / do / ipcctl
1 int
2 do_ipcctl(optype, arglast)
3 int optype;
4 int *arglast;
5 {
6     register STR **st = stack->ary_array;
7     register int sp = arglast[0];
8     STR *astr;
9     char *a;
10     int id, n, cmd, infosize, getinfo, ret;
11
12     id = (int)str_gnum(st[++sp]);
13     n = (optype == O_SEMCTL) ? (int)str_gnum(st[++sp]) : 0;
14     cmd = (int)str_gnum(st[++sp]);
15     astr = st[++sp];
16
17     infosize = 0;
18     getinfo = (cmd == IPC_STAT);
19
20     switch (optype)
21     {
22 #ifdef HAS_MSG
23     case O_MSGCTL:
24         if (cmd == IPC_STAT || cmd == IPC_SET)
25             infosize = sizeof(struct msqid_ds);
26         break;
27 #endif
28 #ifdef HAS_SHM
29     case O_SHMCTL:
30         if (cmd == IPC_STAT || cmd == IPC_SET)
31             infosize = sizeof(struct shmid_ds);
32         break;
33 #endif
34 #ifdef HAS_SEM
35     case O_SEMCTL:
36         if (cmd == IPC_STAT || cmd == IPC_SET)
37             infosize = sizeof(struct semid_ds);
38         else if (cmd == GETALL || cmd == SETALL)
39         {
40             struct semid_ds semds;
41             if (semctl(id, 0, IPC_STAT, &semds) == -1)
42                 return -1;
43             getinfo = (cmd == GETALL);
44             infosize = semds.sem_nsems * sizeof(short);
45                 /* "short" is technically wrong but much more portable
46                    than guessing about u_?short(_t)? */
47         }
48         break;
49 #endif
50 #if !defined(HAS_MSG) || !defined(HAS_SEM) || !defined(HAS_SHM)
51     default:
52         fatal("%s not implemented", opname[optype]);
53 #endif
54     }
55
56     if (infosize)
57     {
58         if (getinfo)
59         {
60             STR_GROW(astr, infosize+1);
61             a = str_get(astr);
62         }
63         else
64         {
65             a = str_get(astr);
66             if (astr->str_cur != infosize)
67             {
68                 errno = EINVAL;
69                 return -1;
70             }
71         }
72     }
73     else
74     {
75         int i = (int)str_gnum(astr);
76         a = (char *)i;          /* ouch */
77     }
78     errno = 0;
79     switch (optype)
80     {
81 #ifdef HAS_MSG
82     case O_MSGCTL:
83         ret = msgctl(id, cmd, (struct msqid_ds *)a);
84         break;
85 #endif
86 #ifdef HAS_SEM
87     case O_SEMCTL:
88         ret = semctl(id, n, cmd, a);
89         break;
90 #endif
91 #ifdef HAS_SHM
92     case O_SHMCTL:
93         ret = shmctl(id, cmd, (struct shmid_ds *)a);
94         break;
95 #endif
96     }
97     if (getinfo && ret >= 0) {
98         astr->str_cur = infosize;
99         astr->str_ptr[infosize] = '\0';
100     }
101     return ret;
102 }
103