00569 {
00570 va_list ap;
00571 int mode;
00572 int shmflg = 0;
00573 shm_t *shm;
00574 #ifdef USE_POSIX_SHAREDMEM
00575 int existed_before = 0;
00576 rcs_print_debug (PRINT_SHARED_MEMORY_ACTIVITY,
00577 "rcs_shm_open(key=%d(0x%X),size=%d(0x%X),oflag=%d)\n",
00578 key, key, size, size, oflag);
00579
00580 if (key == 0)
00581 {
00582 rcs_print_error ("rcs_shm_open(%d(0x%X), %d(0x%X), %d(0x%X)): error\n",
00583 key, key, size, size, oflag, oflag);
00584 rcs_print_error ("RCS Shared Memory key may not be zero.\n");
00585 return NULL;
00586 }
00587
00588 shm = (shm_t *) DEBUG_CALLOC (sizeof (shm_t), 1);
00589 if (NULL == shm)
00590 {
00591 rcs_print_error ("rcs_shm_open: calloc failed\n");
00592 return NULL;
00593 }
00594 shm->create_errno = 0;
00595 shm->addr = NULL;
00596 shm->key = key;
00597 shm->size = size;
00598 sprintf (shm->name, "/rcs_shm%d", key);
00599 shm->id = 0;
00600 errno = 0;
00601
00602
00603 #if defined(IPC_CREAT)
00604 #if O_CREAT != IPC_CREAT
00605 if ((oflag & IPC_CREAT) && !(oflag & O_CREAT))
00606 {
00607 oflag &= ~(IPC_CREAT);
00608 oflag |= O_CREAT;
00609 }
00610 #endif
00611 #endif
00612
00613 if ((oflag & O_CREAT))
00614 {
00615 shm->id = shm_open (shm->name, O_RDWR, mode);
00616 if (shm->id > 0)
00617 {
00618 shm->created = 0;
00619 existed_before = 1;
00620 }
00621 }
00622
00623
00624 if (shm->id <= 0)
00625 {
00626 shm->id = shm_open (shm->name, oflag | O_RDWR, mode);
00627 if (shm->id == -1)
00628 {
00629 rcs_print_error ("shm_open(%s,%d(0x%X),%d(0x%X)) failed:%s %d\n",
00630 shm->name, oflag | O_RDWR, oflag | O_RDWR,
00631 mode, mode, strerror (errno), errno);
00632 shm->create_errno = errno;
00633 return shm;
00634 }
00635 shm->created = 1;
00636 existed_before = 0;
00637 }
00638
00639
00640 if (ftruncate (shm->id, size + 16) == -1)
00641 {
00642 rcs_print_error ("ftruncate(%d,%d): %s %d\n",
00643 shm->id, size, strerror (errno), errno);
00644 shm->create_errno = errno;
00645 return shm;
00646 }
00647
00648
00649 shm->addr = mmap (0, size + 16,
00650 PROT_READ | PROT_WRITE, MAP_SHARED, shm->id, 0);
00651 if (shm->addr == MAP_FAILED)
00652 {
00653 rcs_print_error
00654 ("mmap(0,%d,PROT_READ | PROT_WRITE, MAP_SHARED,%d,0) failed: %s %d\n",
00655 shm->id, size, strerror (errno), errno);
00656 shm->create_errno = errno;
00657 }
00658 if (oflag & O_CREAT && !existed_before)
00659 {
00660 *((int *) ((char *) shm->addr + size)) = 0;
00661 }
00662 else
00663 {
00664 (*((int *) ((char *) shm->addr + size)))++;
00665 }
00666
00667 return (shm);
00668 #else
00669
00670 struct shmid_ds shared_mem_info;
00671 int pid;
00672 int i;
00673
00674 rcs_print_debug (PRINT_SHARED_MEMORY_ACTIVITY,
00675 "rcs_shm_open(key=%d(0x%X),size=%d(0x%X),oflag=%d)\n",
00676 key, key, size, size, oflag);
00677
00678 if (key == 0)
00679 {
00680 rcs_print_error ("rcs_shm_open(%d(0x%X), %d(0x%X), %d(0x%X)): error\n",
00681 key, key, size, size, oflag, oflag);
00682 rcs_print_error ("RCS Shared Memory key may not be zero.\n");
00683 return NULL;
00684 }
00685
00686 #if defined(O_CREAT)
00687 #if O_CREAT != IPC_CREAT
00688 if ((oflag & O_CREAT) && !(oflag & IPC_CREAT))
00689 {
00690 oflag &= ~(O_CREAT);
00691 oflag |= IPC_CREAT;
00692 }
00693 #endif
00694 #endif
00695
00696 if (oflag)
00697 {
00698 shmflg |= IPC_CREAT;
00699 }
00700 if (shmflg & IPC_CREAT)
00701 {
00702 #ifdef USING_VARARGS
00703 va_start (ap);
00704 #else
00705 va_start (ap, oflag);
00706 #endif
00707 mode = va_arg (ap, int);
00708 shmflg |= mode;
00709 }
00710
00711 shm = (shm_t *) DEBUG_CALLOC (sizeof (shm_t), 1);
00712 if (NULL == shm)
00713 {
00714 rcs_print_error ("rcs_shm_open: calloc failed\n");
00715 return NULL;
00716 }
00717 shm->create_errno = 0;
00718 shm->addr = NULL;
00719 shm->key = key;
00720 errno = 0;
00721
00722 if ((shm->id = shmget (key, (int) size, shmflg)) == -1)
00723 {
00724 shm->create_errno = errno;
00725 rcs_print_error ("shmget(%d(0x%X),%d,%d) failed: (errno = %d): %s\n",
00726 key, key, size, shmflg, errno, strerror (errno));
00727 switch (errno)
00728 {
00729 case EEXIST:
00730 rcs_print_error
00731 ("A shared memory buffer for this key already exists.\n");
00732 break;
00733
00734 case EINVAL:
00735 rcs_print_error
00736 ("Either the size is too big or the shared memory buffer already exists but is of the wrong size.\n");
00737 break;
00738
00739 case ENOSPC:
00740 rcs_print_error
00741 ("The system imposed limit on the maximum number of shared memory segments has been exceeded.\n");
00742 break;
00743 }
00744 return (shm);
00745 }
00746
00747
00748 shmflg = 0;
00749 shmflg &= ~SHM_RDONLY;
00750 if ((shm->addr = (void *) shmat (shm->id, 0, shmflg)) == (void *) -1)
00751 {
00752 shm->create_errno = errno;
00753 rcs_print_error ("shmat(%d,0,%d) failed:(errno = %d): %s\n", shm->id,
00754 shmflg, errno, strerror (errno));
00755 rcs_print_error ("key = %d (0x%X)\n", key, key);
00756 shm->addr = NULL;
00757 return (shm);
00758 }
00759
00760
00761 if (shmctl (shm->id, IPC_STAT, &shared_mem_info) < 0)
00762 {
00763 rcs_print_error ("shmctl error: %d %s\n", errno, strerror (errno));
00764 return shm;
00765 }
00766
00767
00768 if (!oflag)
00769 {
00770 return shm;
00771 }
00772
00773 if (!shmems_created_list_initialized)
00774 {
00775 memset (shmems_created_list, 0, 100 * sizeof (int));
00776 shmems_created_list_initialized = 1;
00777 }
00778 else
00779 {
00780 for (i = 0; i < 100; i++)
00781 {
00782 if (shmems_created_list[i] == key)
00783 {
00784 return shm;
00785 }
00786 }
00787 }
00788
00789 pid = (int) getpid ();
00790 if (pid <= 0)
00791 {
00792 rcs_print_error ("getpid error: %d %s\n", errno, strerror (errno));
00793 return shm;
00794 }
00795 shm->created = (shared_mem_info.shm_cpid == pid);
00796 #if defined(darwin) || defined(linux_2_4_0)
00797 shm->created = 1;
00798 #endif
00799
00800 if (shm->created)
00801 {
00802 for (i = 0; i < 100; i++)
00803 {
00804 if (shmems_created_list[i] <= 0)
00805 {
00806 shmems_created_list[i] = shm->key;
00807 break;
00808 }
00809 }
00810 }
00811 return shm;
00812 #endif
00813 }