Ejemplo n.º 1
0
static void callbackLocking(int mode, int n, const char*, int) {
  if (mode & CRYPTO_LOCK) {
    locks()[n].lock();
  } else {
    locks()[n].unlock();
  }
}
Ejemplo n.º 2
0
void SSLContext::initializeOpenSSLLocked() {
  if (initialized_) {
    return;
  }
  SSL_library_init();
  SSL_load_error_strings();
  ERR_load_crypto_strings();
  // static locking
  locks().reset(new SSLLock[::CRYPTO_num_locks()]);
  for (auto it: lockTypes()) {
    locks()[it.first].lockType = it.second;
  }
  CRYPTO_set_id_callback(callbackThreadID);
  CRYPTO_set_locking_callback(callbackLocking);
  // dynamic locking
  CRYPTO_set_dynlock_create_callback(dyn_create);
  CRYPTO_set_dynlock_lock_callback(dyn_lock);
  CRYPTO_set_dynlock_destroy_callback(dyn_destroy);
  randomize();
#ifdef OPENSSL_NPN_NEGOTIATED
  sNextProtocolsExDataIndex_ = SSL_get_ex_new_index(0,
      (void*)"Advertised next protocol index", nullptr, nullptr, nullptr);
#endif
  initialized_ = true;
}
Ejemplo n.º 3
0
bool cLiveQueue::write(MsgPacket* packet)
{
  cSocketLock locks(m_socket);
  while(!packet->write(m_socket, 50) && Running())
    ;
  return true;
}
Ejemplo n.º 4
0
/**********************************************************************
* deleteroom
**********************************************************************/
void
deleteroom(void)
{
char    filename[100];
char    confirm[7];

  if (curr <= AIDE_RM_NBR)
  {
    printf("Can't kill this forum.\n");
    return;
  }

  get_string("Type 'DELETE' to kill this forum -> ", 6, confirm, -1);
  if (strcmp(confirm, "DELETE"))
    return;

  putchar('\n');


  locks(-1);
  msg->room[curr].flags = 0;
  sprintf(filename, "%sroom%d", DESCDIR, curr);
  unlink(filename);
  sprintf(filename, "%srm%d", WHODIR, curr);
  unlink(filename);
  unlocks(-1);

  /* you just nuked the room, need to go somewhere! */
  curr = LOBBY_RM_NBR;
}
Ejemplo n.º 5
0
    void OpDebug::append(const CurOp& curop,
                         const SingleThreadedLockStats& lockStats,
                         BSONObjBuilder& b) const {

        const size_t maxElementSize = 50 * 1024;

        b.append( "op" , iscommand ? "command" : opToString( op ) );
        b.append( "ns" , ns.toString() );

        if (!query.isEmpty()) {
            appendAsObjOrString(iscommand ? "command" : "query", query, maxElementSize, &b);
        }
        else if (!iscommand && curop.haveQuery()) {
            appendAsObjOrString("query", curop.query(), maxElementSize, &b);
        }

        if (!updateobj.isEmpty()) {
            appendAsObjOrString("updateobj", updateobj, maxElementSize, &b);
        }

        const bool moved = (nmoved >= 1);

        OPDEBUG_APPEND_NUMBER( cursorid );
        OPDEBUG_APPEND_NUMBER( ntoreturn );
        OPDEBUG_APPEND_NUMBER( ntoskip );
        OPDEBUG_APPEND_BOOL( exhaust );

        OPDEBUG_APPEND_NUMBER( nscanned );
        OPDEBUG_APPEND_NUMBER( nscannedObjects );
        OPDEBUG_APPEND_BOOL( idhack );
        OPDEBUG_APPEND_BOOL( scanAndOrder );
        OPDEBUG_APPEND_BOOL( moved );
        OPDEBUG_APPEND_NUMBER( nmoved );
        OPDEBUG_APPEND_NUMBER( nMatched );
        OPDEBUG_APPEND_NUMBER( nModified );
        OPDEBUG_APPEND_NUMBER( ninserted );
        OPDEBUG_APPEND_NUMBER( ndeleted );
        OPDEBUG_APPEND_BOOL( fastmod );
        OPDEBUG_APPEND_BOOL( fastmodinsert );
        OPDEBUG_APPEND_BOOL( upsert );
        OPDEBUG_APPEND_NUMBER( keyUpdates );
        OPDEBUG_APPEND_NUMBER( writeConflicts );
        b.appendNumber("numYield", curop.numYields());

        {
            BSONObjBuilder locks(b.subobjStart("locks"));
            lockStats.report(&locks);
        }

        if (!exceptionInfo.empty()) {
            exceptionInfo.append(b, "exception", "exceptionCode");
        }

        OPDEBUG_APPEND_NUMBER( nreturned );
        OPDEBUG_APPEND_NUMBER( responseLength );
        b.append( "millis" , executionTime );

        execStats.append(b, "execStats");
    }
Ejemplo n.º 6
0
bool CGUIDialogLockSettings::ShowAndGetLock(LockType& iLockMode, CStdString& strPassword, int iHeader)
{
  CProfile::CLock locks(iLockMode, strPassword);
  if (ShowAndGetLock(locks, iHeader, false, false))
  {
    locks.Validate();
    iLockMode = locks.mode;
    strPassword = locks.code;
    return true;
  }
  return false;
}
Ejemplo n.º 7
0
bool CGUIDialogLockSettings::ShowAndGetLock(LockType &lockMode, std::string &password, int header /* = 20091 */)
{
  CProfile::CLock locks(lockMode, password);
  if (!ShowAndGetLock(locks, header, false, false))
    return false;

  locks.Validate();
  lockMode = locks.mode;
  password = locks.code;

  return true;
}
Ejemplo n.º 8
0
bool CacheManagerI::load(const KeySeq& keys, const std::string& namespaceId, const std::string& businessId, 
                long expiredTime, bool useMaster, const Ice::Current& current) {
    std::ostringstream os;
    os<<"Key : ";
    for(KeySeq::const_iterator it = keys.begin(); it != keys.end(); ++it) {
        os<<*it<<" ";
    }
    os<<" namespaceId :"<<namespaceId;
    os<<" businessId :"<<businessId;
    os<<" expiredTime :"<<expiredTime;
    os<<" useMaster :"<<useMaster;
    MyUtil::InvokeClient ic = MyUtil::InvokeClient::create(current, os.str(), MyUtil::InvokeClient::INVOKE_LEVEL_INFO);
    ProducerManagerClientPtr producer = getProducer();
    if(producer == NULL) {
        return false;
    }
    
    bool sucFlag = true;

    KeySeq inputKeys(keys.begin(), keys.end());
    KeySeq lockedKeys;
    KeySeq failedLockedKeys;
    DataMap res;
    
    while(true) {
        xce::tempmutext::Locks<std::string> locks(&tempMutexManager_, inputKeys, lockedKeys, failedLockedKeys);
        if(!lockedKeys.empty()) {
            DataMap singleRes = producer->produce(keys, businessId, useMaster, 1000);
            if(!singleRes.empty()) {
                res.insert(singleRes.begin(), singleRes.end());
            }
        
            CacheClientPtr cache = getCache();
            if(cache != NULL) {
                for(DataMap::const_iterator it = singleRes.begin(); it != singleRes.end(); ++it) {
                    sucFlag &= cache->set(it->first, it->second, namespaceId, businessId, expiredTime, 1000);
                }
            }
            if(failedLockedKeys.empty()) {
                break;
            }
        }
        inputKeys.swap(failedLockedKeys);
        lockedKeys.clear();
        failedLockedKeys.clear();
    }

    return sucFlag;
}
Ejemplo n.º 9
0
void SSLContext::cleanupOpenSSLLocked() {
  if (!initialized_) {
    return;
  }

  CRYPTO_set_id_callback(nullptr);
  CRYPTO_set_locking_callback(nullptr);
  CRYPTO_set_dynlock_create_callback(nullptr);
  CRYPTO_set_dynlock_lock_callback(nullptr);
  CRYPTO_set_dynlock_destroy_callback(nullptr);
  CRYPTO_cleanup_all_ex_data();
  ERR_free_strings();
  EVP_cleanup();
  ERR_remove_state(0);
  locks().reset();
  initialized_ = false;
}
Ejemplo n.º 10
0
bool CacheManagerI::loadListCache(const std::string& key, const std::string& namespace_id, const std::string& biz_id, bool use_master, const Ice::Current& current) {
  std::ostringstream os;
  os << "key :" << key;
  os << " namespaceId :" << namespace_id;
  os << " businessId :" << biz_id;
  os << " use_master :" << use_master;
  MyUtil::InvokeClient ic = MyUtil::InvokeClient::create(current, os.str(), MyUtil::InvokeClient::INVOKE_LEVEL_INFO);
  ProducerManagerClientPtr producer = getProducer();
  if(!producer) {
    MCE_ERROR("CacheManagerI::loadListCache() getProducer() return NULL!!!");
    return false;
  }

  KeySeq input_keys;
  input_keys.push_back(key);
  KeySeq locked_keys;
  KeySeq failed_locked_keys;
  bool result = false;
  while(true) {
    xce::tempmutext::Locks<std::string> locks(&tempMutexManager_, input_keys, locked_keys, failed_locked_keys);
    if(!locked_keys.empty()) {
      DataMap data;
      try {
        data = producer->produce(locked_keys, biz_id, use_master, 10000);
      } catch (Ice::Exception& e) {
        MCE_ERROR("CacheManagerI::loadListCache() rpc call produce() " << e.what());
      }
      DataMap::const_iterator iter = data.begin();
      for (; iter != data.end(); ++iter) {
        if (!iter->second.empty()) {
          ListOrHashValue list_value;
          list_value.ParseFromArray(iter->second.data(), iter->second.size());
          if (list_value.values_size() > 0) {
            StrList str_list;
            BOOST_FOREACH(const std::string& v, list_value.values()) {
              str_list.push_back(v);
            }
            RedisCacheClientPtr cache = GetRedisCache();
            if (!cache) {
              MCE_ERROR("CacheManagerI::loadListCache() GetRedisCache() return NULL !!!");
              continue;
            }
            result = cache->SetList(key, str_list, namespace_id, biz_id);
          }
        }
      }
Ejemplo n.º 11
0
/**********************************************************************
* invite
* Modifies the user's generation and forget numbers to make a member
* of the room.
**********************************************************************/
void
invite(void)
{
struct user *tmpuser;
char   *uname;


  uname = get_name("Name of user to invite? ", 2);

  if (*uname)
  {
    if (!(tmpuser = getuser(uname)) || tmpuser->f_invisible)
    {
      if (tmpuser)
        freeuser(tmpuser);
      printf("There is no user %s on this BBS.\n", uname);
      return;
    }
    if (tmpuser->generation[curr] == msg->room[curr].gen || (!(msg->room[curr].flags & QR_PRIVATE) && tmpuser->generation[curr] != RODSERLING))
    {
      freeuser(tmpuser);
      printf("%s is already invited to this forum.\n", uname);
      return;
    }

    locks(SEM_USER);
    if (msg->room[curr].flags & QR_MINOR)
    {
      /* Only undo a kickout, they still have to jump to the room */
      tmpuser->forget[curr] = msg->room[curr].gen;
      tmpuser->generation[curr] = TWILIGHTZONE;
    }
    else
    {
      tmpuser->generation[curr] = msg->room[curr].gen;
      tmpuser->forget[curr] = TWILIGHTZONE;
    }
    unlocks(SEM_USER);

    freeuser(tmpuser);
    printf("%s invited to %s>\n", uname, msg->room[curr].name);
  }
}
Ejemplo n.º 12
0
/**********************************************************************
* kickout
* Edit a user's generation number for a room so (s)he can't get to it.
**********************************************************************/
void
kickout(void)
{
struct user *tmpuser;
char   *uname;


  if (curr == LOBBY_RM_NBR)
  {
    printf("Get a clue!  You can't kick a user out of the Lobby!\n");
    return;
  }

  uname = get_name("Name of user to kick out? ", 2);

  if (*uname)
  {
    if (!(tmpuser = getuser(uname)) || tmpuser->f_invisible)
    {
      if (tmpuser)
        freeuser(tmpuser);
      printf("There is no user %s on thsi BBS.\n", uname);
      return;
    }
    else
    {
      if ((tmpuser->generation[curr] == ((msg->room[curr].flags & QR_PRIVATE) ? TWILIGHTZONE : RODSERLING)) && tmpuser->forget[curr] == TWILIGHTZONE)
      {
        freeuser(tmpuser);
	printf("%s doesn't belong to this forum.\n", uname);
	return;
      }
      locks(SEM_USER);
      tmpuser->generation[curr] = ((msg->room[curr].flags & QR_PRIVATE) && !(msg->room[curr].flags & QR_GUESSNAME)) ? TWILIGHTZONE : RODSERLING;
      tmpuser->forget[curr] = TWILIGHTZONE;
      unlocks(SEM_USER);
      freeuser(tmpuser);

      printf("%s is now kicked out of %s>\n", uname, msg->room[curr].name);
    }
  }
}
Ejemplo n.º 13
0
    void fillLockerInfo(const Locker::LockerInfo& lockerInfo, BSONObjBuilder& infoBuilder) {
        // "locks" section
        BSONObjBuilder locks(infoBuilder.subobjStart("locks"));
        const size_t locksSize = lockerInfo.locks.size();

        // Only add the last lock of each type, and use the largest mode encountered
        LockMode modeForType[ResourceTypesCount] = { }; // default initialize to zero (min value)
        for (size_t i = 0; i < locksSize; i++) {
            const Locker::OneLock& lock = lockerInfo.locks[i];
            const ResourceType lockType = lock.resourceId.getType();
            const LockMode lockMode =  std::max(lock.mode, modeForType[lockType]);

            // Check that lockerInfo is sorted on resource type
            invariant(i == 0 || lockType >= lockerInfo.locks[i - 1].resourceId.getType());

            if (lock.resourceId == resourceIdLocalDB) {
                locks.append("local", legacyModeName(lock.mode));
                continue;
            }

            modeForType[lockType] = lockMode;

            if (i + 1 < locksSize && lockerInfo.locks[i + 1].resourceId.getType() == lockType) {
                continue; // skip this lock as it is not the last one of its type
            }
            else {
                locks.append(resourceTypeName(lockType), legacyModeName(lockMode));
            }
        }
        locks.done();

        // "waitingForLock" section
        infoBuilder.append("waitingForLock", lockerInfo.waitingResource.isValid());

        // "lockStats" section
        {
            BSONObjBuilder lockStats(infoBuilder.subobjStart("lockStats"));
            lockerInfo.stats.report(&lockStats);
            lockStats.done();
        }
    }
Ejemplo n.º 14
0
int warmup(void)
{
    char str[64], *src;
    struct timeval start, cur;
    int old_requests;

	g_echo = 0;

	memset(str, 0, 64);
	memset(str, '.', 40);
	src = "Server Warming Up";
	strncpy(str,src,strlen(src));

	printf("\n%s", str);

	fflush(stdout);

	gettimeofday(&start, NULL);
	gettimeofday(&cur, NULL);
	old_requests = pget_option.requests;
	pget_option.requests = 10;
	while ( (cur.tv_sec - start.tv_sec) < WARMUP_TIME){

		proppatch();
		propfinddead();
		propfindlive();
		put_get1K();
		put_get64K();
		//put_get1024K();
		my_single();
		my_collection();
		locks();

		gettimeofday(&cur, NULL);
	}

	pget_option.requests = old_requests;
	printf("Done\n");
	g_echo = 1;
}
JNIEXPORT void JNICALL
Java_org_apache_subversion_javahl_SVNRepos_rmlocks
(JNIEnv *env, jobject jthis, jobject jpath, jobjectArray jlocks)
{
  JNIEntry(SVNRepos, rmlocks);
  SVNRepos *cl = SVNRepos::getCppObject(jthis);
  if (cl == NULL)
    {
      JNIUtil::throwError(_("bad C++ this"));
      return;
    }

  File path(jpath);
  if (JNIUtil::isExceptionThrown())
    return;

  StringArray locks(jlocks);
  if (JNIUtil::isExceptionThrown())
    return;

  cl->rmlocks(path, locks);
}
Ejemplo n.º 16
0
bool CacheManagerI::deleteCache(const KeySeq& keys, const std::string& namespaceId, const std::string& businessId, const Ice::Current& current) {
    std::ostringstream os;
    os<<"Key : ";
    for(KeySeq::const_iterator it = keys.begin(); it != keys.end(); ++it) {
        os<<*it<<" ";
    }
    os<<" namespaceId :"<<namespaceId;
    os<<" businessId :"<<businessId;
    MyUtil::InvokeClient ic = MyUtil::InvokeClient::create(current, os.str(), MyUtil::InvokeClient::INVOKE_LEVEL_INFO);
    CacheClientPtr cache = getCache();
    if(cache == NULL) {
        return false;
    }
    
    bool sucFlag = true;

    KeySeq inputKeys(keys.begin(), keys.end());
    KeySeq lockedKeys;
    KeySeq failedLockedKeys;
    DataMap res;
    
    while(true) {
        xce::tempmutext::Locks<std::string> locks(&tempMutexManager_, inputKeys, lockedKeys, failedLockedKeys);
        if(!lockedKeys.empty()) {
            for(KeySeq::const_iterator it = keys.begin(); it != keys.end(); ++it) {
                sucFlag &= cache->remove(*it, namespaceId, businessId, 1000);
            }
            if(failedLockedKeys.empty()) {
                break;
            }
        }
        inputKeys.swap(failedLockedKeys);
        lockedKeys.clear();
        failedLockedKeys.clear();
    }

    return sucFlag;
}
Ejemplo n.º 17
0
/*
 * Exit the program in an orderly way. 
 */
void
my_exit(register int doflush)
{
  register int save = f_death;

  if (lockflags)
  {
    f_death = 2;
    return;
  }

  f_alarm = 0;
  if (doflush)
    f_death = -1;
  else
    f_death = -2;
  alarm(120);

  if (mybtmp)
    mybtmp->nox = -1;

  if (save == 1 && doflush)
    printf("\a\n\n\n\n\nYou have been logged off.\n\n\n\n\n");

  if (ouruser)
  {
    int f;
    struct tm *ltm;
    char junk[80];

    if (doflush)
      checkx(-1);

    locks(SEM_USER);
    if (ouruser->btmpindex >= 0 && mybtmp == &bigbtmp->btmp[ouruser->btmpindex])
      ouruser->btmpindex = -1;
    unlocks(SEM_USER);
    ouruser->timeoff = msg->t = time(0);

    strcpy(junk, ETC);
    strcat(junk, "uselog");
    if ((f = open(junk, O_WRONLY | O_CREAT | O_APPEND, 0640)) >= 0)
    {
      ltm = localtime(&ouruser->time);
      sprintf(junk, "%02d%02d%02d:%02d%02d:%04ld:%s\n", ltm->tm_year % 100, ltm->tm_mon + 1, ltm->tm_mday, ltm->tm_hour, ltm->tm_min, (ouruser->timeoff - ouruser->time) / 60 + 1, ouruser->name);
      write(f, junk, strlen(junk));
      close(f);
    }

    msync((caddr_t)ouruser, sizeof(struct user), MS_ASYNC);
    ouruser = NULL;
  }

  if (bigbtmp)
  {
    remove_loggedin(pid);
    bigbtmp = 0;
  }

  if (doflush)
  {
    if (ansi)
      printf("\033[0m");
    fflush(stdout);
    if (doflush > 1)
      mysleep(doflush);
    if (tty)
      myecho(ON);
    else
    {
      int fdr = 1;
      struct timeval tv = {30, 0};

      shutdown(0, 1);
      select(1, (fd_set *)&fdr, 0, 0, &tv);
    }
  }

  _exit(0);
}
Ejemplo n.º 18
0
/**********************************************************************
* editroom
* <E>dit room in aide menu
**********************************************************************/
void
editroom(void)
{
char    anon_opt;
char    opt;
char   *roomname;
int     flags;
int     gen;

  if (curr <= AIDE_RM_NBR && !ouruser->f_prog)
  {
    printf("Only programmers can edit Lobby, Mail, or Aide forums!\n");
    return;
  }

  flags = msg->room[curr].flags;
  gen = msg->room[curr].gen;

  /* Edit the room name */
  printf("Forum name is currently: %s>\n", msg->room[curr].name);

  roomname = get_name("New forum name (return leaves it unchanged) -> ", 3);

  /* If you're an aide or wizard, you can edit the permissions of the room */

  if (ouruser->f_admin)
  {
    /************************************************************
    * These ifs form a sentence onscreen.
    ************************************************************/

    printf("\n%s> was a", msg->room[curr].name);

    if (!(msg->room[curr].flags & QR_PRIVATE))
      printf(" public");

    if (msg->room[curr].flags & QR_PRIVATE)
      printf(" private");

    if (msg->room[curr].flags & QR_GUESSNAME)
      printf(" guessname");

    if (msg->room[curr].flags & QR_MINOR)
      printf(" non-minors only");

    if (msg->room[curr].flags & QR_ANONONLY)
      printf(" Anonymous-only");

    if (msg->room[curr].flags & QR_ANON2)
      printf(" Anonymous-optional");

    printf(" forum\n");

    printf("New forum type <1>pub <2>guessname <3>non-minors only <4>inv-only -> ");
    opt = get_single_quiet("1234");

    putchar('\n');

    /**********************************************************************
    * Option 1 (public) is default.
    * Non-public rooms have only 1 or 2 "privacy" bits: 
    * QR_PRIVATE by itself means invite-only, 
    * otherwise also set QR_GUESSNAME || QR_MINOR
    * Turn off all but inuse bits, we're going to reset everything
    * Turn bits back on as we go along
    **********************************************************************/
    flags = QR_INUSE;

    if (opt > '1')
      flags |= QR_PRIVATE;

    if (opt == '2')
      flags |= QR_GUESSNAME;

    if (opt == '3')
      flags |= QR_MINOR;

    if (opt != '1')
    {
      printf("(Answer yes to start a private forum)\n");
      printf("Cause users to forget forum? (y/n) -> ");

      gen = msg->room[curr].gen;
      if (yesno(-1) == YES)
      {
	if (++gen == 100)
	  gen = 10;
      }
    }
  }

  flags &= ~(QR_ANONONLY | QR_ANON2);
  printf("Identity: <1>Normal <2>Anon <3>Anon-optional -> ");
  anon_opt = get_single_quiet("123");

  if (anon_opt == '1')
    printf("Normal\n");
  else if (anon_opt == '2')
  {
    flags |= QR_ANONONLY;
    printf("Anonymous only\n");
  }
  else
  {
    flags |= QR_ANON2;
    printf("Anonymous optional\n");
  }


  colorize("@YSave changes? (Y/N) ->@G ");
  if (yesno(-1) == YES)
  {
    locks(SEM_MSG);
    if (*roomname)
      strcpy(msg->room[curr].name, roomname);
    msg->room[curr].flags = flags;
    msg->room[curr].gen = gen;
    unlocks(SEM_MSG);
  }

  printf("\nUse edit <D>escription to change description/forum moderator.\n");
}
Ejemplo n.º 19
0
/**********************************************************************
* createroom
**********************************************************************/
void
createroom(void)
{
register int i;
int     found;
char   *newroom;
char    opt;
int     rm_nbr;
int    qpos;
char filename[80];


  printf("Are you sure? (Y/N) ->");
  if (!yesno(-1))
    return;

  newroom = get_name("Name for new forum? ", 3);

  if (!*newroom)
    return;

  found = NO;

  /* Simultaneously search for a duplicate and the first unused room */
  for (qpos = rm_nbr = 0; rm_nbr < MAXROOMS && !found; ++rm_nbr)
  {
    /* quit searching if you find a duplicate */
    if ((msg->room[rm_nbr].flags & QR_INUSE)
	&& !strcmp(msg->room[rm_nbr].name, newroom))
      found = YES;

    /* get position of FIRST available room */
    if (!(msg->room[rm_nbr].flags & QR_INUSE) && !qpos)
      qpos = rm_nbr;
  }

  if (found)
  {
    printf("There is already a forum by that name\n");
    return;
  }

  /* qpos never gets set if all rooms are in use */
  /* the rest of the function depends on qpos being set -sf */
  if (!qpos)
  {
    printf("Sorry, no space is available for another forum.\n");
    return;
  }

  /* Set the access for the new room */
  help("roomaccess", NO);

  printf("\n<1>Public <2>Guess name <3>Non-minors only <4>Invitation only\n");
  printf("Enter forum type-> ");
  opt = get_single_quiet("1234");

  printf("\n\n\042%s\042, will be a", newroom);

  /* This is a bug!!  It never gets used!! */ 
  switch (opt)
  {
    case 1:
      printf(" public");
      break;
    case 2:
      printf(" guess-name");
      break;
    case 3:
      printf(" non-minors only");
      break;
    case 4:
      printf(" invitation-only");
      break;
  }

  printf(" forum\n");

  printf("Install it? (y/n) -> ");
  if (!yesno(-1))
  {
    printf("Create Forum aborted\n");
    return;
  }

  /* delete & zero room info & whoknows files if they exist */
  /* NOTE: Need exclusive access here! */
  sprintf(filename, "%sroom%d", DESCDIR, qpos);
  unlink(filename);
  open(filename, O_WRONLY | O_CREAT, 0640);
  sprintf(filename, "%srm%d", WHODIR, qpos);
  unlink(filename);
  open(filename, O_WRONLY | O_CREAT, 0640);

  locks(SEM_MSG);

  if (msg->room[qpos].flags & QR_INUSE)
  {
    unlocks(SEM_MSG);
    printf("\nForum slot taken, please try again.\n");
    return;
  }

  curr = qpos;

  strcpy(msg->room[curr].name, newroom);

  msg->room[curr].highest = 0L;
  msg->room[curr].posted = 0L;

  if (++msg->room[curr].gen == 100)
    msg->room[curr].gen = 10;

  /* want a clean slate to work with */
  msg->room[curr].flags = QR_INUSE;

  if (opt > '1')
    msg->room[curr].flags |= QR_PRIVATE;
  if (opt == '2')
    msg->room[curr].flags |= QR_GUESSNAME;
  if (opt == '3')
    msg->room[curr].flags |= QR_MINOR;

  for (i = 0; i < MSGSPERRM; i++)
  {
    msg->room[curr].pos[i] = 0;
    msg->room[curr].num[i]= 0;
    msg->room[curr].chron[i]= 0;
  }

  unlocks(SEM_MSG);

  printf("Use edit description to assign forum moderator.\n");

  printf("\n%s> (#%d) created as a", msg->room[curr].name, curr);

  if (!(msg->room[curr].flags & QR_PRIVATE))
    printf(" public");

  if (msg->room[curr].flags & QR_PRIVATE)
    printf(" [private]");

  if (msg->room[curr].flags & QR_GUESSNAME)
    printf(" [guessname]");

  if (msg->room[curr].flags & QR_MINOR)
    printf(" [non-minors only]");

  printf(" forum\n");

  /* Join user to the room that was just created */
  ouruser->forget[curr] = TWILIGHTZONE;
  ouruser->generation[curr] = msg->room[curr].gen;

  return;
}