sysVstuff.c 8.66 KB
Newer Older
kollo's avatar
kollo committed
1 2 3 4 5 6 7 8 9 10
/* sysVstuff.c         (c) Markus Hoffmann   */

/* Semaphoren, Shared- Memory Objekte und Message Queues */

/* This file is part of X11BASIC, the basic interpreter for Unix/X
 * ============================================================
 * X11BASIC is free software and comes with NO WARRANTY - read the file
 * COPYING for details
 */
 
11 12
#include <stdlib.h>
#include <stdint.h>
kollo's avatar
kollo committed
13 14
#include <stdio.h>
#include <errno.h>
15 16 17 18
#include <string.h>
#include "defs.h"
#include "x11basic.h"
#include "xbasic.h"
19
#include "memory.h"
kollo's avatar
kollo committed
20
#if defined WINDOWS || defined ANDROID
kollo's avatar
kollo committed
21 22 23 24
#define EX_OK 0
#else
#include <sysexits.h>
#endif
kollo's avatar
kollo committed
25 26
 
#include <sys/types.h>
kollo's avatar
kollo committed
27 28

#ifndef WINDOWS
kollo's avatar
kollo committed
29
#include <sys/ipc.h>
kollo's avatar
kollo committed
30
#if 0
kollo's avatar
kollo committed
31
#include <sys/msg.h>
kollo's avatar
kollo committed
32
#endif
kollo's avatar
kollo committed
33
#ifndef ANDROID
kollo's avatar
kollo committed
34 35
#include <sys/sem.h>
#include <sys/shm.h>
kollo's avatar
kollo committed
36
#endif
kollo's avatar
kollo committed
37 38 39
#else
#define key_t int
#endif
40 41 42 43
#ifdef __APPLE__
#define key_t int
#endif

kollo's avatar
kollo committed
44 45 46 47 48 49 50

#define FALSE 0
#define TRUE (!FALSE)

#define MAX_SEND_SIZE 80
#define SEM_RESOURCE_MAX         1        /* Initial value of all semaphores */

kollo's avatar
kollo committed
51
void io_error(int,char *);
kollo's avatar
kollo committed
52 53

#if 0
kollo's avatar
kollo committed
54 55 56 57 58 59 60 61 62
struct mymsgbuf {
        long mtype;
        char mtext[MAX_SEND_SIZE];
};

void send_message(int qid, struct mymsgbuf *qbuf, long type, char *text);
void read_message(int qid, struct mymsgbuf *qbuf, long type);
void remove_queue(int qid);
void change_queue_mode(int qid, char *mode);
kollo's avatar
kollo committed
63
#endif
kollo's avatar
kollo committed
64 65 66
#if 0
static void opensem(int *sid, key_t key);
static void createsem(int *sid, key_t key, int members);
kollo's avatar
kollo committed
67 68 69
void locksem(int sid, int member);
void unlocksem(int sid, int member);
void removesem(int sid);
kollo's avatar
kollo committed
70 71 72
static unsigned short get_member_count(int sid);
static int getval(int sid, int member);
#endif
kollo's avatar
kollo committed
73 74 75 76
void dispval(int sid, int member);
void changemode(int sid, char *mode);
void shm_free(int);
void change_shm_mode(int, char *);
kollo's avatar
kollo committed
77
int shm_malloc(size_t,key_t);
kollo's avatar
kollo committed
78
#if 0
kollo's avatar
kollo committed
79 80 81

int open_msg(key_t key) {
  int msgqueue_id;
kollo's avatar
kollo committed
82
#ifndef WINDOWS
kollo's avatar
kollo committed
83 84
      /* Open the queue - create if necessary */
        if((msgqueue_id = msgget(key, IPC_CREAT|0660)) == -1) {
kollo's avatar
kollo committed
85
                 io_error(errno,"open_msg");    /* Message error.*/ 
kollo's avatar
kollo committed
86 87
                 return(-1);
        }
kollo's avatar
kollo committed
88
#endif	
kollo's avatar
kollo committed
89 90 91
  return(msgqueue_id);
}

kollo's avatar
kollo committed
92 93 94
int peek_message( int qid, long type ) {
  int     result, length;
#ifndef WINDOWS
kollo's avatar
kollo committed
95 96
         if((result = msgrcv( qid, NULL, 0, type,  IPC_NOWAIT)) == -1)
         { if(errno == E2BIG) return(TRUE); }
kollo's avatar
kollo committed
97
#endif
kollo's avatar
kollo committed
98 99 100 101
        return(FALSE);
}

void change_queue_mode(int qid, char *mode) {
kollo's avatar
kollo committed
102
#ifndef WINDOWS	
kollo's avatar
kollo committed
103 104 105 106
        struct msqid_ds myqueue_ds;
        msgctl(qid, IPC_STAT, &myqueue_ds);            /* Get current info */
        sscanf(mode, "%ho", &myqueue_ds.msg_perm.mode);/* Convert and load the mode */
        msgctl(qid, IPC_SET, &myqueue_ds);             /* Update the mode */
kollo's avatar
kollo committed
107
#endif
kollo's avatar
kollo committed
108 109 110 111
}

void send_message(int qid, struct mymsgbuf *qbuf, long type, char *text) {
        /* Send a message to the queue */
kollo's avatar
kollo committed
112
#if DEBUG
kollo's avatar
kollo committed
113
        printf("Sending a message ...\n");
kollo's avatar
kollo committed
114
#endif
kollo's avatar
kollo committed
115 116
        qbuf->mtype = type;
        strcpy(qbuf->mtext, text);
kollo's avatar
kollo committed
117
#ifndef WINDOWS
kollo's avatar
kollo committed
118 119
        if((msgsnd(qid, (struct msgbuf *)qbuf,
                strlen(qbuf->mtext)+1, 0)) ==-1) {
kollo's avatar
kollo committed
120
               io_error(errno,"send_message");    /* Message konnte nicht versandt werden.*/ 
kollo's avatar
kollo committed
121
        }
kollo's avatar
kollo committed
122
#endif	
kollo's avatar
kollo committed
123 124 125 126 127 128 129
}


void read_message(int qid, struct mymsgbuf *qbuf, long type)
{
        /* Read a message from the queue */
        qbuf->mtype = type;
kollo's avatar
kollo committed
130
#ifndef WINDOWS
kollo's avatar
kollo committed
131
        msgrcv(qid, (struct msgbuf *)qbuf, MAX_SEND_SIZE, type, 0);
kollo's avatar
kollo committed
132 133
#endif
#if DEBUG
kollo's avatar
kollo committed
134
        printf("Type: %ld Text: %s\n", qbuf->mtype, qbuf->mtext);
kollo's avatar
kollo committed
135
#endif
kollo's avatar
kollo committed
136 137 138 139
}


void remove_queue(int qid) /* Remove the msg-queue */ {
kollo's avatar
kollo committed
140
#ifndef WINDOWS
kollo's avatar
kollo committed
141
        msgctl(qid, IPC_RMID, 0);
kollo's avatar
kollo committed
142
#endif
kollo's avatar
kollo committed
143 144 145
}


kollo's avatar
kollo committed
146 147
#if 0
static int opensem( key_t key) {   /* Open the semaphore set - do not create! */
kollo's avatar
kollo committed
148 149 150
  int sid;
  if((*sid = semget(key, 0, 0666)) == -1) printf("Semaphore set does not exist!\n");
  return(sid);
kollo's avatar
kollo committed
151 152 153
}


kollo's avatar
kollo committed
154
static void createsem(int *sid, key_t key, int members) {
kollo's avatar
kollo committed
155 156
  int cntr;
  union semun semopts;
kollo's avatar
kollo committed
157

kollo's avatar
kollo committed
158
  if(members > SEMMSL) {
kollo's avatar
kollo committed
159
	  printf("Sorry, max number of semaphores in a set is %d\n",SEMMSL);
kollo's avatar
kollo committed
160
	  return;
kollo's avatar
kollo committed
161
  }
kollo's avatar
kollo committed
162 163
  printf("Attempting to create new semaphore set with %d members\n",members);
  if((*sid = semget(key, members, IPC_CREAT|IPC_EXCL|0666))== -1) {
kollo's avatar
kollo committed
164
                fprintf(stderr, "Semaphore set already exists!\n");
kollo's avatar
kollo committed
165
                return;
kollo's avatar
kollo committed
166
  }
kollo's avatar
kollo committed
167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189


        semopts.val = SEM_RESOURCE_MAX;


        /* Initialize all members (could be done with SETALL) */
        for(cntr=0; cntr<members; cntr++)
                semctl(*sid, cntr, SETVAL, semopts);
}

void locksem(int sid, int member)
{
        struct sembuf sem_lock={ 0, -1, IPC_NOWAIT};


        if( member<0 || member>(get_member_count(sid)-1))
        {
                 fprintf(stderr, "semaphore member %d out of range\n", member);
                 return;
        }


        /* Attempt to lock the semaphore set */
kollo's avatar
kollo committed
190
        if(!getval(sid, member)) {
kollo's avatar
kollo committed
191
                 fprintf(stderr, "Semaphore resources exhausted (no lock)!\n");
kollo's avatar
kollo committed
192
                 return;
kollo's avatar
kollo committed
193 194 195 196
        }

        sem_lock.sem_num = member;

kollo's avatar
kollo committed
197
        if((semop(sid, &sem_lock, 1)) == -1) {
kollo's avatar
kollo committed
198
                 fprintf(stderr, "Lock failed\n");
kollo's avatar
kollo committed
199
                 return;
kollo's avatar
kollo committed
200
        } else printf("Semaphore resources decremented by one (locked)\n");
kollo's avatar
kollo committed
201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220

        dispval(sid, member);
}
void unlocksem(int sid, int member)
{
        struct sembuf sem_unlock={ member, 1, IPC_NOWAIT};
        int semval;


        if( member<0 || member>(get_member_count(sid)-1))
        {
                 fprintf(stderr, "semaphore member %d out of range\n", member);
                 return;
        }


        /* Is the semaphore set locked? */
        semval = getval(sid, member);
        if(semval == SEM_RESOURCE_MAX) {
                 fprintf(stderr, "Semaphore not locked!\n");
kollo's avatar
kollo committed
221
                 return;
kollo's avatar
kollo committed
222 223 224 225 226
        }
        sem_unlock.sem_num = member;


        /* Attempt to lock the semaphore set */
kollo's avatar
kollo committed
227
        if((semop(sid, &sem_unlock, 1)) == -1) {
kollo's avatar
kollo committed
228
                fprintf(stderr, "Unlock failed\n");
kollo's avatar
kollo committed
229
                return;
kollo's avatar
kollo committed
230
        } else printf("Semaphore resources incremented by one (unlocked)\n");
kollo's avatar
kollo committed
231 232 233
        dispval(sid, member);
}

kollo's avatar
kollo committed
234 235
void removesem(int sid){
  semctl(sid, 0, IPC_RMID, 0);
kollo's avatar
kollo committed
236 237 238
}


kollo's avatar
kollo committed
239
static unsigned short get_member_count(int sid) {
kollo's avatar
kollo committed
240 241 242 243 244 245 246 247 248 249
        union semun semopts;
        struct semid_ds mysemds;


        semopts.buf = &mysemds;


        /* Return number of members in the semaphore set */
        return(semopts.buf->sem_nsems);
}
kollo's avatar
kollo committed
250
static int getval(int sid, int member) {
kollo's avatar
kollo committed
251 252 253 254 255 256 257
        int semval;
	
        semval = semctl(sid, member, GETVAL, 0);
        return(semval);
}


kollo's avatar
kollo committed
258 259 260 261
void changemode(int sid, char *mode) {
  int rc;
  union semun semopts;
  struct semid_ds mysemds;
kollo's avatar
kollo committed
262 263 264 265 266 267 268

        /* Get current values for internal data structure */

        semopts.buf = &mysemds;
        rc = semctl(sid, 0, IPC_STAT, semopts);
        if (rc == -1) {
                 perror("semctl");
kollo's avatar
kollo committed
269
                 return;
kollo's avatar
kollo committed
270 271 272 273 274 275 276 277 278 279 280 281 282
        }

        printf("Old permissions were %o\n", semopts.buf->sem_perm.mode);


        /* Change the permissions on the semaphore */
        sscanf(mode, "%ho", &semopts.buf->sem_perm.mode);


        /* Update the internal data structure */
        semctl(sid, 0, IPC_SET, semopts);
}

kollo's avatar
kollo committed
283

kollo's avatar
kollo committed
284 285 286 287 288 289

void dispval(int sid, int member) {
        int semval;
        semval = semctl(sid, member, GETVAL, 0);
        printf("semval for member %d is %d\n", member, semval);
}
kollo's avatar
kollo committed
290
#endif
kollo's avatar
kollo committed
291
#endif
kollo's avatar
kollo committed
292

kollo's avatar
kollo committed
293 294 295 296 297 298 299 300 301 302 303 304
#if defined WINDOWS || defined __CYGWIN__ || defined ANDROID
  #define shmget(a,b,c) (-1)
  #define shmat(a,b,c) (-1)
  #define shmdt(a) (-1)
  #define shmctl(a,b,c) (-1)
  #ifndef IPC_CREAT
    #define IPC_CREAT 0
    #define IPC_EXCL 0
    #define IPC_RMID 0
    #define IPC_STAT 0
    #define IPC_SET 0
  #endif
kollo's avatar
kollo committed
305 306
#endif

kollo's avatar
kollo committed
307

kollo's avatar
kollo committed
308
int shm_malloc(size_t segsize, key_t key) {
kollo's avatar
kollo committed
309
  int shmid=shmget(key, segsize, IPC_CREAT|IPC_EXCL|0666);
kollo's avatar
kollo committed
310
  /* Open the shared memory segment - create if necessary */
kollo's avatar
kollo committed
311
  if(shmid==-1) {
kollo's avatar
kollo committed
312
    /* Segment probably already exists - try as a client */
kollo's avatar
kollo committed
313
    shmid=shmget(key,segsize,0);
kollo's avatar
kollo committed
314
  }
kollo's avatar
kollo committed
315
  if(shmid==-1) io_error(errno,"SHM_MALLOC");    /* shm_malloc error.*/ 
kollo's avatar
kollo committed
316 317
  return(shmid);
}
kollo's avatar
kollo committed
318

kollo's avatar
kollo committed
319
int shm_attach(int shmid) {
320
  int r=POINTER2INT(shmat(shmid,0,0));
kollo's avatar
kollo committed
321 322
  if(r==-1) io_error(errno,"SHM_ATTACH");    /* shm_attach error.*/ 
  return(r);
kollo's avatar
kollo committed
323
}
kollo's avatar
kollo committed
324

325 326
int shm_detatch(const void *shmaddr) {
  if(shmdt(shmaddr)==-1) return(errno);
kollo's avatar
kollo committed
327
  return(0);
kollo's avatar
kollo committed
328 329
}

kollo's avatar
kollo committed
330 331 332
void shm_free(int shmid) {        /*  mark for deletion*/
  int r=shmctl(shmid, IPC_RMID, 0);
  if(r==-1) io_error(errno,"SHM_FREE");
kollo's avatar
kollo committed
333
}
kollo's avatar
kollo committed
334

kollo's avatar
kollo committed
335
#if 0
kollo's avatar
kollo committed
336 337 338 339 340 341 342 343
void change_shm_mode(int shmid, char *mode) {
        struct shmid_ds myshmds;

        /* Get current values for internal data structure */
        shmctl(shmid, IPC_STAT, &myshmds);
      /*  printf("Old permissions were: %o\n", myshmds.shm_perm.mode); */
        /* Convert and load the mode */
        sscanf(mode, "%o", &myshmds.shm_perm.mode);
kollo's avatar
kollo committed
344
        shmctl(shmid, IPC_SET, &myshmds);  /* Update the mode */
kollo's avatar
kollo committed
345 346
/*        printf("New permissions are : %o\n", myshmds.shm_perm.mode);*/
}
kollo's avatar
kollo committed
347
#endif