Wrong output while parsing a .sql file - sql

I need to write a simple c program that takes a particular dump of a table as input and arrange it in a particular way in the output. I'm trying to parse the information I need and put them inside the memory, but I have a problem. I've outputed my data, and I can see "strange chars" as output. Here's the code:
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
typedef struct entityTail
{
char entity[50];
struct entityTail* next;
} entityTail;
typedef struct keyTail
{
char key[300];
struct keyTail* next;
} keyTail;
typedef struct eventTail
{
char event[5];
struct eventTail* next;
} eventTail;
void setATuple(entityTail* entityNew, entityTail* entityNext, keyTail* keyNew, keyTail* keyNext, eventTail* eventNew, eventTail* eventNext, char* startOfParam);
int main(int argc, char* argv[])
{
if(argc != 2)
{
printf("Only 1 param needed: the filename");
return -1;
}
char* buffer = NULL; //this buffer will contain all our conf file
long size = 0; //in bytes
long length = 0; //in chars, must match the "size" variable
FILE* hFile;
bool exit = false;
char* startOfTuple = NULL;
bool headsSet = false; //used within a cycle
entityTail* entityHead = (entityTail*) malloc(sizeof(entityTail));
keyTail* keyHead = (keyTail*) malloc(sizeof(keyTail));
eventTail* eventHead = (eventTail*) malloc(sizeof(eventTail));
entityTail* theEntityTail = NULL;
keyTail* theKeyTail = NULL;
eventTail* theEventTail = NULL;
hFile = fopen( argv[1], "r"); //opening the file in "read-only" mode
if (hFile == NULL)
{
printf("Error: the input file doesn't exist\n");
return -2; //error opening the file
}
//retrieving the size (in bytes) of my text file
fseek (hFile , 0 , SEEK_END); //point to the end of the file
size = ftell (hFile); //retrieving the size of the file
rewind (hFile); //point to the start
// allocate memory to contain the whole file:
buffer = malloc (sizeof(char) * size);
if (buffer == NULL)
{
printf("Error: memory error\n");
return -3; //memory error
}
// copy the file into the buffer:
length = fread (buffer,1,size,hFile); //reading "size" elements of 1 byte, stored in hFile
if (length != size)
{
printf("Error: read error\n");
return -4; //reading error, length and size doesn't match
}
/* the whole file is now loaded in the memory buffer. */
// terminate
fclose (hFile);
//now we look for the position where our data starts
//our entity param is just an int, so it will be not enclosed by the ' symbol
startOfTuple = strstr(buffer, "VALUES"); //finding "VALUES" inside our table dump
startOfTuple = strstr(startOfTuple + 1, "("); //now we point to our first tuple
//now we process the rest of our file
while(!exit)
{
entityTail* entityNew = (entityTail*) malloc(sizeof(entityTail));
keyTail* keyNew = (keyTail*) malloc(sizeof(keyTail));
eventTail* eventNew = (eventTail*) malloc(sizeof(eventTail));
if(!headsSet) //we need to set our heads
{
setATuple(entityHead, NULL, keyHead, NULL, eventHead, NULL, startOfTuple);
theEntityTail = entityHead;
theKeyTail = keyHead;
theEventTail = eventHead;
headsSet = true;
printf("\n%s %s %s\n", entityHead->entity, keyHead->key, eventHead->event);
}
else
{
setATuple(entityNew, theEntityTail, keyNew, theKeyTail, eventNew, theEventTail, startOfTuple);
theEntityTail = entityNew;
theKeyTail = keyNew;
theEventTail = eventNew;
printf("\n%s %s %s\n", entityNew->entity, keyNew->key, eventNew->event);
exit = true; //debugging purpose
}
startOfTuple = strchr(startOfTuple + 1 , '('); //pointing to the next tuple
if(startOfTuple == NULL) exit = true;
}
return 0;
}
void setATuple(entityTail* entityNew, entityTail* entityNext, keyTail* keyNew, keyTail* keyNext, eventTail* eventNew, eventTail* eventNext, char* startOfParam)
{
int i = 0;
char* endOfParam = NULL;
//first we reach the "entity" param (an integer)
for(i = 0; i < 3; i++)
{
startOfParam = strchr(startOfParam + 1, ',');
endOfParam = strchr(startOfParam + 1, ',');
}
//now we set the entityHead
if(entityNext != NULL)
entityNew->next = entityNext;
else //we're setting the heads
entityNew->next = NULL;
strncpy(entityNew->entity, startOfParam + 1, endOfParam - startOfParam - 1);
//now we set the keyHead; that param is enclosed by two ' symbols
startOfParam = strchr(endOfParam + 1, '\''); //we look now for the ' symbol, it's easier that look for a comma and then remove the ' symbol
endOfParam = strchr(startOfParam + 1, '\''); //it should work even if that field in the database is empty
if(keyNext != NULL)
keyNew->next = keyNext;
else
keyNew->next = NULL;
strncpy(keyNew->key, startOfParam + 1, endOfParam - startOfParam - 1);
//now we set the eventHead
startOfParam = strchr(endOfParam + 1, '\''); //we look now for the ' symbol, it's easier that look for a comma and then remove the ' symbol
endOfParam = strchr(startOfParam + 1, '\''); //it should work even if that field in the database is empty
if(eventNext != NULL)
eventNew->next = eventNext;
else
eventNew->next = NULL;
strncpy(eventNew->event, startOfParam + 1, endOfParam - startOfParam - 1);
}
I think the problem is related to the function setATuple, but I can't figure out what's wrong.
Since it's a specific file-related program, I'm going to copy the file it's supposed to process. Here it is:
-- MySQL dump 10.13 Distrib 5.5.24, for debian-linux-gnu (i686)
--
-- Host: localhost Database: tesi
-- ------------------------------------------------------
-- Server version 5.5.24-0ubuntu0.12.04.1
/*!40101 SET #OLD_CHARACTER_SET_CLIENT=##CHARACTER_SET_CLIENT */;
/*!40101 SET #OLD_CHARACTER_SET_RESULTS=##CHARACTER_SET_RESULTS */;
/*!40101 SET #OLD_COLLATION_CONNECTION=##COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;
/*!40103 SET #OLD_TIME_ZONE=##TIME_ZONE */;
/*!40103 SET TIME_ZONE='+00:00' */;
/*!40014 SET #OLD_UNIQUE_CHECKS=##UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET #OLD_FOREIGN_KEY_CHECKS=##FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET #OLD_SQL_MODE=##SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET #OLD_SQL_NOTES=##SQL_NOTES, SQL_NOTES=0 */;
--
-- Table structure for table `log`
--
DROP TABLE IF EXISTS `log`;
/*!40101 SET #saved_cs_client = ##character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `log` (
`eid` int(11) NOT NULL AUTO_INCREMENT,
`system` int(11) NOT NULL,
`host` varchar(15) NOT NULL,
`entity` int(30) NOT NULL,
`key` varchar(40) NOT NULL,
`event` varchar(5) NOT NULL,
`timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`eid`),
KEY `event` (`event`),
CONSTRAINT `log_ibfk_1` FOREIGN KEY (`event`) REFERENCES `events` (`name`)
) ENGINE=InnoDB AUTO_INCREMENT=238 DEFAULT CHARSET=latin1;
/*!40101 SET character_set_client = #saved_cs_client */;
--
-- Dumping data for table `log`
--
LOCK TABLES `log` WRITE;
/*!40000 ALTER TABLE `log` DISABLE KEYS */;
INSERT INTO `log` VALUES (1,1,'127.000.000.001',0,'10','CMP','2012-10-09 15:13:37'),(2,1,'127.000.000.001',0,'19','CMP','2012-10-09 15:13:37'),(3,1,'127.000.000.001',0,'38','CMP','2012-10-09 15:13:37'),(4,1,'127.000.000.001',0,'77','CMP','2012-10-09 15:13:37'),(5,1,'127.000.000.001',0,'108','CMP','2012-10-09 15:13:37'),(6,1,'127.000.000.001',0,'119','CMP','2012-10-09 15:13:37'),(7,1,'127.000.000.001',0,'149','CMP','2012-10-09 15:13:37'),(8,1,'127.000.000.001',0,'154','CMP','2012-10-09 15:13:38'),(9,1,'127.000.000.001',1,'34','CMP','2012-10-09 15:13:38'),(10,1,'127.000.000.001',1,'143','CMP','2012-10-09 15:13:38'),(11,1,'127.000.000.001',2,'10','CMP','2012-10-09 15:13:38'),(12,1,'127.000.000.001',2,'30','CMP','2012-10-09 15:13:38'),(13,1,'127.000.000.001',2,'87','CMP','2012-10-09 15:13:38'),(14,1,'127.000.000.001',2,'102','CMP','2012-10-09 15:13:39'),(15,1,'127.000.000.001',2,'125','CMP','2012-10-09 15:13:39'),(16,1,'127.000.000.001',2,'161','CMP','2012-10-09 15:13:39'),(17,1,'127.000.000.001',2,'163','CMP','2012-10-09 15:13:39'),(18,1,'127.000.000.001',2,'181','CMP','2012-10-09 15:13:39'),(19,1,'127.000.000.001',2,'182','CMP','2012-10-09 15:13:39'),(20,1,'127.000.000.001',2,'183','CMP','2012-10-09 15:13:39'),(21,1,'127.000.000.001',3,'0','CMP','2012-10-09 15:13:39'),(22,1,'127.000.000.001',3,'40','CMP','2012-10-09 15:13:39'),(23,1,'127.000.000.001',3,'43','CMP','2012-10-09 15:13:39'),(24,1,'127.000.000.001',3,'101','CMP','2012-10-09 15:13:39'),(25,1,'127.000.000.001',3,'126','CMP','2012-10-09 15:13:40'),(26,1,'127.000.000.001',3,'190','CMP','2012-10-09 15:13:40'),(27,1,'127.000.000.001',4,'21','CMP','2012-10-09 15:13:40'),(28,1,'127.000.000.001',4,'22','CMP','2012-10-09 15:13:40'),(29,1,'127.000.000.001',4,'75','CMP','2012-10-09 15:13:40'),(30,1,'127.000.000.001',4,'88','CMP','2012-10-09 15:13:40'),(31,1,'127.000.000.001',4,'110','CMP','2012-10-09 15:13:40'),(32,1,'127.000.000.001',4,'182','CMP','2012-10-09 15:13:40'),(33,1,'127.000.000.001',5,'66','CMP','2012-10-09 15:13:40'),(34,1,'127.000.000.001',5,'90','CMP','2012-10-09 15:13:41'),(35,1,'127.000.000.001',5,'193','CMP','2012-10-09 15:13:41'),(36,1,'127.000.000.001',6,'57','CMP','2012-10-09 15:13:41'),(37,1,'127.000.000.001',6,'67','CMP','2012-10-09 15:13:41'),(38,1,'127.000.000.001',6,'71','CMP','2012-10-09 15:13:41'),(39,1,'127.000.000.001',6,'73','SER','2012-10-09 15:13:41'),(40,1,'127.000.000.001',6,'90','CMP','2012-10-09 15:13:41'),(41,1,'127.000.000.001',6,'91','CMP','2012-10-09 15:13:41'),(42,1,'127.000.000.001',6,'112','CMP','2012-10-09 15:13:41'),(43,1,'127.000.000.001',6,'126','CMP','2012-10-09 15:13:41'),(44,1,'127.000.000.001',6,'173','CMP','2012-10-09 15:13:41'),(45,1,'127.000.000.001',7,'20','CMP','2012-10-09 15:13:41'),(46,1,'127.000.000.001',7,'22','CMP','2012-10-09 15:13:42'),(47,1,'127.000.000.001',7,'33','CMP','2012-10-09 15:13:42'),(48,1,'127.000.000.001',7,'73','CMP','2012-10-09 15:13:42'),(49,1,'127.000.000.001',7,'97','CMP','2012-10-09 15:13:42'),(50,1,'127.000.000.001',7,'126','CMP','2012-10-09 15:13:42'),(51,1,'127.000.000.001',7,'127','CMP','2012-10-09 15:13:42'),(52,1,'127.000.000.001',7,'170','CMP','2012-10-09 15:13:42'),(53,1,'127.000.000.001',7,'189','CMP','2012-10-09 15:13:42'),(54,1,'127.000.000.001',8,'5','CMP','2012-10-09 15:13:42'),(55,1,'127.000.000.001',8,'80','CMP','2012-10-09 15:13:43'),(56,1,'127.000.000.001',8,'90','CMP','2012-10-09 15:13:43'),(57,1,'127.000.000.001',8,'102','CMP','2012-10-09 15:13:43'),(58,1,'127.000.000.001',8,'158','CMP','2012-10-09 15:13:43'),(59,1,'127.000.000.001',8,'185','CMP','2012-10-09 15:13:43'),(60,1,'127.000.000.001',9,'22','CMP','2012-10-09 15:13:43'),(61,1,'127.000.000.001',9,'34','CMP','2012-10-09 15:13:43'),(62,1,'127.000.000.001',9,'50','CMP','2012-10-09 15:13:43'),(63,1,'127.000.000.001',9,'51','CMP','2012-10-09 15:13:43'),(64,1,'127.000.000.001',9,'89','CMP','2012-10-09 15:13:43'),(65,1,'127.000.000.001',9,'110','CMP','2012-10-09 15:13:43'),(66,1,'127.000.000.001',9,'137','CMP','2012-10-09 15:13:43'),(67,1,'127.000.000.001',9,'141','CMP','2012-10-09 15:13:44'),(68,1,'127.000.000.001',9,'186','CMP','2012-10-09 15:13:44'),(69,1,'127.000.000.001',9,'194','CMP','2012-10-09 15:13:44'),(70,1,'127.000.000.001',10,'23','CMP','2012-10-09 15:13:44'),(71,1,'127.000.000.001',10,'42','CMP','2012-10-09 15:13:44'),(72,1,'127.000.000.001',10,'51','CMP','2012-10-09 15:13:44'),(73,1,'127.000.000.001',10,'52','CMP','2012-10-09 15:13:44'),(74,1,'127.000.000.001',11,'44','CMP','2012-10-09 15:13:44'),(75,1,'127.000.000.001',11,'57','CMP','2012-10-09 15:13:44'),(76,1,'127.000.000.001',11,'123','CMP','2012-10-09 15:13:45'),(77,1,'127.000.000.001',11,'125','CMP','2012-10-09 15:13:45'),(78,1,'127.000.000.001',11,'145','CMP','2012-10-09 15:13:45'),(79,1,'127.000.000.001',12,'6','CMP','2012-10-09 15:13:45'),(80,1,'127.000.000.001',12,'26','CMP','2012-10-09 15:13:45'),(81,1,'127.000.000.001',12,'28','CMP','2012-10-09 15:13:45'),(82,1,'127.000.000.001',12,'61','CMP','2012-10-09 15:13:45'),(83,1,'127.000.000.001',12,'117','CMP','2012-10-09 15:13:45'),(84,1,'127.000.000.001',12,'134','CMP','2012-10-09 15:13:45'),(85,1,'127.000.000.001',12,'139','CMP','2012-10-09 15:13:45'),(86,1,'127.000.000.001',12,'158','CMP','2012-10-09 15:13:45'),(87,1,'127.000.000.001',12,'186','CMP','2012-10-09 15:13:45'),(88,1,'127.000.000.001',12,'189','CMP','2012-10-09 15:13:45'),(89,1,'127.000.000.001',12,'191','CMP','2012-10-09 15:13:46'),(90,1,'127.000.000.001',12,'193','CMP','2012-10-09 15:13:46'),(91,1,'127.000.000.001',13,'31','CMP','2012-10-09 15:13:46'),(92,1,'127.000.000.001',13,'93','CMP','2012-10-09 15:13:46'),(93,1,'127.000.000.001',13,'109','CMP','2012-10-09 15:13:46'),(94,1,'127.000.000.001',13,'149','CMP','2012-10-09 15:13:46'),(95,1,'127.000.000.001',14,'5','CMP','2012-10-09 15:13:46'),(96,1,'127.000.000.001',14,'24','CMP','2012-10-09 15:13:46'),(97,1,'127.000.000.001',14,'128','CMP','2012-10-09 15:13:47'),(98,1,'127.000.000.001',14,'142','CMP','2012-10-09 15:13:47'),(99,1,'127.000.000.001',14,'161','CMP','2012-10-09 15:13:47'),(100,1,'127.000.000.001',15,'17','CMP','2012-10-09 15:13:47'),(101,1,'127.000.000.001',15,'19','CMP','2012-10-09 15:13:47'),(102,1,'127.000.000.001',15,'27','CMP','2012-10-09 15:13:47'),(103,1,'127.000.000.001',15,'71','CMP','2012-10-09 15:13:47'),(104,1,'127.000.000.001',15,'74','CMP','2012-10-09 15:13:47'),(105,1,'127.000.000.001',15,'104','CMP','2012-10-09 15:13:47'),(106,1,'127.000.000.001',15,'126','CMP','2012-10-09 15:13:48'),(107,1,'127.000.000.001',15,'143','CMP','2012-10-09 15:13:48'),(108,1,'127.000.000.001',15,'155','CMP','2012-10-09 15:13:48'),(109,1,'127.000.000.001',15,'185','CMP','2012-10-09 15:13:48'),(110,1,'127.000.000.001',16,'69','CMP','2012-10-09 15:13:48'),(111,1,'127.000.000.001',16,'103','CMP','2012-10-09 15:13:48'),(112,1,'127.000.000.001',16,'139','CMP','2012-10-09 15:13:48'),(113,1,'127.000.000.001',16,'169','CMP','2012-10-09 15:13:48'),(114,1,'127.000.000.001',17,'51','CMP','2012-10-09 15:13:48'),(115,1,'127.000.000.001',17,'67','CMP','2012-10-09 15:13:49'),(116,1,'127.000.000.001',17,'138','CMP','2012-10-09 15:13:49'),(117,1,'127.000.000.001',17,'162','CMP','2012-10-09 15:13:49'),(118,1,'127.000.000.001',17,'173','CMP','2012-10-09 15:13:49'),(119,1,'127.000.000.001',17,'185','CMP','2012-10-09 15:13:49'),(120,1,'127.000.000.001',18,'17','CMP','2012-10-09 15:13:49'),(121,1,'127.000.000.001',18,'57','CMP','2012-10-09 15:13:49'),(122,1,'127.000.000.001',18,'107','CMP','2012-10-09 15:13:49'),(123,1,'127.000.000.001',18,'163','CMP','2012-10-09 15:13:50'),(124,1,'127.000.000.001',18,'193','CMP','2012-10-09 15:13:50'),(125,1,'127.000.000.001',19,'3','CMP','2012-10-09 15:13:50'),(126,1,'127.000.000.001',19,'11','CMP','2012-10-09 15:13:50'),(127,1,'127.000.000.001',19,'36','CMP','2012-10-09 15:13:50'),(128,1,'127.000.000.001',19,'109','CMP','2012-10-09 15:13:50'),(129,1,'127.000.000.001',19,'126','CMP','2012-10-09 15:13:50'),(130,1,'127.000.000.001',19,'194','CMP','2012-10-09 15:13:50'),(131,1,'127.000.000.001',19,'196','CMP','2012-10-09 15:13:50'),(132,1,'127.000.000.001',0,'19','IER','2012-10-09 15:13:55'),(133,1,'127.000.000.001',0,'20','SER','2012-10-09 15:13:55'),(134,1,'127.000.000.001',0,'174','SER','2012-10-09 15:13:55'),(135,1,'127.000.000.001',0,'199','IER','2012-10-09 15:13:55'),(136,1,'127.000.000.001',1,'140','SER','2012-10-09 15:13:55'),(137,1,'127.000.000.001',1,'147','SER','2012-10-09 15:13:56'),(138,1,'127.000.000.001',1,'164','IER','2012-10-09 15:13:56'),(139,1,'127.000.000.001',1,'167','IER','2012-10-09 15:13:56'),(140,1,'127.000.000.001',1,'183','IER','2012-10-09 15:13:56'),(141,1,'127.000.000.001',2,'29','IER','2012-10-09 15:13:56'),(142,1,'127.000.000.001',2,'33','IER','2012-10-09 15:13:56'),(143,1,'127.000.000.001',2,'129','IER','2012-10-09 15:13:56'),(144,1,'127.000.000.001',2,'155','SER','2012-10-09 15:13:56'),(145,1,'127.000.000.001',2,'180','IER','2012-10-09 15:13:56'),(146,1,'127.000.000.001',3,'8','SER','2012-10-09 15:13:57'),(147,1,'127.000.000.001',3,'25','SER','2012-10-09 15:13:57'),(148,1,'127.000.000.001',3,'33','SER','2012-10-09 15:13:57'),(149,1,'127.000.000.001',3,'109','SER','2012-10-09 15:13:57'),(150,1,'127.000.000.001',3,'144','IER','2012-10-09 15:13:57'),(151,1,'127.000.000.001',4,'13','SER','2012-10-09 15:13:57'),(152,1,'127.000.000.001',4,'56','SER','2012-10-09 15:13:57'),(153,1,'127.000.000.001',4,'94','SER','2012-10-09 15:13:58'),(154,1,'127.000.000.001',4,'125','IER','2012-10-09 15:13:58'),(155,1,'127.000.000.001',4,'171','SER','2012-10-09 15:13:58'),(156,1,'127.000.000.001',4,'199','SER','2012-10-09 15:13:58'),(157,1,'127.000.000.001',5,'4','IER','2012-10-09 15:13:58'),(158,1,'127.000.000.001',5,'93','SER','2012-10-09 15:13:58'),(159,1,'127.000.000.001',5,'94','SER','2012-10-09 15:13:58'),(160,1,'127.000.000.001',6,'8','IER','2012-10-09 15:13:58'),(161,1,'127.000.000.001',6,'103','IER','2012-10-09 15:13:59'),(162,1,'127.000.000.001',6,'107','SER','2012-10-09 15:13:59'),(163,1,'127.000.000.001',6,'154','IER','2012-10-09 15:13:59'),(164,1,'127.000.000.001',6,'167','SER','2012-10-09 15:13:59'),(165,1,'127.000.000.001',7,'14','SER','2012-10-09 15:13:59'),(166,1,'127.000.000.001',7,'42','SER','2012-10-09 15:13:59'),(167,1,'127.000.000.001',7,'109','IER','2012-10-09 15:13:59'),(168,1,'127.000.000.001',7,'115','SER','2012-10-09 15:13:59'),(169,1,'127.000.000.001',7,'132','IER','2012-10-09 15:14:00'),(170,1,'127.000.000.001',7,'148','IER','2012-10-09 15:14:00'),(171,1,'127.000.000.001',7,'162','IER','2012-10-09 15:14:00'),(172,1,'127.000.000.001',8,'13','IER','2012-10-09 15:14:00'),(173,1,'127.000.000.001',8,'33','SER','2012-10-09 15:14:00'),(174,1,'127.000.000.001',8,'57','IER','2012-10-09 15:14:00'),(175,1,'127.000.000.001',8,'65','IER','2012-10-09 15:14:00'),(176,1,'127.000.000.001',8,'84','SER','2012-10-09 15:14:00'),(177,1,'127.000.000.001',8,'90','IER','2012-10-09 15:14:00'),(178,1,'127.000.000.001',9,'9','IER','2012-10-09 15:14:01'),(179,1,'127.000.000.001',9,'78','IER','2012-10-09 15:14:01'),(180,1,'127.000.000.001',9,'92','SER','2012-10-09 15:14:01'),(181,1,'127.000.000.001',9,'114','SER','2012-10-09 15:14:01'),(182,1,'127.000.000.001',10,'54','SER','2012-10-09 15:14:01'),(183,1,'127.000.000.001',10,'79','SER','2012-10-09 15:14:01'),(184,1,'127.000.000.001',10,'86','SER','2012-10-09 15:14:01'),(185,1,'127.000.000.001',10,'91','SER','2012-10-09 15:14:01'),(186,1,'127.000.000.001',10,'97','SER','2012-10-09 15:14:01'),(187,1,'127.000.000.001',10,'158','SER','2012-10-09 15:14:02'),(188,1,'127.000.000.001',11,'56','IER','2012-10-09 15:14:02'),(189,1,'127.000.000.001',11,'132','SER','2012-10-09 15:14:02'),(190,1,'127.000.000.001',11,'136','IER','2012-10-09 15:14:02'),(191,1,'127.000.000.001',11,'163','SER','2012-10-09 15:14:02'),(192,1,'127.000.000.001',11,'165','IER','2012-10-09 15:14:02'),(193,1,'127.000.000.001',12,'55','IER','2012-10-09 15:14:02'),(194,1,'127.000.000.001',12,'137','SER','2012-10-09 15:14:02'),(195,1,'127.000.000.001',12,'142','IER','2012-10-09 15:14:02'),(196,1,'127.000.000.001',12,'192','IER','2012-10-09 15:14:03'),(197,1,'127.000.000.001',13,'53','IER','2012-10-09 15:14:03'),(198,1,'127.000.000.001',13,'56','SER','2012-10-09 15:14:03'),(199,1,'127.000.000.001',13,'135','IER','2012-10-09 15:14:03'),(200,1,'127.000.000.001',13,'139','SER','2012-10-09 15:14:03'),(201,1,'127.000.000.001',13,'143','IER','2012-10-09 15:14:03'),(202,1,'127.000.000.001',13,'155','IER','2012-10-09 15:14:03'),(203,1,'127.000.000.001',13,'178','IER','2012-10-09 15:14:03'),(204,1,'127.000.000.001',13,'181','IER','2012-10-09 15:14:03'),(205,1,'127.000.000.001',13,'182','SER','2012-10-09 15:14:03'),(206,1,'127.000.000.001',14,'25','SER','2012-10-09 15:14:04'),(207,1,'127.000.000.001',14,'55','IER','2012-10-09 15:14:04'),(208,1,'127.000.000.001',14,'66','SER','2012-10-09 15:14:04'),(209,1,'127.000.000.001',14,'70','SER','2012-10-09 15:14:04'),(210,1,'127.000.000.001',14,'86','SER','2012-10-09 15:14:04'),(211,1,'127.000.000.001',14,'93','SER','2012-10-09 15:14:04'),(212,1,'127.000.000.001',14,'108','IER','2012-10-09 15:14:04'),(213,1,'127.000.000.001',14,'183','SER','2012-10-09 15:14:04'),(214,1,'127.000.000.001',15,'24','IER','2012-10-09 15:14:04'),(215,1,'127.000.000.001',15,'65','IER','2012-10-09 15:14:04'),(216,1,'127.000.000.001',15,'153','IER','2012-10-09 15:14:05'),(217,1,'127.000.000.001',15,'157','SER','2012-10-09 15:14:05'),(218,1,'127.000.000.001',16,'60','IER','2012-10-09 15:14:05'),(219,1,'127.000.000.001',16,'108','IER','2012-10-09 15:14:05'),(220,1,'127.000.000.001',16,'148','IER','2012-10-09 15:14:05'),(221,1,'127.000.000.001',16,'170','IER','2012-10-09 15:14:05'),(222,1,'127.000.000.001',16,'181','SER','2012-10-09 15:14:05'),(223,1,'127.000.000.001',17,'20','IER','2012-10-09 15:14:05'),(224,1,'127.000.000.001',17,'134','SER','2012-10-09 15:14:06'),(225,1,'127.000.000.001',17,'200','IER','2012-10-09 15:14:06'),(226,1,'127.000.000.001',18,'4','SER','2012-10-09 15:14:06'),(227,1,'127.000.000.001',18,'63','IER','2012-10-09 15:14:06'),(228,1,'127.000.000.001',18,'74','SER','2012-10-09 15:14:06'),(229,1,'127.000.000.001',18,'84','SER','2012-10-09 15:14:06'),(230,1,'127.000.000.001',18,'88','IER','2012-10-09 15:14:06'),(231,1,'127.000.000.001',18,'94','SER','2012-10-09 15:14:06'),(232,1,'127.000.000.001',18,'108','IER','2012-10-09 15:14:06'),(233,1,'127.000.000.001',19,'24','SER','2012-10-09 15:14:07'),(234,1,'127.000.000.001',19,'88','SER','2012-10-09 15:14:07'),(235,1,'127.000.000.001',19,'137','IER','2012-10-09 15:14:07'),(236,1,'127.000.000.001',19,'142','SER','2012-10-09 15:14:07'),(237,1,'127.000.000.001',19,'187','SER','2012-10-09 15:14:07');
/*!40000 ALTER TABLE `log` ENABLE KEYS */;
It "dies" as soon as it reaches the second tuple. Sorry for my poor english, I'm from Italy. Thank you for your help!

I was unable to debug your code; :-(, however I rewrote this code, see if you can use it:
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
/*
* Apparently only interested in 4,5 & 6th comma separated values
* strtok_r() should be preferred over strtok(); Windows MINGW doesn't have it
*/
int process_record(char *recordPtr/* and , your DataStructure Ptr if necessary */)
{
unsigned count;
char* fieldPtr = NULL;
fprintf(stderr, "\nFields :");
for (count = 1; NULL != (fieldPtr = strtok_r(NULL, ",", &recordPtr)); count++)
{
if (count > 3 && count < 7)
{// required fields range
/*TODO Trim unwanted characters */
switch (count)
{
case 4: // copy to relevant DS
break;
case 5: // copy to relevant DS
break;
case 6: // copy to relevant DS
break;
}
fprintf(stderr, "\t %s", fieldPtr);
}
}
return 0;
}
int main(int argc, char* argv[])
{
int status;
unsigned count;
unsigned readBytes = 0;
struct stat fStat;
unsigned fileSize ;
FILE* hFile;
char* fileData = NULL;
char* dataPtr =NULL;
char* recordPtr = NULL;
fprintf (stderr, "\n");
if (argc != 2)
{
fprintf(stderr, "\nERROR: Only <filename> required");
return -1;
}
/*
* Get the file size for Memory Load
*/
status = stat(argv[1], &fStat);
if (status < 0) {
fprintf(stderr, "\nERROR: Line[%d] ErroNo[%d]", __LINE__, errno);
return -2;
}
fileSize = fStat.st_size;
fprintf (stderr, "\nDump File size[%u]", fileSize);
/*
* Allocate sufficient memory to load file data on to memory
*/
fileData = (char*) malloc (sizeof(char) * fileSize);
if (NULL == fileData) {
fprintf(stderr, "\nERROR: Allocating memory");
return -3;
}
/* Open file and read data on to memory
*/
hFile = fopen( argv[1], "r"); //opening the file in "read-only" mode
if (hFile == NULL)
{
fprintf(stderr, "ERROR: Opening file[%s] ErroNo[%d]\n", argv[1], errno);
return -4; //error opening the file
}
/* assuming file will be read within 3 attempts */
for (status =0; fileSize != readBytes && status < 3; status ++) {
readBytes += fread (fileData + readBytes, 1, fileSize - readBytes, hFile);
fprintf (stderr, "\nData read Size [%u]", readBytes);
}
fclose (hFile);
//fprintf (stderr, "\nNOTE: Data read[\n%s\n]", fileData);
/*
* Chunk it into manageable records
*/
dataPtr = strstr (fileData, "VALUES (") + strlen ("VALUES ("); //handle error checks
for(count =1; NULL != (recordPtr = strtok_r(NULL, "()", &dataPtr)); count ++) {
if (strlen(recordPtr) > 1) { // NOTE: "," between each record will be tokenised
//fprintf (stderr, "\nRecord[%d] : [%s]", count, recordPtr);
/* Process Record
*/
process_record (recordPtr /* and , your DataStructure Ptr if necessary */);
}
}
free (fileData);
return 0;
}

Related

How to Get Remote Proc address of injected DLL into another process

This application is created
1) Console Application
2) InjectedDLL - DLL Project for inject into the process
1) the console application i have taken notepad.exe process id and inject my DLL into the notepad.
2) I have Created one exported method in the injected dll.
3) Now after injecting dll into notepad , i require the proc address of that exported method.
I have writted code here to get it but it's is not calling that methods and crash it.
I am attaching sample code this here. for run it only need to give full path of the dll.
const WCHAR INJECTED_DLL_FULL_PATH[] = L"FULL PATH OF DLL";
Only change this path, everything else will work.
I am unable to get the proc address of the injected dll.
anyone can help me on that.
/
Console Application code
/ DLLInjection.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <Windows.h>
#include <stdlib.h>
#include "RemoteOperation.h"
#include <stdio.h>
#include <tchar.h>
#include <tlhelp32.h>
BOOL InjectDLL();
void EjectDLL();
HANDLE m_hRemoteThread;
HANDLE m_hProcess;
void* m_pLibRemoteAddress;
DWORD m_dwhLibModule;
BOOL m_bIsDLLInjected;
DWORD m_dwProcessID;
HWND m_hCaptureWnd;
const WCHAR INJECTED_DLL[] = L"InjectedDLL.dll";
const WCHAR INJECTED_DLL_FULL_PATH[] = L"FULL PATH OF DLL";
DWORD GetProcessIdEx(LPCWSTR szExeName);
typedef void (WINAPI *test)();
test _test = NULL;
int main()
{
InjectDLL();
HMODULE hDLLModule = GetRemoteModuleHandle(m_hProcess, INJECTED_DLL);
_test = (test)GetRemoteProcAddress(m_hProcess, hDLLModule, "test");
_test();
EjectDLL();
return 0;
}
DWORD GetProcessIdEx(LPCWSTR szExeName)
{
DWORD dwRet = 0;
DWORD dwCount = 0;
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnapshot != INVALID_HANDLE_VALUE)
{
PROCESSENTRY32 pe = { 0 };
pe.dwSize = sizeof(PROCESSENTRY32);
BOOL bRet = Process32First(hSnapshot, &pe);
while (bRet)
{
OutputDebugString(pe.szExeFile);
OutputDebugString(L"\n");
if (!wcscmp(szExeName, pe.szExeFile))
{
dwCount++;
dwRet = pe.th32ProcessID;
break;
}
bRet = Process32Next(hSnapshot, &pe);
}
if (dwCount > 1)
dwRet = 0xFFFFFFFF;
CloseHandle(hSnapshot);
}
return dwRet;
}
BOOL InjectDLL()
{
m_hRemoteThread = NULL;
m_hProcess = NULL;
m_pLibRemoteAddress = NULL;
m_dwhLibModule = 0;
char chardllPath[MAX_PATH] = "\0";
wcstombs(chardllPath, INJECTED_DLL_FULL_PATH, MAX_PATH);
int Length = strlen(chardllPath);
HMODULE hKernel32 = ::GetModuleHandle(L"Kernel32");
LPVOID LoadLibraryPoniter = (LPVOID)GetProcAddress(hKernel32, "LoadLibraryA");
m_dwProcessID = GetProcessIdEx(L"notepad.exe");
m_hProcess = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION, FALSE, m_dwProcessID);
// 1. Allocate memory in the remote process for szLibPath
// 2. Write szLibPath to the allocated memory
m_pLibRemoteAddress = 0;
m_pLibRemoteAddress = ::VirtualAllocEx(m_hProcess, NULL, Length, MEM_COMMIT, PAGE_READWRITE);
if (m_pLibRemoteAddress == NULL)
{
CloseHandle(m_hProcess);
m_hProcess = NULL;
return false;
}
::WriteProcessMemory(m_hProcess, m_pLibRemoteAddress, (void*)chardllPath, Length, NULL);
// Load "dll" into the remote process
// (via CreateRemoteThread & LoadLibrary)
m_hRemoteThread = ::CreateRemoteThread(m_hProcess, NULL, NULL, (LPTHREAD_START_ROUTINE)LoadLibraryPoniter, (LPVOID)m_pLibRemoteAddress, 0, NULL);
m_bIsDLLInjected = true;
::WaitForSingleObject(m_hRemoteThread, INFINITE);
// Get handle of loaded module
m_dwhLibModule = 0;
::GetExitCodeThread(m_hRemoteThread, &m_dwhLibModule);
::CloseHandle(m_hRemoteThread);
m_hRemoteThread = NULL;
::VirtualFreeEx(m_hProcess, m_pLibRemoteAddress, Length, MEM_RELEASE);
m_pLibRemoteAddress = NULL;
return true;
}
void EjectDLL()
{
if (m_hProcess && m_bIsDLLInjected)
{
HMODULE hKernel32 = ::GetModuleHandle(L"Kernel32");
LPVOID LoadFreeLibraryPoniter = (LPVOID)GetProcAddress(hKernel32, "FreeLibrary");
HMODULE hDLLModule = GetRemoteModuleHandle(m_hProcess, INJECTED_DLL);
if (hDLLModule)
{
HANDLE hThread = ::CreateRemoteThread(m_hProcess, NULL, NULL, (LPTHREAD_START_ROUTINE)LoadFreeLibraryPoniter, (void*)hDLLModule, 0, NULL);
::WaitForSingleObject(hThread, INFINITE);
// Clean up
::CloseHandle(hThread);
}
}
if (m_hProcess)
{
CloseHandle(m_hProcess);
}
m_hProcess = NULL;
}
Remoteoperation.h
#pragma once
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
// Windows Header Files:
#include <windows.h>
#include <commctrl.h>
// C RunTime Header Files
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include <tchar.h>
#ifndef REM_OPS_H
#define REM_OPS_H
HMODULE WINAPI GetRemoteModuleHandle(HANDLE hProcess, LPCWSTR lpModuleName);
FARPROC WINAPI GetRemoteProcAddress(HANDLE hProcess, HMODULE hModule, LPCSTR lpProcName, UINT Ordinal = 0, BOOL UseOrdinal = FALSE);
BOOL RemoteLibraryFunction(HANDLE hProcess, LPCSTR lpModuleName, LPCSTR lpProcName, LPVOID lpParameters, SIZE_T dwParamSize, PVOID *ppReturn);
#endif //REM_OPS_H
// RemoteOperation.cpp
#include "stdafx.h"
/* RempteOps.cpp */
#include "stdafx.h" // SDKDDKVer.h, windows.h, stdlib.h, malloc.h, memory.h, tchar.h
#include "RemoteOperation.h" // Function prototypes
#include <string>
#include <windows.h>
#include <psapi.h>
using std::string;
//-----------------------------------------------------------------------------
HMODULE WINAPI GetRemoteModuleHandle(HANDLE hProcess, LPCWSTR lpModuleName)
{
HMODULE* ModuleArray = NULL;
DWORD ModuleArraySize = 200;
DWORD NumModules = 0;
WCHAR lpModuleNameCopy[MAX_PATH] = { 0 };
WCHAR ModuleNameBuffer[MAX_PATH] = { 0 };
/* Make sure we didn't get a NULL pointer for the module name */
if (lpModuleName == NULL)
goto GRMH_FAIL_JMP;
/* Convert lpModuleName to all lowercase so the comparison isn't case sensitive */
for (size_t i = 0; lpModuleName[i] != '\0'; ++i)
{
if (lpModuleName[i] >= 'A' && lpModuleName[i] <= 'Z')
lpModuleNameCopy[i] = lpModuleName[i] + 0x20; // 0x20 is the difference between uppercase and lowercase
else
lpModuleNameCopy[i] = lpModuleName[i];
lpModuleNameCopy[i + 1] = '\0';
}
/* Allocate memory to hold the module handles */
ModuleArray = new HMODULE[ModuleArraySize];
/* Check if the allocation failed */
if (ModuleArray == NULL)
goto GRMH_FAIL_JMP;
/* Get handles to all the modules in the target process */
if (!::EnumProcessModulesEx(hProcess, ModuleArray,
ModuleArraySize * sizeof(HMODULE), &NumModules, LIST_MODULES_ALL))
goto GRMH_FAIL_JMP;
/* We want the number of modules not the number of bytes */
NumModules /= sizeof(HMODULE);
/* Did we allocate enough memory for all the module handles? */
if (NumModules > ModuleArraySize)
{
delete[] ModuleArray; // Deallocate so we can try again
ModuleArray = NULL; // Set it to NULL se we can be sure if the next try fails
ModuleArray = new HMODULE[NumModules]; // Allocate the right amount of memory
/* Check if the allocation failed */
if (ModuleArray == NULL)
goto GRMH_FAIL_JMP;
ModuleArraySize = NumModules; // Update the size of the array
/* Get handles to all the modules in the target process */
if (!::EnumProcessModulesEx(hProcess, ModuleArray,
ModuleArraySize * sizeof(HMODULE), &NumModules, LIST_MODULES_ALL))
goto GRMH_FAIL_JMP;
/* We want the number of modules not the number of bytes */
NumModules /= sizeof(HMODULE);
}
/* Iterate through all the modules and see if the names match the one we are looking for */
for (DWORD i = 0; i <= NumModules; ++i)
{
/* Get the module's name */
::GetModuleBaseName(hProcess, ModuleArray[i],
ModuleNameBuffer, sizeof(ModuleNameBuffer));
/* Convert ModuleNameBuffer to all lowercase so the comparison isn't case sensitive */
for (size_t j = 0; ModuleNameBuffer[j] != '\0'; ++j)
{
if (ModuleNameBuffer[j] >= 'A' && ModuleNameBuffer[j] <= 'Z')
ModuleNameBuffer[j] += 0x20; // 0x20 is the difference between uppercase and lowercase
}
/* Does the name match? */
if (wcsstr(ModuleNameBuffer, lpModuleNameCopy) != NULL)
{
/* Make a temporary variable to hold return value*/
HMODULE TempReturn = ModuleArray[i];
/* Give back that memory */
delete[] ModuleArray;
/* Success */
return TempReturn;
}
/* Wrong module let's try the next... */
}
/* Uh Oh... */
GRMH_FAIL_JMP:
/* If we got to the point where we allocated memory we need to give it back */
if (ModuleArray != NULL)
delete[] ModuleArray;
/* Failure... */
return NULL;
}
//-----------------------------------------------------------------------------
FARPROC WINAPI GetRemoteProcAddress(HANDLE hProcess, HMODULE hModule, LPCSTR lpProcName, UINT Ordinal, BOOL UseOrdinal)
{
BOOL Is64Bit = FALSE;
MODULEINFO RemoteModuleInfo = { 0 };
UINT_PTR RemoteModuleBaseVA = 0;
IMAGE_DOS_HEADER DosHeader = { 0 };
DWORD Signature = 0;
IMAGE_FILE_HEADER FileHeader = { 0 };
IMAGE_OPTIONAL_HEADER64 OptHeader64 = { 0 };
IMAGE_OPTIONAL_HEADER32 OptHeader32 = { 0 };
IMAGE_DATA_DIRECTORY ExportDirectory = { 0 };
IMAGE_EXPORT_DIRECTORY ExportTable = { 0 };
UINT_PTR ExportFunctionTableVA = 0;
UINT_PTR ExportNameTableVA = 0;
UINT_PTR ExportOrdinalTableVA = 0;
DWORD* ExportFunctionTable = NULL;
DWORD* ExportNameTable = NULL;
WORD* ExportOrdinalTable = NULL;
/* Temporary variables not used until much later but easier
/* to define here than in all the the places they are used */
CHAR TempChar;
BOOL Done = FALSE;
/* Check to make sure we didn't get a NULL pointer for the name unless we are searching by ordinal */
if (lpProcName == NULL && !UseOrdinal)
goto GRPA_FAIL_JMP;
/* Get the base address of the remote module along with some other info we don't need */
if (!::GetModuleInformation(hProcess, hModule, &RemoteModuleInfo, sizeof(RemoteModuleInfo)))
goto GRPA_FAIL_JMP;
RemoteModuleBaseVA = (UINT_PTR)RemoteModuleInfo.lpBaseOfDll;
/* Read the DOS header and check it's magic number */
if (!::ReadProcessMemory(hProcess, (LPCVOID)RemoteModuleBaseVA, &DosHeader,
sizeof(DosHeader), NULL) || DosHeader.e_magic != IMAGE_DOS_SIGNATURE)
goto GRPA_FAIL_JMP;
/* Read and check the NT signature */
if (!::ReadProcessMemory(hProcess, (LPCVOID)(RemoteModuleBaseVA + DosHeader.e_lfanew),
&Signature, sizeof(Signature), NULL) || Signature != IMAGE_NT_SIGNATURE)
goto GRPA_FAIL_JMP;
/* Read the main header */
if (!::ReadProcessMemory(hProcess,
(LPCVOID)(RemoteModuleBaseVA + DosHeader.e_lfanew + sizeof(Signature)),
&FileHeader, sizeof(FileHeader), NULL))
goto GRPA_FAIL_JMP;
/* Which type of optional header is the right size? */
if (FileHeader.SizeOfOptionalHeader == sizeof(OptHeader64))
Is64Bit = TRUE;
else if (FileHeader.SizeOfOptionalHeader == sizeof(OptHeader32))
Is64Bit = FALSE;
else
goto GRPA_FAIL_JMP;
if (Is64Bit)
{
/* Read the optional header and check it's magic number */
if (!::ReadProcessMemory(hProcess,
(LPCVOID)(RemoteModuleBaseVA + DosHeader.e_lfanew + sizeof(Signature) + sizeof(FileHeader)),
&OptHeader64, FileHeader.SizeOfOptionalHeader, NULL)
|| OptHeader64.Magic != IMAGE_NT_OPTIONAL_HDR64_MAGIC)
goto GRPA_FAIL_JMP;
}
else
{
/* Read the optional header and check it's magic number */
if (!::ReadProcessMemory(hProcess,
(LPCVOID)(RemoteModuleBaseVA + DosHeader.e_lfanew + sizeof(Signature) + sizeof(FileHeader)),
&OptHeader32, FileHeader.SizeOfOptionalHeader, NULL)
|| OptHeader32.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC)
goto GRPA_FAIL_JMP;
}
/* Make sure the remote module has an export directory and if it does save it's relative address and size */
if (Is64Bit && OptHeader64.NumberOfRvaAndSizes >= IMAGE_DIRECTORY_ENTRY_EXPORT + 1)
{
ExportDirectory.VirtualAddress = (OptHeader64.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]).VirtualAddress;
ExportDirectory.Size = (OptHeader64.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]).Size;
}
else if (OptHeader32.NumberOfRvaAndSizes >= IMAGE_DIRECTORY_ENTRY_EXPORT + 1)
{
ExportDirectory.VirtualAddress = (OptHeader32.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]).VirtualAddress;
ExportDirectory.Size = (OptHeader32.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]).Size;
}
else
goto GRPA_FAIL_JMP;
/* Read the main export table */
if (!::ReadProcessMemory(hProcess, (LPCVOID)(RemoteModuleBaseVA + ExportDirectory.VirtualAddress),
&ExportTable, sizeof(ExportTable), NULL))
goto GRPA_FAIL_JMP;
/* Save the absolute address of the tables so we don't need to keep adding the base address */
ExportFunctionTableVA = RemoteModuleBaseVA + ExportTable.AddressOfFunctions;
ExportNameTableVA = RemoteModuleBaseVA + ExportTable.AddressOfNames;
ExportOrdinalTableVA = RemoteModuleBaseVA + ExportTable.AddressOfNameOrdinals;
/* Allocate memory for our copy of the tables */
ExportFunctionTable = new DWORD[ExportTable.NumberOfFunctions];
ExportNameTable = new DWORD[ExportTable.NumberOfNames];
ExportOrdinalTable = new WORD[ExportTable.NumberOfNames];
/* Check if the allocation failed */
if (ExportFunctionTable == NULL || ExportNameTable == NULL || ExportOrdinalTable == NULL)
goto GRPA_FAIL_JMP;
/* Get a copy of the function table */
if (!::ReadProcessMemory(hProcess, (LPCVOID)ExportFunctionTableVA,
ExportFunctionTable, ExportTable.NumberOfFunctions * sizeof(DWORD), NULL))
goto GRPA_FAIL_JMP;
/* Get a copy of the name table */
if (!::ReadProcessMemory(hProcess, (LPCVOID)ExportNameTableVA,
ExportNameTable, ExportTable.NumberOfNames * sizeof(DWORD), NULL))
goto GRPA_FAIL_JMP;
/* Get a copy of the ordinal table */
if (!::ReadProcessMemory(hProcess, (LPCVOID)ExportOrdinalTableVA,
ExportOrdinalTable, ExportTable.NumberOfNames * sizeof(WORD), NULL))
goto GRPA_FAIL_JMP;
/* If we are searching for an ordinal we do that now */
if (UseOrdinal)
{
/* NOTE:
/* Microsoft's PE/COFF specification does NOT say we need to subtract the ordinal base
/* from our ordinal but it seems to always give the wrong function if we don't */
/* Make sure the ordinal is valid */
if (Ordinal < ExportTable.Base || (Ordinal - ExportTable.Base) >= ExportTable.NumberOfFunctions)
goto GRPA_FAIL_JMP;
UINT FunctionTableIndex = Ordinal - ExportTable.Base;
/* Check if the function is forwarded and if so get the real address*/
if (ExportFunctionTable[FunctionTableIndex] >= ExportDirectory.VirtualAddress &&
ExportFunctionTable[FunctionTableIndex] <= ExportDirectory.VirtualAddress + ExportDirectory.Size)
{
Done = FALSE;
string TempForwardString;
TempForwardString.clear(); // Empty the string so we can fill it with a new name
/* Get the forwarder string one character at a time because we don't know how long it is */
for (UINT_PTR i = 0; !Done; ++i)
{
/* Get next character */
if (!::ReadProcessMemory(hProcess,
(LPCVOID)(RemoteModuleBaseVA + ExportFunctionTable[FunctionTableIndex] + i),
&TempChar, sizeof(TempChar), NULL))
goto GRPA_FAIL_JMP;
TempForwardString.push_back(TempChar); // Add it to the string
/* If it's NUL we are done */
if (TempChar == (CHAR)'\0')
Done = TRUE;
}
/* Find the dot that seperates the module name and the function name/ordinal */
size_t Dot = TempForwardString.find('.');
if (Dot == string::npos)
goto GRPA_FAIL_JMP;
/* Temporary variables that hold parts of the forwarder string */
string RealModuleName, RealFunctionId;
RealModuleName = TempForwardString.substr(0, Dot - 1);
RealFunctionId = TempForwardString.substr(Dot + 1, string::npos);
WCHAR newModuleName[MAX_PATH] = L"\0";
swprintf_s(newModuleName, L"%s", RealModuleName.c_str());
HMODULE RealModule = GetRemoteModuleHandle(hProcess, newModuleName);
FARPROC TempReturn;// Make a temporary variable to hold return value
/* Figure out if the function was exported by name or by ordinal */
if (RealFunctionId.at(0) == '#') // Exported by ordinal
{
UINT RealOrdinal = 0;
RealFunctionId.erase(0, 1); // Remove '#' from string
/* My version of atoi() because I was too lazy to use the real one... */
for (size_t i = 0; i < RealFunctionId.size(); ++i)
{
if (RealFunctionId[i] >= '0' && RealFunctionId[i] <= '9')
{
RealOrdinal *= 10;
RealOrdinal += RealFunctionId[i] - '0';
}
else
break;
}
/* Recursively call this function to get return value */
TempReturn = GetRemoteProcAddress(hProcess, RealModule, NULL, RealOrdinal, TRUE);
}
else // Exported by name
{
/* Recursively call this function to get return value */
TempReturn = GetRemoteProcAddress(hProcess, RealModule, RealFunctionId.c_str(), 0, FALSE);
}
/* Give back that memory */
delete[] ExportFunctionTable;
delete[] ExportNameTable;
delete[] ExportOrdinalTable;
/* Success!!! */
return TempReturn;
}
else // Not Forwarded
{
/* Make a temporary variable to hold return value*/
FARPROC TempReturn = (FARPROC)(RemoteModuleBaseVA + ExportFunctionTable[FunctionTableIndex]);
/* Give back that memory */
delete[] ExportFunctionTable;
delete[] ExportNameTable;
delete[] ExportOrdinalTable;
/* Success!!! */
return TempReturn;
}
}
/* Iterate through all the names and see if they match the one we are looking for */
for (DWORD i = 0; i < ExportTable.NumberOfNames; ++i) {
string TempFunctionName;
Done = FALSE;// Reset for next name
TempFunctionName.clear(); // Empty the string so we can fill it with a new name
/* Get the function name one character at a time because we don't know how long it is */
for (UINT_PTR j = 0; !Done; ++j)
{
/* Get next character */
if (!::ReadProcessMemory(hProcess, (LPCVOID)(RemoteModuleBaseVA + ExportNameTable[i] + j),
&TempChar, sizeof(TempChar), NULL))
goto GRPA_FAIL_JMP;
TempFunctionName.push_back(TempChar); // Add it to the string
/* If it's NUL we are done */
if (TempChar == (CHAR)'\0')
Done = TRUE;
}
/* Does the name match? */
if (TempFunctionName.find(lpProcName) != string::npos)
{
/* NOTE:
/* Microsoft's PE/COFF specification says we need to subtract the ordinal base
/*from the value in the ordinal table but that seems to always give the wrong function */
/* Check if the function is forwarded and if so get the real address*/
if (ExportFunctionTable[ExportOrdinalTable[i]] >= ExportDirectory.VirtualAddress &&
ExportFunctionTable[ExportOrdinalTable[i]] <= ExportDirectory.VirtualAddress + ExportDirectory.Size)
{
Done = FALSE;
string TempForwardString;
TempForwardString.clear(); // Empty the string so we can fill it with a new name
/* Get the forwarder string one character at a time because we don't know how long it is */
for (UINT_PTR j = 0; !Done; ++j)
{
/* Get next character */
if (!::ReadProcessMemory(hProcess,
(LPCVOID)(RemoteModuleBaseVA + ExportFunctionTable[i] + j),
&TempChar, sizeof(TempChar), NULL))
goto GRPA_FAIL_JMP;
TempForwardString.push_back(TempChar); // Add it to the string
/* If it's NUL we are done */
if (TempChar == (CHAR)'\0')
Done = TRUE;
}
/* Find the dot that seperates the module name and the function name/ordinal */
size_t Dot = TempForwardString.find('.');
if (Dot == string::npos)
goto GRPA_FAIL_JMP;
/* Temporary variables that hold parts of the forwarder string */
string RealModuleName, RealFunctionId;
RealModuleName = TempForwardString.substr(0, Dot);
RealFunctionId = TempForwardString.substr(Dot + 1, string::npos);
WCHAR newModuleName[MAX_PATH] = L"\0";
swprintf_s(newModuleName, L"%s", RealModuleName.c_str());
HMODULE RealModule = GetRemoteModuleHandle(hProcess, newModuleName);
FARPROC TempReturn;// Make a temporary variable to hold return value
/* Figure out if the function was exported by name or by ordinal */
if (RealFunctionId.at(0) == '#') // Exported by ordinal
{
UINT RealOrdinal = 0;
RealFunctionId.erase(0, 1); // Remove '#' from string
/* My version of atoi() because I was to lazy to use the real one... */
for (size_t i = 0; i < RealFunctionId.size(); ++i)
{
if (RealFunctionId[i] >= '0' && RealFunctionId[i] <= '9')
{
RealOrdinal *= 10;
RealOrdinal += RealFunctionId[i] - '0';
}
else
break;
}
/* Recursively call this function to get return value */
TempReturn = GetRemoteProcAddress(hProcess, RealModule, NULL, RealOrdinal, TRUE);
}
else // Exported by name
{
/* Recursively call this function to get return value */
TempReturn = GetRemoteProcAddress(hProcess, RealModule, RealFunctionId.c_str(), 0, FALSE);
}
/* Give back that memory */
delete[] ExportFunctionTable;
delete[] ExportNameTable;
delete[] ExportOrdinalTable;
/* Success!!! */
return TempReturn;
}
else // Not Forwarded
{
/* Make a temporary variable to hold return value*/
FARPROC TempReturn;
/* NOTE:
/* Microsoft's PE/COFF specification says we need to subtract the ordinal base
/*from the value in the ordinal table but that seems to always give the wrong function */
//TempReturn = (FARPROC)(RemoteModuleBaseVA + ExportFunctionTable[ExportOrdinalTable[i] - ExportTable.Base]);
/* So we do it this way instead */
TempReturn = (FARPROC)(RemoteModuleBaseVA + ExportFunctionTable[ExportOrdinalTable[i]]);
/* Give back that memory */
delete[] ExportFunctionTable;
delete[] ExportNameTable;
delete[] ExportOrdinalTable;
/* Success!!! */
return TempReturn;
}
}
/* Wrong function let's try the next... */
}
/* Uh Oh... */
GRPA_FAIL_JMP:
/* If we got to the point where we allocated memory we need to give it back */
if (ExportFunctionTable != NULL)
delete[] ExportFunctionTable;
if (ExportNameTable != NULL)
delete[] ExportNameTable;
if (ExportOrdinalTable != NULL)
delete[] ExportOrdinalTable;
/* Falure... */
return NULL;
}
BOOL RemoteLibraryFunction(HANDLE hProcess, LPCSTR lpModuleName, LPCSTR lpProcName, LPVOID lpParameters, SIZE_T dwParamSize, PVOID *ppReturn)
{
LPVOID lpRemoteParams = NULL;
LPVOID lpFunctionAddress = GetProcAddress(GetModuleHandleA(lpModuleName), lpProcName);
if (!lpFunctionAddress) lpFunctionAddress = GetProcAddress(LoadLibraryA(lpModuleName), lpProcName);
if (!lpFunctionAddress) goto ErrorHandler;
if (lpParameters)
{
lpRemoteParams = VirtualAllocEx(hProcess, NULL, dwParamSize, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (!lpRemoteParams) goto ErrorHandler;
SIZE_T dwBytesWritten = 0;
BOOL result = WriteProcessMemory(hProcess, lpRemoteParams, lpParameters, dwParamSize, &dwBytesWritten);
if (!result || dwBytesWritten < 1) goto ErrorHandler;
}
HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)lpFunctionAddress, lpRemoteParams, NULL, NULL);
if (!hThread) goto ErrorHandler;
DWORD dwOut = 0;
while (GetExitCodeThread(hThread, &dwOut)) {
if (dwOut != STILL_ACTIVE) {
*ppReturn = (PVOID)dwOut;
break;
}
}
return TRUE;
ErrorHandler:
if (lpRemoteParams)
VirtualFreeEx(hProcess, lpRemoteParams, dwParamSize, MEM_RELEASE);
return FALSE;
}
Injectdl DLL Expoerted methods
#define EXPORT __declspec (dllexport)
EXPORT void test();
EXPORT void test()
{
::MessageBox(NULL, L"test", L"", MB_OK);
}
DLL Main cpp
// dllmain.cpp : Defines the entry point for the DLL application.
#include "stdafx.h"
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
{
::MessageBox(NULL, L"DLL Injected", L"", MB_OK);
}
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
def file
LIBRARY InjectedDLL
EXPORTS
test #1
That is a lot of code to debug. What you're having a problem with is writing an external version of GetProcAddress which walks the export table. Instead of taking the time to debug your code I will supply a code which I know works. It is not my own code but I have used it before, the original author is iPower.
#define ReCa reinterpret_cast
uintptr_t GetProcAddressEx(HANDLE hProcess, DWORD pid, const char* module, const char* function)
{
if (!module || !function || !pid || !hProcess)
return 0;
uintptr_t moduleBase = GetModuleBaseEx(module, pid); //toolhelp32snapshot method
if (!moduleBase)
return 0;
IMAGE_DOS_HEADER Image_Dos_Header = { 0 };
if (!ReadProcessMemory(hProcess, ReCa<LPCVOID>(moduleBase), &Image_Dos_Header, sizeof(IMAGE_DOS_HEADER), nullptr))
return 0;
if (Image_Dos_Header.e_magic != IMAGE_DOS_SIGNATURE)
return 0;
IMAGE_NT_HEADERS Image_Nt_Headers = { 0 };
if (!ReadProcessMemory(hProcess, ReCa<LPCVOID>(moduleBase + Image_Dos_Header.e_lfanew), &Image_Nt_Headers, sizeof(IMAGE_NT_HEADERS), nullptr))
return 0;
if (Image_Nt_Headers.Signature != IMAGE_NT_SIGNATURE)
return 0;
IMAGE_EXPORT_DIRECTORY Image_Export_Directory = { 0 };
uintptr_t img_exp_dir_rva = 0;
if (!(img_exp_dir_rva = Image_Nt_Headers.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress))
return 0;
if (!ReadProcessMemory(hProcess, ReCa<LPCVOID>(moduleBase + img_exp_dir_rva), &Image_Export_Directory, sizeof(IMAGE_EXPORT_DIRECTORY), nullptr))
return 0;
uintptr_t EAT = moduleBase + Image_Export_Directory.AddressOfFunctions;
uintptr_t ENT = moduleBase + Image_Export_Directory.AddressOfNames;
uintptr_t EOT = moduleBase + Image_Export_Directory.AddressOfNameOrdinals;
WORD ordinal = 0;
SIZE_T len_buf = strlen(function) + 1;
char* temp_buf = new char[len_buf];
for (size_t i = 0; i < Image_Export_Directory.NumberOfNames; i++)
{
uintptr_t tempRvaString = 0;
if (!ReadProcessMemory(hProcess, ReCa<LPCVOID>(ENT + (i * sizeof(uintptr_t))), &tempRvaString, sizeof(uintptr_t), nullptr))
return 0;
if (!ReadProcessMemory(hProcess, ReCa<LPCVOID>(moduleBase + tempRvaString), temp_buf, len_buf, nullptr))
return 0;
if (!lstrcmpi(function, temp_buf))
{
if (!ReadProcessMemory(hProcess, ReCa<LPCVOID>(EOT + (i * sizeof(WORD))), &ordinal, sizeof(WORD), nullptr))
return 0;
uintptr_t temp_rva_func = 0;
if (!ReadProcessMemory(hProcess, ReCa<LPCVOID>(EAT + (ordinal * sizeof(uintptr_t))), &temp_rva_func, sizeof(uintptr_t), nullptr))
return 0;
delete[] temp_buf;
return moduleBase + temp_rva_func;
}
}
delete[] temp_buf;
return 0;
}

*** Error in `./text_buffer': corrupted double-linked list: 0x089cbd98 **

I'm trying to make the app using FreeTDS. Following are my code
/*
* Purpose: Test to see if row buffering and blobs works correctly.
* Functions: dbbind dbnextrow dbopen dbresults dbsqlexec dbgetrow
*/
#include "common.h"
#include "stdio.h"
#include<stdlib.h>
#include "readline/readline.h"
#include "readline/history.h"
#include "string.h"
int
main(int argc, char **argv)
{
char failed;
int hasil;
char ch;
char* r = malloc(30);
LOGINREC *login;
DBPROCESS *dbproc;
int i;
int p = 0;
char teststr[1024];
DBINT testint;
read_login_info(argc, argv);
fprintf(stdout, "Starting %s\n", argv[0]);
/* Fortify_EnterScope(); */
while(1)
{
char qrcode[50];
char perintahsql[100] = "select * from REF_COBA where id=";
char *alokasi="";
while(ch != '\n') // terminates if user hit enter
{
ch = getchar();
qrcode[p] = ch;
p++;
}
qrcode[p]='\0';
strcpy(r,qrcode);
alokasi = strsep(&r, ",");
strcpy(r,"");
p=0;
ch = "";
dbinit();
dberrhandle(syb_err_handler);
dbmsghandle(syb_msg_handler);
fprintf(stdout, "About to logon\n");
login = dblogin();
DBSETLPWD(login, PASSWORD);
DBSETLUSER(login, USER);
DBSETLAPP(login, "text_buffer");
//DBSETLHOST(login, "ntbox.dntis.ro");
DBSETLHOST(login, "192.168.1.9");
fprintf(stdout, "About to open\n");
dbproc = dbopen(login, SERVER);
if (strlen(DATABASE))
dbuse(dbproc, DATABASE);
dbloginfree(login);
#ifdef MICROSOFT_DBLIB
dbsetopt(dbproc, DBBUFFER, "100");
#else
dbsetopt(dbproc, DBBUFFER, "100", 0);
#endif
dbcmd(dbproc, strcat(perintahsql,alokasi));
dbsqlexec(dbproc);
if (dbresults(dbproc) != SUCCEED)
{
failed = 1;
fprintf(stdout, "Was expecting a result set.");
exit(1);
}
fprintf(stdout, "select\n");
for (i = 1; i <= dbnumcols(dbproc); i++)
printf("col %d is %s\n", i, dbcolname(dbproc, i));
fprintf(stdout, "setelah for\n");
dbbind(dbproc, 1, INTBIND, 0, (BYTE *) & testint);
dbbind(dbproc, 2, CHARBIND, 0, (BYTE *) teststr);
for (i = 1; i < 2; i++)
{
char expected[1024];
sprintf(expected, "row %03d", i);
if (i % 100 == 0)
{
dbclrbuf(dbproc, 100);
}
if (REG_ROW != dbnextrow(dbproc))
{
failed = 1;
fprintf(stderr, "Failed. Expected a row\n");
//exit(1);
}
else
{
fprintf(stdout, "jalanin usb\n");
printf("Read a row of data -> %d %s\n", (int) testint, teststr);
hasil = system("/opt/usb1rc_linux USB1REL-172 R");
sleep(2);
hasil = system("/opt/usb1rc_linux USB1REL-172 r");
}
}
dbfreebuf(dbproc);
dbexit();
}
return 0;
}
I modified the source from FreeTDS, after compilation there are some warning
bash-4.2# make text_buffer
CC text_buffer.o
text_buffer.c: In function 'main':
text_buffer.c:54:8: warning: assignment makes integer from pointer without a cast [enabled by default]
ch = "";
^
text_buffer.c:18:7: warning: variable 'hasil' set but not used [-Wunused-but-set-variable]
int hasil;
^
text_buffer.c:17:8: warning: variable 'failed' set but not used [-Wunused-but-set-variable]
char failed;
^
CC common.o
CCLD text_buffer
I execute the program without error. This program will check input from user then run the sql command. The format of input shall be , e.g 123456,john doe then press enter. After 50-60 times of input, the double-linked list error will happen.
could anybody help why the error happen?

GNU Radio circular buffer manipulation

I encountered the following error
gr::log :WARN: tpb_thread_body - asynchronous message buffer overflowing, dropping message
Out of serendipity, I ran into this GNU Radio presentation on
Youtube.
The presenter mentioned an OOT block he called "buffer" that is capable of eliminating the "buffer overflowing" error. Apparently, this block plays with different sample rates and the so-called "circular buffers". I haven't worked with circular buffers myself. Any ideas on circular buffers or any hints on how to build this buffer block are welcome.
EDIT
Below is the flowgraph that generates the error. As it was suggested in the comments, the culprits could be the message processing blocks (red-circled) namely generateCADU (for generating standard CCSDS frames) and processCADU (for extracting CADUs from a data stream).
The implementation file of the generateCADU block is given below
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <gnuradio/io_signature.h>
#include "generateCADU_impl.h"
#include "fec/ReedSolomon/ReedSolomon.h"
#include "fec/Scrambler/Scrambler.h"
namespace gr {
namespace ccsds {
generateCADU::sptr
generateCADU::make(int frameLength,std::string sync, int scramble, int rs, int intDepth)
{
return gnuradio::get_initial_sptr
(new generateCADU_impl(frameLength, sync, scramble, rs, intDepth));
}
/*
* The private constructor
*/
generateCADU_impl::generateCADU_impl(int frameLength,std::string sync, int scramble, int rs, int intDepth)
: gr::sync_block("generateCADU",
gr::io_signature::make(1, 1, sizeof(unsigned char)),
gr::io_signature::make(0, 0, 0)),
d_frameLength(frameLength),d_scramble(scramble == 1),d_rs(rs >= 1), d_basis(rs >= 2), d_intDepth(intDepth)
{
set_output_multiple(d_frameLength);
//Registering output port
message_port_register_out(pmt::mp("out"));
d_sync = parse_string(sync);
}
/*
* Our virtual destructor.
*/
generateCADU_impl::~generateCADU_impl()
{
}
unsigned char
generateCADU_impl::parse_hex(char c)
{
if ('0' <= c && c <= '9') return c - '0';
if ('A' <= c && c <= 'F') return c - 'A' + 10;
if ('a' <= c && c <= 'f') return c - 'a' + 10;
std::abort();
}
std::vector<unsigned char>
generateCADU_impl::parse_string(const std::string & s)
{
if (s.size() % 2 != 0) std::abort();
std::vector<unsigned char> result(s.size() / 2);
for (std::size_t i = 0; i != s.size() / 2; ++i)
result[i] = 16 * parse_hex(s[2 * i]) + parse_hex(s[2 * i + 1]);
return result;
}
int
generateCADU_impl::work(int noutput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items)
{
const unsigned char *in = (const unsigned char *) input_items[0];
//Reed-Solomon and Scrambler objects
ReedSolomon RS(16,d_intDepth,d_basis);// False = conventional, True = dual-basis
Scrambler S;
//Buffers
unsigned char *frameBuffer1 = (unsigned char*)malloc(d_frameLength*sizeof(unsigned char));
std::vector<unsigned char> frameBuffer2;
//The work function engine
for(int i = 0; (i + d_frameLength) < noutput_items; i += d_frameLength)
{
//Copying data from input stream
memcpy(frameBuffer1,in + i + d_frameLength,d_frameLength);
//Copying frame into std::vector buffer
frameBuffer2.insert(frameBuffer2.begin(),frameBuffer1, frameBuffer1 + d_frameLength);
//Optional scrambling and Reed-Solomon
if (d_rs) RS.Encode_RS(frameBuffer2);
if (d_scramble) S.Scramble(frameBuffer2);
//Insert sync word
frameBuffer2.insert(frameBuffer2.begin(), d_sync.begin(), d_sync.end());
//Transmitting PDU
pmt::pmt_t pdu(pmt::cons(pmt::PMT_NIL,pmt::make_blob(frameBuffer2.data(),frameBuffer2.size())));
message_port_pub(pmt::mp("out"), pdu);
//Clear buffer
frameBuffer2.clear();
}
// Tell runtime system how many output items we produced.
return noutput_items;
}
} /* namespace ccsds */
} /* namespace gr */
And here is the processCADU block. This block uses tags generated by the synchronizeCADU (which is simply a wrapper for the correlate_access_tag block) to extract CADUs
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <gnuradio/io_signature.h>
#include "processCADU_impl.h"
#include "fec/ReedSolomon/ReedSolomon.h"
#include "fec/Scrambler/Scrambler.h"
namespace gr {
namespace ccsds {
processCADU::sptr
processCADU::make(int frameLength, int scramble, int rs, int intDepth, std::string tagName)
{
return gnuradio::get_initial_sptr
(new processCADU_impl(frameLength, scramble, rs, intDepth, tagName));
}
/*
* The private constructor
*/
processCADU_impl::processCADU_impl(int frameLength, int scramble, int rs, int intDepth, std::string tagName)
: gr::sync_block("processCADU",
gr::io_signature::make(1, 1, sizeof(unsigned char)),
gr::io_signature::make(0, 0, 0)),
d_frameLength(frameLength),d_scramble(scramble == 1),d_rs(rs >= 1), d_basis(rs >= 2), d_intDepth(intDepth)
{
//Multiple input
set_output_multiple(d_frameLength * 8);
//Registering output port
message_port_register_out(pmt::mp("out"));
if (d_rs) d_frameLength += 32 * d_intDepth;
//SEtting tag name
key = pmt::mp(tagName);
}
/*
* Our virtual destructor.
*/
processCADU_impl::~processCADU_impl()
{
delete d_pack;
}
int
processCADU_impl::work(int noutput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items)
{
const unsigned char *in = (const unsigned char *) input_items[0];
unsigned char *out = (unsigned char *) output_items[0];
void *msg_data = NULL;
unsigned char frame_data[d_frameLength];
unsigned char frame_len = 0;
std::vector<unsigned char> frameBuffer;
//Reed-Solomon and Scrambler objects
ReedSolomon RS(16,d_intDepth,d_basis);// False = conventional, True = dual-basis
std::vector<int> errors;//errors.push_back(0);
Scrambler S;
d_tags.clear();
d_pack = new blocks::kernel::pack_k_bits(8);
this->get_tags_in_window(d_tags, 0, 0, noutput_items,key);
for(d_tags_itr = d_tags.begin(); d_tags_itr != d_tags.end(); d_tags_itr++) {
// Check that we have enough data for a full frame
if ((d_tags_itr->offset - this->nitems_read(0)) > (noutput_items - (d_frameLength) * 8))
{
return (d_tags_itr->offset - this->nitems_read(0) - 1);
}
//Pack bits into bytes
d_pack->pack(frame_data, &in[d_tags_itr->offset - this->nitems_read(0)], d_frameLength);
//Copying frame into std::vector buffer
frameBuffer.insert(frameBuffer.begin(),frame_data, frame_data + d_frameLength);
//Optional scrambling and Reed-Solomon
if (d_scramble) S.Scramble(frameBuffer);
//if (d_rs) RS.Decode_RS(frameBuffer,errors);
//If there is Reed-Solomon decoding
if(d_rs)
{
RS.Decode_RS(frameBuffer,errors);
if (RS.Success(errors)) // Success
{
//std::cout << "Success" << std::endl;
pmt::pmt_t pdu(pmt::cons(pmt::PMT_NIL,pmt::make_blob(frameBuffer.data(),frameBuffer.size())));
message_port_pub(pmt::mp("out"), pdu);
/*for(int i=0; i < errors.size(); i++)
{
//std::cout << "Number of Errors : " << errors.at(i) << std::endl << std::endl;
}*/
}
else // Failure
{
std::cout << "RS failure" << std::endl;
}
}
else{
pmt::pmt_t pdu(pmt::cons(pmt::PMT_NIL,pmt::make_blob(frameBuffer.data(),frameBuffer.size())));
message_port_pub(pmt::mp("out"), pdu);
}
//Clear buffers
frameBuffer.clear();
errors.clear();
}
// Tell runtime system how many output items we produced.
return noutput_items;
}
} /* namespace ccsds */
} /* namespace gr */
Regards,
M
Thanks to #MarcusMüller suggestion, using the tagged_stream paradigma as opposed to PDUs solved the problem. I was able to transmit 47 terabytes of data without any problems. Below is the code for the newly implemented block.
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <gnuradio/io_signature.h>
#include "genCADU_impl.h"
namespace gr {
namespace ccsds {
genCADU::sptr
genCADU::make(int frameLength,std::string sync, int scramble, int rs, int intDepth, std::string len_tag_key)
{
return gnuradio::get_initial_sptr
(new genCADU_impl(frameLength, sync, scramble, rs, intDepth, len_tag_key));
}
/*
* The private constructor
*/
genCADU_impl::genCADU_impl(int frameLength,std::string sync, int scramble, int rs, int intDepth, std::string len_tag_key)
: gr::tagged_stream_block("genCADU",
gr::io_signature::make(1, 1, sizeof(unsigned char)),
gr::io_signature::make(1, 1, sizeof(unsigned char)),len_tag_key),
d_frameLength(frameLength),d_scramble(scramble == 1),d_rs(rs >= 1), d_basis(rs >= 2), d_intDepth(intDepth)
{
//Synchronization pattern
d_sync = parse_string(sync);
//Reed-Solomon and Scrambler objects
RS = new ReedSolomon(16,d_intDepth,d_basis);// False = conventional, True = dual-basis
S = new Scrambler();
}
/*
* Our virtual destructor.
*/
genCADU_impl::~genCADU_impl()
{
delete RS;
delete S;
}
int
genCADU_impl::calculate_output_stream_length(const gr_vector_int &ninput_items)
{
int noutput_items = (d_rs) ? d_frameLength + 32*d_intDepth + d_sync.size() : d_frameLength + d_sync.size();
return noutput_items ;
}
unsigned char
genCADU_impl::parse_hex(char c)
{
if ('0' <= c && c <= '9') return c - '0';
if ('A' <= c && c <= 'F') return c - 'A' + 10;
if ('a' <= c && c <= 'f') return c - 'a' + 10;
std::abort();
}
std::vector<unsigned char>
genCADU_impl::parse_string(const std::string & s)
{
if (s.size() % 2 != 0) std::abort();
std::vector<unsigned char> result(s.size() / 2);
for (std::size_t i = 0; i != s.size() / 2; ++i)
result[i] = 16 * parse_hex(s[2 * i]) + parse_hex(s[2 * i + 1]);
return result;
}
int
genCADU_impl::work (int noutput_items,
gr_vector_int &ninput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items)
{
const unsigned char *in = (const unsigned char *) input_items[0];
unsigned char *out = (unsigned char *) output_items[0];
int total_len;
//Copy pdu from circular buffer to local buffer
buffer.insert(buffer.end(), in, in + d_frameLength);
//Optional scrambling and Reed-Solomon. TO DO: Turbo and LDPC
if (d_rs) RS->Encode_RS(buffer);
if (d_scramble) S->Scramble(buffer);
//Insert sync word
buffer.insert(buffer.begin(), d_sync.begin(), d_sync.end());
//Copy from local buffer to circular buffer
std::copy(buffer.begin(),buffer.end(),out);
//Clear the local buffer
total_len = buffer.size();
buffer.clear();
// Tell runtime system how many output items we produced.
return total_len;
}
} /* namespace ccsds */
} /* namespace gr */
Regards,
M.

How to change this app to disable input from command line?

This is the Original code:
#include <stdio.h>
#include <string.h>
#include <assert.h>
#if defined(_WIN32) && !defined(__CYGWIN__)
#include <windows.h>
#else
#include <sys/select.h>
#endif
#include <sphinxbase/err.h>
#include <sphinxbase/ad.h>
#include "pocketsphinx.h"
static const arg_t cont_args_def[] = {
POCKETSPHINX_OPTIONS,
/* Argument file. */
{"-argfile",
ARG_STRING,
NULL,
"Argument file giving extra arguments."},
{"-adcdev",
ARG_STRING,
NULL,
"Name of audio device to use for input."},
{"-infile",
ARG_STRING,
NULL,
"Audio file to transcribe."},
{"-inmic",
ARG_BOOLEAN,
"no",
"Transcribe audio from microphone."},
{"-time",
ARG_BOOLEAN,
"no",
"Print word times in file transcription."},
CMDLN_EMPTY_OPTION
};
static ps_decoder_t *ps;
static cmd_ln_t *config;
static FILE *rawfd;
static void
print_word_times()
{
int frame_rate = cmd_ln_int32_r(config, "-frate");
ps_seg_t *iter = ps_seg_iter(ps);
while (iter != NULL) {
int32 sf, ef, pprob;
float conf;
ps_seg_frames(iter, &sf, &ef);
pprob = ps_seg_prob(iter, NULL, NULL, NULL);
conf = logmath_exp(ps_get_logmath(ps), pprob);
printf("%s %.3f %.3f %f\n", ps_seg_word(iter), ((float)sf / frame_rate),
((float) ef / frame_rate), conf);
iter = ps_seg_next(iter);
}
}
static int
check_wav_header(char *header, int expected_sr)
{
int sr;
if (header[34] != 0x10) {
E_ERROR("Input audio file has [%d] bits per sample instead of 16\n", header[34]);
return 0;
}
if (header[20] != 0x1) {
E_ERROR("Input audio file has compression [%d] and not required PCM\n", header[20]);
return 0;
}
if (header[22] != 0x1) {
E_ERROR("Input audio file has [%d] channels, expected single channel mono\n", header[22]);
return 0;
}
sr = ((header[24] & 0xFF) | ((header[25] & 0xFF) << 8) | ((header[26] & 0xFF) << 16) | ((header[27] & 0xFF) << 24));
if (sr != expected_sr) {
E_ERROR("Input audio file has sample rate [%d], but decoder expects [%d]\n", sr, expected_sr);
return 0;
}
return 1;
}
/*
* Continuous recognition from a file
*/
static void
recognize_from_file()
{
int16 adbuf[2048];
const char *fname;
const char *hyp;
int32 k;
uint8 utt_started, in_speech;
int32 print_times = cmd_ln_boolean_r(config, "-time");
fname = cmd_ln_str_r(config, "-infile");
if ((rawfd = fopen(fname, "rb")) == NULL) {
E_FATAL_SYSTEM("Failed to open file '%s' for reading",
fname);
}
if (strlen(fname) > 4 && strcmp(fname + strlen(fname) - 4, ".wav") == 0) {
char waveheader[44];
fread(waveheader, 1, 44, rawfd);
if (!check_wav_header(waveheader, (int)cmd_ln_float32_r(config, "-samprate")))
E_FATAL("Failed to process file '%s' due to format mismatch.\n", fname);
}
if (strlen(fname) > 4 && strcmp(fname + strlen(fname) - 4, ".mp3") == 0) {
E_FATAL("Can not decode mp3 files, convert input file to WAV 16kHz 16-bit mono before decoding.\n");
}
ps_start_utt(ps);
utt_started = FALSE;
while ((k = fread(adbuf, sizeof(int16), 2048, rawfd)) > 0) {
ps_process_raw(ps, adbuf, k, FALSE, FALSE);
in_speech = ps_get_in_speech(ps);
if (in_speech && !utt_started) {
utt_started = TRUE;
}
if (!in_speech && utt_started) {
ps_end_utt(ps);
hyp = ps_get_hyp(ps, NULL);
if (hyp != NULL)
printf("%s\n", hyp);
if (print_times)
print_word_times();
fflush(stdout);
ps_start_utt(ps);
utt_started = FALSE;
}
}
ps_end_utt(ps);
if (utt_started) {
hyp = ps_get_hyp(ps, NULL);
if (hyp != NULL) {
printf("%s\n", hyp);
if (print_times) {
print_word_times();
}
}
}
fclose(rawfd);
}
/* Sleep for specified msec */
static void
sleep_msec(int32 ms)
{
#if (defined(_WIN32) && !defined(GNUWINCE)) || defined(_WIN32_WCE)
Sleep(ms);
#else
/* ------------------- Unix ------------------ */
struct timeval tmo;
tmo.tv_sec = 0;
tmo.tv_usec = ms * 1000;
select(0, NULL, NULL, NULL, &tmo);
#endif
}
/*
* Main utterance processing loop:
* for (;;) {
* start utterance and wait for speech to process
* decoding till end-of-utterance silence will be detected
* print utterance result;
* }
*/
static void
recognize_from_microphone()
{
ad_rec_t *ad;
int16 adbuf[2048];
uint8 utt_started, in_speech;
int32 k;
char const *hyp;
if ((ad = ad_open_dev(cmd_ln_str_r(config, "-adcdev"),
(int) cmd_ln_float32_r(config,
"-samprate"))) == NULL)
E_FATAL("Failed to open audio device\n");
if (ad_start_rec(ad) < 0)
E_FATAL("Failed to start recording\n");
if (ps_start_utt(ps) < 0)
E_FATAL("Failed to start utterance\n");
utt_started = FALSE;
E_INFO("Ready....\n");
for (;;) {
if ((k = ad_read(ad, adbuf, 2048)) < 0)
E_FATAL("Failed to read audio\n");
ps_process_raw(ps, adbuf, k, FALSE, FALSE);
in_speech = ps_get_in_speech(ps);
if (in_speech && !utt_started) {
utt_started = TRUE;
E_INFO("Listening...\n");
}
if (!in_speech && utt_started) {
/* speech -> silence transition, time to start new utterance */
ps_end_utt(ps);
hyp = ps_get_hyp(ps, NULL );
if (hyp != NULL) {
printf("%s\n", hyp);
fflush(stdout);
}
if (ps_start_utt(ps) < 0)
E_FATAL("Failed to start utterance\n");
utt_started = FALSE;
E_INFO("Ready....\n");
}
sleep_msec(100);
}
ad_close(ad);
}
int
main(int argc, char *argv[])
{
char const *cfg;
config = cmd_ln_parse_r(NULL, cont_args_def, argc, argv, TRUE);
/* Handle argument file as -argfile. */
if (config && (cfg = cmd_ln_str_r(config, "-argfile")) != NULL) {
config = cmd_ln_parse_file_r(config, cont_args_def, cfg, FALSE);
}
if (config == NULL || (cmd_ln_str_r(config, "-infile") == NULL && cmd_ln_boolean_r(config, "-inmic") == FALSE)) {
E_INFO("Specify '-infile <file.wav>' to recognize from file or '-inmic yes' to recognize from microphone.\n");
cmd_ln_free_r(config);
return 1;
}
ps_default_search_args(config);
ps = ps_init(config);
if (ps == NULL) {
cmd_ln_free_r(config);
return 1;
}
E_INFO("%s COMPILED ON: %s, AT: %s\n\n", argv[0], __DATE__, __TIME__);
if (cmd_ln_str_r(config, "-infile") != NULL) {
recognize_from_file();
} else if (cmd_ln_boolean_r(config, "-inmic")) {
recognize_from_microphone();
}
ps_free(ps);
cmd_ln_free_r(config);
return 0;
}
#if defined(_WIN32_WCE)
#pragma comment(linker,"/entry:mainWCRTStartup")
#include <windows.h>
//Windows Mobile has the Unicode main only
int
wmain(int32 argc, wchar_t * wargv[])
{
char **argv;
size_t wlen;
size_t len;
int i;
argv = malloc(argc * sizeof(char *));
for (i = 0; i < argc; i++) {
wlen = lstrlenW(wargv[i]);
len = wcstombs(NULL, wargv[i], wlen);
argv[i] = malloc(len + 1);
wcstombs(argv[i], wargv[i], wlen);
}
//assuming ASCII parameters
return main(argc, argv);
}
#endif
I can compile it by this command:
g++ -o output continuous.cpp -DMODELDIR=\"`pkg-config --variable=modeldir pocketsphinx`\" `pkg-config --cflags --libs pocketsphinx sphinxbase`
And run it by this command : output -inmic yes .
But I like to convert the code as it has no need to get inmic yes and it automatically starts the program from microphone. But I got segmentation fault(core dumped) error when I changed these parts:
static const arg_t cont_args_def= {"-inmic",
ARG_BOOLEAN,
"no",
"Transcribe audio from microphone."};
int main(int argc, char *argv[])
{
config = cmd_ln_parse_r(NULL, cont_args_def, argc, argv, TRUE);
if (cmd_ln_boolean_r(config, "-inmic")) {
recognize_from_microphone();
}
// recognize_from_microphone();
ps_free(ps);
cmd_ln_free_r(config);
return 0;
}
I searched a lot and red the documentation but couldn't understand what's the problem?
Change the last argument passed to cmd_ln_parse_r from TRUE to FALSE.
It has something to do with strict checking.
I figured this out by reading the source code for cmd_ln.c in the sphinxbase code.
I also changed the boolean value for -inmic in cont_args_def from "no" to "yes".

True non-blocking two-way communication between parent and external child process

I have read around 50 posts and tutorials on this topic, I have copied, written and tested around 20 alternatives and done every possible research I can think of. Still, I have not seen a working solution for the following problem:
Parent process A wants to pass data to an external process B, let process B modify the data and pass it back to parent process A, then continue with parent process A. Process B is part of an external program suite that I have no influence over, and that is normally run like this on the UNIX command line:
< input_data program_B1 | program_B2 | program_B3 > output_data
...where
input_data, output_data: Some data that is processed in programs B1-B3
program_B1,B2,B3: Programs that read data from stdin (fread) and output to stdout (fwrite) and apply some processing to the data.
So, in sequence:
(1) Parent process A passes data to child process B
(2) Child process B reads data and modifies it
(3) Child process B passes data back to parent process A
(4) Parent process A reads data and continues (for example passing it further on to a process B2..).
(5) Parent process A passes another data set to child process B etc.
The problem is, whatever I do, the program almost always ends up hanging on a read/fread (or write/fwrite?) to or from a pipe.
One important thing to note is that the parent process cannot simply close the pipes after passing data on to the child process, because it works in a loop and wants to pass another set of data to the child process once it has finished processing the first set.
Here is a working set of parent/child programs (compile with g++ pipe_parent.cc -o pipe_parent, g++ pipe_child.cc -o pipe_child) illustrating the problem with unnamed pipes. I have also tried named pipes, but not as extensively. Each execution can have a slightly different outcome. If the sleep statement is omitted in the parent, or the fflush() statement is omitted in the child, the pipes will almost surely block. If the amount of data to be passed on is increased, it will always block independent of the sleep or fflush.
Parent program A:
#include <cstring>
#include <cstdio>
#include <cstdlib>
extern "C" {
#include <unistd.h>
#include <fcntl.h>
}
using namespace std;
/*
* Parent-child inter-communication
* Child is external process
*/
int main() {
int fd[2];
if( pipe(fd) == -1 ) {
fprintf(stderr,"Unable to create pipe\n");
}
int fd_parentWrite = fd[1];
int fd_childRead = fd[0];
if( pipe(fd) == -1 ) {
fprintf(stderr,"Unable to create pipe\n");
exit(-1);
}
int fd_childWrite = fd[1];
int fd_parentRead = fd[0];
pid_t pid = fork();
if( pid == -1 ) {
fprintf(stderr,"Unable to fork new process\n");
exit(-1);
}
if( pid == 0 ) { // Child process
dup2( fd_childRead, fileno(stdin) ); // Redirect standard input(0) to child 'read pipe'
dup2( fd_childWrite, fileno(stdout) ); // Redirect standard output(1) to child 'write pipe'
close(fd_parentRead);
close(fd_parentWrite);
close(fd_childRead);
close(fd_childWrite);
// execl replaces child process with an external one
int ret = execl("/disk/sources/pipe_test/pipe_child","pipe_child",NULL);
fprintf(stderr,"External process failed, return code: %d...\n", ret);
exit(-1);
// Child process is done. Will not continue from here on
}
else { // Parent process
// Nothing to set up
}
// ...more code...
if( pid > 0 ) { // Parent process (redundant if statement)
int numElements = 10000;
int totalSize = numElements * sizeof(float);
float* buffer = new float[numElements];
for( int i = 0; i < numElements; i++ ) {
buffer[i] = (float)i;
}
for( int iter = 0; iter < 5; iter++ ) {
fprintf(stderr,"--------- Iteration #%d -----------\n", iter);
int sizeWrite = (int)write( fd_parentWrite, buffer, totalSize );
if( sizeWrite == -1 ) {
fprintf(stderr,"Parent process write error\n");
exit(-1);
}
fprintf(stderr,"Parent #%d: Wrote %d elements. Total size: %d\n", iter, sizeWrite, totalSize);
sleep(1); // <--- CHANGE!
int sizeRead = (int)read( fd_parentRead, buffer, totalSize );
if( sizeRead <= 0 ) {
fprintf(stderr,"Parent process read error\n");
}
while( sizeRead < totalSize ) {
fprintf(stderr,"Parent #%d: Read %d elements, continue reading...\n", iter, sizeRead);
int sizeNew = (int)read( fd_parentRead, &buffer[sizeRead], totalSize-sizeRead );
fprintf(stderr," ...newly read %d elements\n", sizeNew);
if( sizeNew < 0 ) {
exit(-1);
}
sizeRead += sizeNew;
}
fprintf(stderr,"Parent #%d: Read %d elements. Total size: %d\n", iter, sizeRead, totalSize);
fprintf(stderr,"Examples : %f %f %f\n", buffer[0], buffer[10], buffer[100]);
}
delete [] buffer;
}
close(fd_parentRead);
close(fd_parentWrite);
close(fd_childRead);
close(fd_childWrite);
return 0;
}
Child program B:
#include <cstdio>
using namespace std;
int main() {
int numElements = 10000;
int totalSize = numElements * sizeof(float);
float* buffer = new float[numElements];
int counter = 0;
int sizeRead = 0;
do {
sizeRead = fread( buffer, 1, totalSize, stdin);
fprintf(stderr,"Child #%d: Read %d elements, buffer100: %f\n", counter, sizeRead, buffer[100]);
if( sizeRead > 0 ) {
for( int i = 0; i < numElements; i++ ) {
buffer[i] += numElements;
}
int sizeWrite = fwrite( buffer, 1, totalSize, stdout);
fflush(stdout); // <--- CHANGE!
fprintf(stderr,"Child #%d: Wrote %d elements\n", counter, sizeWrite);
counter += 1;
}
} while( sizeRead > 0 );
return 0;
}
Is there any way to check when the pipe has enough data to be read? Or is there an alternative way to resolve the above problem, with or without pipes?
Please help!
Possibly the best solution when reading is to check with select whether you can read from the pipe. You can even pass a timeout. The alternative might be setting the O_NONBLOCK flag on file descriptor 0 (stdin) with fcntl, though I think the select way is better.
As with ensuring non-blocking write: that's a bit harder as you don't know how much you can write before the pipe blocks. One way (that I feel is very ugly) would be to only write 1 byte chunks and again check with select whether you can write. But that would be a performance killer, so use only if performance in communication is not an issue.
The first answer (using select to find out whether a pipe is ready to be read from) was good but didn't really solve my issue, see also my previous comments. Sooner or later I always ended up with a "race condition" where the program kept hanging either on a read or write.
The solution (maybe not be the only one?) is to run the child-to-parent data transfer in a different thread. I also went back and implemented the pipes as named pipes. It would probably also work with unnamed pipes but I didn't check that.
The final code is below. Note that no explicit flushing is required; the parent-to-child and child-to-parent data transfers are now decoupled. Any comments how this can be improved welcome! One residual problem I can see is that the pipes may fill up depending on how long time the child needs to process the data. I'm not sure how likely this is to happen. And by the way this worked fine with my external programs, not only with the provided child program.
Parent program A:
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <string>
#include <iostream>
extern "C" {
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h>
#include <signal.h>
#include <sys/wait.h>
#include <pthread.h>
}
using namespace std;
static int const READING = -1;
static int const BUFFER_READY = 1;
static int const FINISHED = 0;
/*
* Parent-child inter-communication
* Child is external process
*/
struct threadStruct {
FILE* file_c2p;
int sizeBuffer;
float* buffer;
int io_flag;
};
// Custom sleep function
void mini_sleep( int millisec ) {
struct timespec req={0},rem={0};
time_t sec = (int)(millisec/1000);
millisec = (int)(millisec-(sec*1000));
req.tv_sec = sec;
req.tv_nsec = millisec*1000000L;
nanosleep(&req,&rem);
}
// Function to be executed within separate thread: Reads in data from file pointer
// Hand-shaking with main thread is done via the flag 'io_flag'
void *threadFunction( void *arg ) {
threadStruct* ptr = (threadStruct*)arg;
ptr->io_flag = READING;
while( ptr->io_flag != FINISHED ) {
if( ptr->io_flag == READING ) {
int sizeRead = fread( ptr->buffer, 1, ptr->sizeBuffer, ptr->file_c2p );
if( sizeRead <= 0 ) {
ptr->io_flag = FINISHED;
return NULL;
}
ptr->io_flag = BUFFER_READY;
}
else {
mini_sleep(10);
}
}
return NULL;
}
//--------------------------------------------------
int main() {
std::string filename_p2c("/tmp/fifo11_p2c");
std::string filename_c2p("/tmp/fifo11_c2p");
fprintf(stderr,"..started\n");
int status = mknod(filename_p2c.c_str(), S_IRUSR | S_IWUSR | S_IFIFO, 0);
if( (status == -1) && (errno != EEXIST) ) {
fprintf(stderr,"Error creating named pipe: %s\n", strerror(errno));
exit(-1);
}
status = mknod(filename_c2p.c_str(), S_IRUSR | S_IWUSR | S_IFIFO, 0);
if( (status == -1) && (errno != EEXIST) ) {
fprintf(stderr,"Error creating named pipe: %s\n", strerror(errno));
exit(-1);
}
FILE* file_dump = fopen("parent_dump","w");
int fd_p2c;
int fd_c2p;
FILE* file_c2p = NULL;
//--------------------------------------------------
// Set up parent/child processes
//
pid_t pid = fork();
if( pid == -1 ) {
fprintf(stderr,"Unable to fork new process\n");
}
if( pid == 0 ) { // Child process
fd_p2c = open( filename_p2c.c_str(), O_RDONLY );
if( fd_p2c < 0 ) {
fprintf(stderr,"Child: Error opening the named pipe: %d %d '%s'\n", fd_p2c, errno, strerror(errno));
exit(-1);
}
fd_c2p = open( filename_c2p.c_str(), O_WRONLY );
if( fd_c2p < 0 ) {
fprintf(stderr,"Child: Error opening the named pipe: %d %d '%s'\n", fd_c2p, errno, strerror(errno));
exit(-1);
}
dup2(fd_p2c,fileno(stdin)); // Redirect standard input(0) to child 'read pipe'
dup2(fd_c2p,fileno(stdout)); // Redirect standard output(1) to child 'write pipe'
close(fd_p2c);
close(fd_c2p);
int ret = execl("/disk/sources/pipe_test/pipe_child","pipe_child",NULL);
fprintf(stderr,"External process failed, return code: %d...\n", ret);
kill( getppid(), 9 ); // Kill parent process
exit(-1);
}
else { // Parent process
fd_p2c = open( filename_p2c.c_str(), O_WRONLY );
if( fd_p2c < 0 ) {
fprintf(stderr,"Parent: Error opening the named pipe: %d %d '%s'\n", fd_p2c, errno, strerror(errno));
exit(-1);
}
file_c2p = fopen( filename_c2p.c_str(), "r");
fd_c2p = fileno( file_c2p );
if( fd_c2p < 0 ) {
fprintf(stderr,"Parent: Error opening the named pipe: %d %d '%s'\n", fd_c2p, errno, strerror(errno));
exit(-1);
}
}
int numElements = 10000;
int sizeBuffer = numElements * sizeof(float);
float* bufferIn = new float[numElements];
float* bufferOut = new float[numElements];
for( int i = 0; i < numElements; i++ ) {
bufferIn[i] = 0.0;
}
int numIterations = 5;
int numBytesAll = numElements * sizeof(float) * numIterations;
pthread_t thread;
threadStruct* threadParam = new threadStruct();
threadParam->file_c2p = file_c2p;
threadParam->sizeBuffer = sizeBuffer;
threadParam->buffer = bufferIn;
threadParam->io_flag = READING;
int thread_stat = pthread_create( &thread, NULL, threadFunction, threadParam );
if( thread_stat < 0 ) {
fprintf(stderr,"Error when creating thread\n");
exit(-1);
}
int readCounter = 0;
int numBytesWrite = 0;
int numBytesRead = 0;
for( int iter = 0; iter < numIterations; iter++ ) {
for( int i = 0; i < numElements; i++ ) {
bufferOut[i] = (float)i + iter*numElements*10;
}
int sizeWrite = (int)write( fd_p2c, bufferOut, sizeBuffer );
if( sizeWrite == -1 ) {
fprintf(stderr,"Parent process write error\n");
exit(-1);
}
numBytesWrite += sizeWrite;
fprintf(file_dump,"Parent #%d: Wrote %d/%d bytes.\n", iter, numBytesWrite, numBytesAll);
if( iter == numIterations-1 ) close(fd_p2c); // Closing output pipe makes sure child receives EOF
if( threadParam->io_flag != READING ) {
numBytesRead += sizeBuffer;
fprintf(file_dump,"Parent #%d: Read %d/%d bytes. Examples: %f %f\n",
readCounter, numBytesRead, numBytesAll, bufferIn[1], bufferIn[numElements-1] );
readCounter += 1;
if( threadParam->io_flag != FINISHED ) threadParam->io_flag = READING;
}
}
//********************************************************************************
//
fprintf(file_dump,"------------------------------\n");
while( threadParam->io_flag != FINISHED ) {
if( threadParam->io_flag == BUFFER_READY ) {
numBytesRead += sizeBuffer;
fprintf(file_dump,"Parent #%d: Read %d/%d bytes. Examples: %f %f\n",
readCounter, numBytesRead, numBytesAll, bufferIn[1], bufferIn[numElements-1] );
readCounter += 1;
if( threadParam->io_flag != FINISHED ) threadParam->io_flag = READING;
}
else {
mini_sleep(10);
}
}
// wait for thread to finish before continuing
pthread_join( thread, NULL );
fclose(file_dump);
fclose(file_c2p);
waitpid(pid, &status, 0); // clean up any children
fprintf(stderr,"..finished\n");
delete [] bufferIn;
delete [] bufferOut;
return 0;
}
Child program B:
#include <cstdio>
using namespace std;
int main() {
int numElements = 10000;
int totalSize = numElements * sizeof(float);
float* buffer = new float[numElements];
FILE* file_dump = fopen("child_dump","w");
int counter = 0;
int sizeRead = 0;
do {
sizeRead = fread( buffer, 1, totalSize, stdin);
if( sizeRead > 0 ) {
fprintf(file_dump,"Child #%d: Read %d bytes, examples: %f %f\n", counter, sizeRead, buffer[1], buffer[numElements-1]);
for( int i = 0; i < numElements; i++ ) {
buffer[i] += numElements;
}
int sizeWrite = fwrite( buffer, 1, totalSize, stdout);
fprintf(file_dump,"Child #%d: Wrote %d bytes, examples: %f %f\n", counter, sizeRead, buffer[1], buffer[numElements-1]);
counter += 1;
}
} while( sizeRead > 0 );
fprintf(file_dump,"Child is finished\n");
fclose(file_dump);
fclose(stdout);
return 0;
}