예제 #1
0
파일: cajun.cpp 프로젝트: Aegisub/Aegisub
TEST(lagi_cajun, ReaderParserErrors) {
	json::UnknownElement ue;

	std::istringstream missing_comma("[1 2]");
	EXPECT_THROW(json::Reader::Read(ue, missing_comma), json::Exception);

	std::istringstream garbage_after_number("123!");
	EXPECT_THROW(json::Reader::Read(ue, garbage_after_number), json::Exception);

	std::istringstream unexpected_eof("[");
	EXPECT_THROW(json::Reader::Read(ue, unexpected_eof), json::Exception);

	std::istringstream bad_initial_token("]");
	EXPECT_THROW(json::Reader::Read(ue, bad_initial_token), json::Exception);

	std::istringstream garbage_after_end("[]a");
	EXPECT_THROW(json::Reader::Read(ue, garbage_after_end), json::Exception);

	std::istringstream empty_str("");
	EXPECT_THROW(json::Reader::Read(ue, empty_str), json::Exception);

	std::istringstream dupe_keys("{\"a\": [], \"a\": 0}");
	EXPECT_THROW(json::Reader::Read(ue, dupe_keys), json::Exception);

	std::istringstream unique_keys("{\"a\": [], \"b\": 0}");
	EXPECT_NO_THROW(json::Reader::Read(ue, unique_keys));
}
예제 #2
0
파일: cajun.cpp 프로젝트: Aegisub/Aegisub
TEST(lagi_cajun, ReaderScanErrors) {
	json::UnknownElement ue;

	std::istringstream doc("[true, false, thiswontwork]");
	EXPECT_THROW(json::Reader::Read(ue, doc), json::Exception);

	std::istringstream garbage_after_number("123abc");
	EXPECT_THROW(json::Reader::Read(ue, garbage_after_number), json::Exception);

	std::istringstream bad_escape("\"\\j\"");
	EXPECT_THROW(json::Reader::Read(ue, bad_escape), json::Exception);

	std::istringstream unexpected_eof("\"abc");
	EXPECT_THROW(json::Reader::Read(ue, unexpected_eof), json::Exception);
}
예제 #3
0
파일: main.c 프로젝트: enadam/bzip
unsigned bs_fill_byte(struct bitstream_st *bs, int eofok)
{
	unsigned n;

	assert(INRANGE(bs->byte_end,
		bs->byte_window, AFTER_OF(bs->byte_window)));
	assert(INRANGE(bs->byte_p, bs->byte_window, bs->byte_end));

	n = bs_read(bs, bs->byte_window, sizeof(bs->byte_window));
	bs->eof = n != sizeof(bs->byte_window);

	bs->byte_p = bs->byte_window;
	bs->byte_end = &bs->byte_window[n];

	if (!n && !eofok)
		unexpected_eof(bs);
	return n;
} /* bs_fill_byte */
예제 #4
0
파일: db.c 프로젝트: mysidia/snservices1
/** 
 * \brief Loads the memo database from disk
 */
void readMemoData(void)
{
	RegNickList *nick = NULL;
	RegNickList *from, *rnlb;
	MemoList *newmemo;
	char *command;
	char *topic;
	int done = 0;
	unsigned long linenum = 0;

	db.ms = fopen(MS_DB, "r");

	if (db.ms == NULL)
		return;

	while (!done) {
		if (!(sfgets(dbLine, 2048, db.ms))) {
			if (!done) {
				unexpected_eof(MS_DB);
			}
			done = 1;
			fclose(db.ms);
			return;
		}

		linenum++;
		if (parse_init(&state, dbLine) != 0) {
			/*! \bug XXX be nicer here... */
			abort();
		}

		command = parse_getarg(&state);

		if (strcmp(command, "data") == 0) {
			nick = getRegNickData(parse_getarg(&state));
			/*! \bug Increment the arguments.. we REALLY need to fix the dbs */
			(void)parse_getarg(&state);
			(void)parse_getarg(&state);
			if (nick) {
				nick->memos->flags = atoi(parse_getarg(&state));
				nick->memos->max = atoi(parse_getarg(&state));
				if (nick->memos->max <= 0)
					nick->memos->max = MS_DEF_RCV_MAX;
			}
		} else if (strcmp(command, "mblock") == 0) {
			MemoBlock *mbitem;
			if (nick && nick->memos) {
				char *nickToBlock;

				if ((nickToBlock = parse_getarg(&state))
					&& (rnlb = getRegNickData(nickToBlock))) {

					mbitem = (MemoBlock *) oalloc(sizeof(MemoBlock));
					mbitem->blockId = rnlb->regnum;
					mbitem->next = nick->memos->firstMblock;
					nick->memos->firstMblock = mbitem;
				}
			}
		} else if (strcmp(command, "redirect") == 0) {
			nick = getRegNickData(parse_getarg(&state));
			if (nick != NULL)
				nick->memos->forward =
					getRegNickData(parse_getarg(&state));
		} else if (strcmp(command, "memo") == 0) {
			char *cn;

			cn = parse_getarg(&state);

			nick = getRegNickData(cn);
			if (nick == NULL) {
				printf("memo: %s not valid\n", cn);
				continue;
			}
			newmemo = (MemoList *) oalloc(sizeof(MemoList));
			newmemo->realto = nick;
			/*! \bug Increment the argument 1, we need to fix the db */
			(void)parse_getarg(&state);
			newmemo->flags = atoi(parse_getarg(&state));
			newmemo->sent = (time_t) atol(parse_getarg(&state));

			/* Memo expiration code */

			if ((time(NULL) - newmemo->sent) >= NICKDROPTIME
			     && !(newmemo->flags & MEMO_SAVE)) {
				FREE(newmemo);
				continue;
			}

			strncpyzt(newmemo->from, parse_getarg(&state), NICKLEN);
			from = getRegNickData(newmemo->from);
			strncpyzt(newmemo->to, parse_getarg(&state), CHANLEN);

			/* Read the memo, skipping the leading : */
			topic = parse_getallargs(&state);
			if (topic == NULL) {
				FREE(newmemo);
				continue;
			}
			newmemo->memotxt = strdup(topic);

			/* Add the memo to the users memobox */
			LIST_ENTRY_INIT(newmemo, ml_lst);
			LIST_INSERT_HEAD(&nick->memos->mb_memos, newmemo, ml_lst);
			if (from && newmemo->flags & MEMO_UNREAD)
				LIST_INSERT_HEAD(&from->memos->mb_sent, newmemo, ml_sent);
			nick->memos->memocnt++;
		} else if (strcmp(command, "done") == 0) {
			done = 1;
		} else {
			fprintf(stderr, "Error in reading memo data (%s) %lu\n",
					dbLine, linenum);
			sshutdown(-1);
		}
#ifdef DBDEBUG
		sSend(":%s PRIVMSG " DEBUGCHAN " :Read memo data (%s)", MemoServ,
			  dbLine);
#endif

		parse_cleanup(&state);
	}

	fclose(db.ms);
}
예제 #5
0
파일: db.c 프로젝트: mysidia/snservices1
/** 
 * \brief Loads the ChanServ database from disk
 */
void readChanData()
{
	RegChanList *rcl;
	RegNickList *rnl;
	char *command;
	int done = 0, db_version = 1;
	int line_num = 0;
	char *pass;
	char *topic;

	rcl = NULL;
	rnl = NULL;
	db.cs = fopen(CS_DIR "chanserv.db", "r");
	if (db.cs == NULL)
		return;

	while (!done) {
		if ((sfgets(dbLine, 2048, db.cs)) == 0) {
			if (!done) {
				unexpected_eof(CS_DB);
			}
			done = 1;
			fclose(db.cs);
			return;
		}
		line_num++;

		if (parse_init(&state, dbLine) != 0) {
			fprintf(stderr,
					CS_DIR "chanserv.db:%d: " " Fatal error during read "
					" (Null line?) \n", line_num);
			abort();
		}

		command = parse_getarg(&state);
		if (!strcmp(command, "version")) {
			db_version = atoi(parse_getarg(&state));
		}
		else if (!strcmp(command, "channel")) {
			char *sChannelName, *sFounderNick;

			rcl = (RegChanList *) oalloc(sizeof(RegChanList));
			sChannelName = parse_getarg(&state);
			sFounderNick = parse_getarg(&state);
			initRegChanData(rcl);

			if (strlen(sChannelName) >= CHANLEN) {
				fprintf(stderr,
						CS_DIR "chanserv.db:%d: "
						" Channel name '%.80s' exceeds " " CHANLEN.\n",
						line_num, sChannelName);
				sshutdown(-1);
			} else if (strlen(sFounderNick) >= NICKLEN) {
				fprintf(stderr,
						CS_DIR "chanserv.db:%d: "
						" Founder nick name '%.80s' " " (%.80s)"
						" exceeds NICKLEN.\n", line_num, sFounderNick,
						sChannelName);
				sshutdown(-1);
			}

			if (!sChannelName || !sFounderNick) {
				fprintf(stderr,
						CS_DIR "chanserv.db:%d: " " Parse error. (%p, %p)",
						line_num, sChannelName, sFounderNick);
				sshutdown(-1);
			}

			rnl = getRegNickData(sFounderNick);

			strcpy(rcl->name, sChannelName);

			if (rnl)
			{
				rcl->founderId = rnl->regnum;
				rnl->chans++;
			}
			else
				rcl->founderId = RegId(0, 0);

			rcl->mlock = atol(parse_getarg(&state));
			rcl->flags = atol(parse_getarg(&state));
			pass = parse_getarg(&state);	/*! \bug XXX verify this works */
			if (!pass) {
				fprintf(stderr,
						CS_DIR "chanserv.db:%d: " " Null password?!",
						line_num);
				sshutdown(-1);
			} 

			if ((db_version < 2) || *pass == '@') {
				if (db_version < 2)
					strcpy((char *)rcl->password, pass);
				else
					strcpy((char *)rcl->password, pass + 1);

				if (strlen(pass) > (u_int)((db_version < 2) ? PASSLEN : PASSLEN+1)) {
					fprintf(stderr,
							CS_DIR "chanserv.db:%d: " " password > PASSLEN",
							line_num);
					sshutdown(-1);
				}

				xorit((char *)rcl->password);
				rcl->flags &= ~CENCRYPT;
			}
			else {
				u_char *tmpup = fromBase64(pass+1, NULL);
				int q;

				if (!tmpup)
					abort();
				for(q = 0; q < 16; q++)
					rcl->password[q] = tmpup[q];
				FREE(tmpup);
				rcl->flags |= CENCRYPT;
			}

			rcl->timereg = (time_t) atol(parse_getarg(&state));
			rcl->timestamp = (time_t) atol(parse_getarg(&state));
			strncpyzt(rcl->key, parse_getarg(&state), KEYLEN);
			rcl->limit = atol(parse_getarg(&state));
			rcl->memolevel = atoi(parse_getarg(&state));
			rcl->tlocklevel = atoi(parse_getarg(&state));
			rcl->restrictlevel = atoi(parse_getarg(&state));
			/* The rest of the line - skipping the leading : */
			topic = parse_getallargs(&state);
			if (topic == NULL)
				rcl->desc[0] = '\0';
			else
				strncpyzt(rcl->desc, topic, CHANDESCBUF);
			addRegChan(rcl);
			mostchans++;
		} else if (!strcmp(command, "topic")) {
			rcl = getRegChanData(parse_getarg(&state));
			if (rcl == NULL)
				continue;
			strncpyzt(rcl->tsetby, parse_getarg(&state), NICKLEN);
			rcl->ttimestamp = (time_t) atol(parse_getarg(&state));
			/* The rest of the topic, skipping the : in it */
			topic = parse_getallargs(&state);
			if (topic == NULL)
				rcl->topic = NULL;
			else
				rcl->topic = strdup(topic);
		} else if (!strcmp(command, "url")) {
			rcl = getRegChanData(parse_getarg(&state));
			if (rcl == NULL)
				continue;
			topic = parse_getallargs(&state);
			if (topic == NULL)
				rcl->url = NULL;
			else
				rcl->url = strdup(topic);
		} else if (!strcmp(command, "autogreet")) {
			rcl = getRegChanData(parse_getarg(&state));
			if (rcl == NULL)
				continue;
			topic = parse_getallargs(&state);
			if (topic == NULL)
				rcl->autogreet = NULL;
			else
				rcl->autogreet = strdup(topic);
		} else if (!strcmp(command, "markby")) {
			rcl = getRegChanData(parse_getarg(&state));
			if (rcl == NULL)
				continue;
			topic = parse_getarg(&state);
			if (topic == NULL)
				rcl->markby = NULL;
			else
				rcl->markby = strdup(topic);
		} else if (strcmp(command, "chkey") == 0) {
			char *tmpp = parse_getarg(&state);
			if (rcl && tmpp)
				rcl->chpw_key = strtoul(tmpp, (char **)0, 16);
		} else if (!strcmp(command, "op")) {
			cAccessList *lame;
			char *tmpName;

			rcl = getRegChanData(parse_getarg(&state));
			if (rcl == NULL)
				continue;
			tmpName = parse_getarg(&state);
			if ((rnl = getRegNickData(tmpName)) != NULL)
			{
				lame = (cAccessList *) oalloc(sizeof(cAccessList));
				lame->nickId = rnl->regnum;
				lame->uflags = atoi(parse_getarg(&state));
				addChanOp(rcl, lame);
			}
		} else if (!strcmp(command, "akick")) {
			cAkickList *lame;
			lame = (cAkickList *) oalloc(sizeof(cAkickList));
			rcl = getRegChanData(parse_getarg(&state));
			if (rcl == NULL)
				continue;
			strncpyzt(lame->mask, parse_getarg(&state), 70);
			lame->added = (time_t) atol(parse_getarg(&state));
			/* The rest of the string... */
			topic = parse_getallargs(&state);
			if (topic == NULL)
				lame->reason[0] = '\0';
			else {
				strncpyzt(lame->reason, topic, NICKLEN + 50);
			}
			addChanAkick(rcl, lame);
		} else if (!strcmp(command, "done"))
			done = 1;
		else {
			fprintf(stderr, "GLOBOPS :Read chan data (%s)", dbLine);
			sshutdown(-1);
		}

#ifdef DBDEBUG
		sSend(":%s PRIVMSG " DEBGUGCHAN " :Read chan data (%s)", ChanServ,
			  dbLine);
#endif

		parse_cleanup(&state);
	}
	fclose(db.cs);
}
예제 #6
0
파일: db.c 프로젝트: mysidia/snservices1
/**
 * \brief Loads the NickServ database from disk
 */
void readNickData()
{
	RegNickList *rnl = NULL;
	char *command, *tmpp;
	unsigned char *tmpup;
	int done = 0, db_version = 1;
	int line_num = 0, do_enc = 0;

#ifdef REQ_EMAIL
	readRegData();
#endif

	db.ns = fopen(NS_DB, "r");

	if (db.ns == NULL) {
		logDump(corelog, "Unable to open " NS_DB ": %s", strerror(errno));
		return;
	}

	while (!done) {
		if (!(sfgets(dbLine, 1024, db.ns))) {
			if (!done) {
				unexpected_eof(NS_DB);
			}
			done = 1;
			fclose(db.ns);
			return;
		}

		line_num++;

		if (parse_init(&state, dbLine) != 0) {
			/*! \bug XXX make a nicer error here! */
			abort();
		}

		command = parse_getarg(&state);
		if (strcmp(command, "version") == 0) {
			tmpp = parse_getarg(&state);
			assert(tmpp);

			if (tmpp)
				db_version = atoi(tmpp);
		}
		else
		if (strcmp(command, "nick") == 0) {
			rnl = (RegNickList *) oalloc(sizeof(RegNickList));
			char *sNick, *sUser, *sHost, *sPass;

			sNick = parse_getarg(&state);
			sUser = parse_getarg(&state);
			sHost = parse_getarg(&state);
			sPass = parse_getarg(&state);

			if (strlen(sNick) >= NICKLEN) {
				fprintf(stderr,
						NS_DB ":%d: " " Nickname '%.80s' exceeds "
						" NICKLEN.\n", line_num, sNick);
				sshutdown(-1);
			} 

			strcpy(rnl->nick, sNick);
			strncpyzt(rnl->user, sUser, USERLEN);
			SetDynBuffer(&rnl->host, sHost);

			if (db_version < 2)
			{
				if (strlen(sPass) > PASSLEN) {
					fprintf(stderr,
						NS_DB ":%d: " " Password for nick '%s' "
						" exceeds PASSLEN.\n", line_num, sNick);
					sshutdown(-1);
				}

				strcpy((char *)rnl->password, xorit(sPass));
			}
			else {
				char encType = *sPass;

				if (encType == '@') {
					if (strlen(sPass+1) > PASSLEN) {
						fprintf(stderr,
							NS_DB ":%d: " " Password for nick '%s' "
							" exceeds PASSLEN.\n", line_num, sNick);
						sshutdown(-1);
					}

					strcpy((char *)rnl->password, xorit(sPass + 1));
					do_enc = 0;
				}
				else if (encType == '$') {
					int q, len;

					tmpup = fromBase64(sPass + 1, &len);
					assert(tmpup);

					for(q = 0; q < 16; q++)
						rnl->password[q] = tmpup[q];
					do_enc = 1;
					FREE(tmpup);
				}
				else
					rnl->password[0] = '\0';
			}

			rnl->timestamp = (time_t) atol(parse_getarg(&state));
			rnl->timereg = (time_t) atol(parse_getarg(&state));
			rnl->flags = atoi(parse_getarg(&state));

			if (db_version >= 3) {
				const char *idString = parse_getarg(&state);
				int av, bv;

				sscanf(idString, "%X*%X", &av, &bv);
				rnl->regnum.SetDirect(top_regnick_idnum, av, bv);				
			}
			else {
				rnl->regnum.SetNext(top_regnick_idnum);
			}

			if (do_enc)
				rnl->flags |= NENCRYPT;
			else
				rnl->flags &= ~NENCRYPT;

			rnl->opflags = 0;
			rnl->idtime = DEF_NDELAY;
			ADD_MEMO_BOX(rnl);
			addRegNick(rnl);
		} else if (strcmp(command, "is") == 0) {
			char *data = parse_getarg(&state);
			if (rnl && data)
				rnl->is_readtime = atol(data);
		} else if (strcmp(command, "oper") == 0) {
			char *opflags_s;
			if (rnl && (rnl == getRegNickData(parse_getarg(&state)))) {
				if ((opflags_s = parse_getarg(&state)))
					rnl->opflags |=
						(strtoul(opflags_s, (char **)0, 10) &
						 ~(OROOT | OSERVOP));
				if (rnl->opflags)
					addOpData(rnl);
			}
		} else if (strcmp(command, "url") == 0) {
			if (rnl && (rnl == getRegNickData(parse_getarg(&state))))
			{
				rnl->url = strdup(parse_getarg(&state));
				if (strlen(rnl->url) > (URLLEN - 1))
					rnl->url[URLLEN - 1] = '\0';
			}
		} else if (strcmp(command, "gecos") == 0) {
#ifdef TRACK_GECOS
			char *gecos = parse_getallargs(&state);
			if (gecos != NULL)
				rnl->gecos = strdup(gecos);
#endif
		} else if (strcmp(command, "akey") == 0) {
#ifdef REQ_EMAIL
			if (rnl)
				rnl->email_key = atoi(parse_getarg(&state));
#endif
		} else if (strcmp(command, "chkey") == 0) {
			char *tmpp = parse_getarg(&state);
			if (rnl && tmpp)
				rnl->chpw_key = strtoul(tmpp, (char **)0, 16);
		} else if (strcmp(command, "markby") == 0) {
			char *mby;

			rnl = getRegNickData(parse_getarg(&state));
			if (!rnl || !(mby = parse_getarg(&state)))
				continue;
			rnl->markby = strdup(mby);
		} else if (strcmp(command, "access") == 0) {
			rnl = getRegNickData(parse_getarg(&state));
			addAccItem(rnl, parse_getarg(&state));
		} else if (!strcmp(command, "email")) {
			rnl = getRegNickData(parse_getarg(&state));

			strncpyzt(rnl->email, parse_getarg(&state), EMAILLEN);

			if (!strcmp(rnl->email, "(none)"))
				strcat(rnl->email, " ");
		} else if (!strcmp(command, "idtime")) {
			rnl = getRegNickData(parse_getarg(&state));
			rnl->idtime = atoi(parse_getarg(&state));
		} else if (!strcmp(command, "done"))
			done = 1;
		else {
			fprintf(stderr, NS_DB ":%d: Error reading nick data (%s)",
					line_num, dbLine);
			sshutdown(-1);
		}
#ifdef DBDEBUG
		sSend(":%s PRIVMSG " DEBUGCHAN " :Read nick data (%s)", NICKSERV,
			  dbLine);
#endif

		parse_cleanup(&state);
	}
	fclose(db.ns);

	readMemoData();
}
예제 #7
0
파일: db.c 프로젝트: mysidia/snservices1
/** 
 * \brief Loads the InfoServ database from disk
 */
void readInfoData(void)
{
	char *command;
	int done = 0;
	SomeNews *news, *tmpnews;

	is_listhead = NULL;
	db.is = fopen(IS_DB, "r");

	if (db.is == NULL)
		return;

		/**
         * There was still a crash bug in what was here before...
         * cleaning this up .. allocate memory when it's
         * needed, don't allocate it in the beginning and
         * give it up later if superflous in a linked list
         * load.
         * -Mysidia
         */

	while (!done) {
		if (!(sfgets(dbLine, 2048, db.is))) {
			if (!done) {
				unexpected_eof(IS_DB);
			}
			done = 1;
			fclose(db.is);
			return;
		}

		if (parse_init(&state, dbLine) != 0) {
			/*! \bug XXX be nicer here... */
			abort();
		}

		command = parse_getarg(&state);

		if (!strcmp(command, "article")) {
			char *temp;

			news = (SomeNews *) oalloc(sizeof(SomeNews));
			if (!is_listhead)
				is_listhead = news;
			else {
				for (tmpnews = is_listhead; tmpnews->next;
					 tmpnews = tmpnews->next);
				tmpnews->next = news;
			}
			news->importance = atoi(parse_getarg(&state));
			strncpyzt(news->from, parse_getarg(&state), NICKLEN);
			news->timestamp = atol(parse_getarg(&state));
			temp = parse_getallargs(&state);
			if (temp)
				news->header = strdup(temp);
			news->content = dbReadString(db.is);

			if (news->timestamp > is_last_post_time)
				is_last_post_time = news->timestamp;
		}

		else if (!strcmp(command, "done"))
			done = 1;
		else
			sshutdown(-1);

		parse_cleanup(&state);
	}
	fclose(db.is);
}
예제 #8
0
파일: db.c 프로젝트: mysidia/snservices1
/** 
 * \brief Loads the clone rule database from disk
 */
void readTriggerData(void)
{
	CloneRule *rule = NULL;
	char *command, *text;
	int done = 0;
	unsigned long linenum = 0;

	db.trigger = fopen(TRG_DB, "r");

	if (db.trigger == NULL) {
		logDump(corelog,
				"Unable to open trigger database for read access: %s",
				strerror(errno));
		return;
	}

	while (!done) {
		if (!(sfgets(dbLine, 2048, db.trigger))) {
			if (!done) {
				unexpected_eof(TRG_DB);
			}
			done = 1;
			fclose(db.trigger);
			return;
		}
		linenum++;

		if (parse_init(&state, dbLine) != 0) {
			/*! \bug XXX be nicer here... */
			abort();
		}

		command = parse_getarg(&state);

		if (strcmp(command, "Trigger") == 0) {
			rule = NewCrule();
			rule->kill_msg = NULL;
			rule->warn_msg = NULL;
			strncpyzt(rule->mask, parse_getarg(&state),
					  sizeof(rule->mask));
			rule->mask[sizeof(rule->mask) - 1] = '\0';
			rule->trigger = atoi(parse_getarg(&state));
			rule->utrigger = atoi(parse_getarg(&state));
			rule->flags = atol(parse_getarg(&state));
			AddCrule(rule, -2);	/* -2 is magic for append to end */
		} else if (strcmp(command, "Killmsg") == 0) {
			text = parse_getallargs(&state);
			if (text && rule)
				rule->kill_msg = strdup(text);
		} else if (strcmp(command, "Warnmsg") == 0) {
			text = parse_getallargs(&state);
			if (text && rule)
				rule->warn_msg = strdup(text);
		} else if (strcmp(command, "done") == 0) {
			done = 1;
		} else {
			fprintf(stderr, "Error in reading trigger data (%s) %lu\n",
					dbLine, linenum);
			parse_cleanup(&state);
			return;
		}
#ifdef DBDEBUG
		sSend(":%s PRIVMSG " DEBUGCHAN " :Read trigger data (%s)",
			  OperServ, dbLine);
#endif

		parse_cleanup(&state);
	}

	fclose(db.trigger);
}
예제 #9
0
static bool get_w_conf(FILE *in, char *infile, char *title,
		       t_atoms *atoms, int *ndec, rvec x[],rvec *v, matrix box)
{
  static t_symtab *symtab=NULL;
  char   name[6];
  char   line[STRLEN+1],*ptr;
  char   buf[256];
  double x1,y1,z1,x2,y2,z2;
  rvec   xmin,xmax;
  int    natoms,i,m,resnr,newres,oldres,ddist,c;
  bool   bFirst,bVel;
  char   *p1,*p2,*p3;
  
  newres  = 0;
  oldres  = NOTSET; /* Unlikely number for the first residue! */
  ddist   = 0;
  
  if (!symtab) {
    snew(symtab,1);
    open_symtab(symtab);
  }

  /* Read the title and number of atoms */
  get_coordnum_fp(in,title,&natoms);

  if (natoms > atoms->nr)
    gmx_fatal(FARGS,"gro file contains more atoms (%d) than expected (%d)",
		natoms,atoms->nr);
  else if (natoms <  atoms->nr)
    fprintf(stderr,"Warning: gro file contains less atoms (%d) than expected"
	    " (%d)\n",natoms,atoms->nr);
  
  bFirst=TRUE;
  
  bVel = FALSE;

  /* just pray the arrays are big enough */
  for (i=0; (i < natoms) ; i++) {
    if ((fgets2 (line,STRLEN,in)) == NULL) {
      unexpected_eof(infile,i+2);
    }
    if (strlen(line) < 39)
      gmx_fatal(FARGS,"Invalid line in %s for atom %d:\n%s",infile,i+1,line);

    /* determine read precision from distance between periods 
       (decimal points) */
    if (bFirst) {
      bFirst=FALSE;
      p1=strchr(line,'.');
      if (p1 == NULL)
	gmx_fatal(FARGS,"A coordinate in file %s does not contain a '.'",infile);
      p2=strchr(&p1[1],'.');
      if (p2 == NULL)
	gmx_fatal(FARGS,"A coordinate in file %s does not contain a '.'",infile);
      ddist = p2 - p1;
      *ndec = ddist - 5;

      p3=strchr(&p2[1],'.');
      if (p3 == NULL)
	gmx_fatal(FARGS,"A coordinate in file %s does not contain a '.'",infile);

      if (p3 - p2 != ddist)
	gmx_fatal(FARGS,"The spacing of the decimal points in file %s is not consistent for x, y and z",infile);
    }
    
    /* residue number*/
    memcpy(name,line,5);
    name[5]='\0';
    sscanf(name,"%d",&resnr);
    memcpy(name,line+5,5);
    name[5]='\0';
    if (resnr != oldres) {
      oldres = resnr;
      if (newres >= natoms)
	gmx_fatal(FARGS,"More residues than atoms in %s (natoms = %d)",
		    infile,natoms);
      atoms->resname[newres] = put_symtab(symtab,name);
      newres++;
    }
    resnr = newres;
    atoms->atom[i].resnr = resnr-1;

    /* atomname */
    memcpy(name,line+10,5);
    atoms->atomname[i]=put_symtab(symtab,name);
   
    /* eventueel controle atomnumber met i+1 */

    /* coordinates (start after residue shit) */
    ptr = line + 20;
    /* Read fixed format */
    for(m=0; m<DIM; m++) {
      for(c=0; (c<ddist && ptr[0]); c++) {
	buf[c] = ptr[0];
	ptr++;
      }
      buf[c] = '\0';
      if (sscanf (buf,"%lf %lf",&x1,&x2) != 1) {
	gmx_fatal(FARGS,"Something is wrong in the coordinate formatting of file %s. Note that gro is fixed format (see the manual)",infile);
      } else {
	x[i][m] = x1;
      }
    }

    /* velocities (start after residues and coordinates) */
    if (v) {
      /* Read fixed format */
      for(m=0; m<DIM; m++) {
	for(c=0; (c<ddist && ptr[0]); c++) {
	  buf[c] = ptr[0];
	  ptr++;
	}
	buf[c] = '\0';
	if (sscanf (buf,"%lf",&x1) != 1) {
	  v[i][m] = 0;
	} else {
	  v[i][m] = x1;
	  bVel = TRUE;
	}
      }
    }
  }
  atoms->nres=newres;

  /* box */
  fgets2 (line,STRLEN,in);
  if (sscanf (line,"%lf%lf%lf",&x1,&y1,&z1) != 3) {
    sprintf(buf,"Bad box in file %s",infile);
    warning(buf);
    
    /* Generate a cubic box */
    for(m=0; (m<DIM); m++)
      xmin[m]=xmax[m]=x[0][m];
    for(i=1; (i<atoms->nr); i++)
      for(m=0; (m<DIM); m++) {
	xmin[m]=min(xmin[m],x[i][m]);
	xmax[m]=max(xmax[m],x[i][m]);
      }
    for (i=0; i<DIM; i++) for (m=0; m<DIM; m++) box[i][m]=0.0;
    for(m=0; (m<DIM); m++)
      box[m][m]=(xmax[m]-xmin[m]);
    fprintf(stderr,"Generated a cubic box %8.3f x %8.3f x %8.3f\n",
	    box[XX][XX],box[YY][YY],box[ZZ][ZZ]);
  }
  else {
    /* We found the first three values, the diagonal elements */
    box[XX][XX]=x1;
    box[YY][YY]=y1;
    box[ZZ][ZZ]=z1;
    if (sscanf (line,"%*f%*f%*f%lf%lf%lf%lf%lf%lf",
		&x1,&y1,&z1,&x2,&y2,&z2) != 6) 
      x1=y1=z1=x2=y2=z2=0.0;
    box[XX][YY] = x1;
    box[XX][ZZ] = y1;
    box[YY][XX] = z1;
    box[YY][ZZ] = x2;
    box[ZZ][XX] = y2;
    box[ZZ][YY] = z2;
  }
  close_symtab(symtab);

  return bVel;
}