I am trying to execute scsi inquiry command.
I managed to do it with:
device_ = open(device_path, O_RDWR|O_NONBLOCK);
...
if (ioctl(device, SG_IO, &io_hdr) < 0)
{
int err = errno;
cerr << "Inquiry SG_IO ioctl error. Errno: " << err <<
"; error message: " << strerror(err) << endl;
result = false;
}
How should I rewrite my code to use write/read pair instead?
SG_IO is a blocking operation, it ignores O_NONBLOCK flag and I need to be sure that the call will not block.
I used these articles as a reference:
http://www.tldp.org/HOWTO/SCSI-Generic-HOWTO/write.html
http://www.tldp.org/HOWTO/SCSI-Generic-HOWTO/read.html
...and wrote such code:
sg_io_hdr_t io_hdr, out_io_hdr;
do
{
size_t count = sizeof(sg_io_hdr_t);
size_t written = write(device, &io_hdr, count);
if (written == count)
{
break;
}
int err = errno;
cerr << "write io_hdr_t. Errno: " << err << "; error message: " << strerror(err) << endl;
if (err != EAGAIN)
{
return false;
}
} while (true);
do
{
size_t count = sizeof(sg_io_hdr_t);
// same result with both io_hdr and out_io_hdr as a second parameter
size_t read_count = read(device, &out_io_hdr, count);
if (read_count == count)
{
break;
}
int err = errno;
cerr << "write io_hdr_t. Errno: " << err << "; error message: " << strerror(err) << endl;
if (err != EAGAIN)
{
return false;
}
} while (true);
But this code results in a trash in a status fields as well as in a sense buffer:
INQUIRY sense data length: 100
inquiry sense buffer (hex):
e4 9a eb 2a 30 fa de 2a 20 0
0 0 40 91 e6 2a d8 c3 e0 2a
40 5 f3 2a 14 38 e6 2a 14 38
e6 2a 0 0 0 0 3 0 0 0
0 0 0 0 1 0 0 0 b4 eb
b1 7f 1 0 0 0 e8 4e e6 2a
b8 eb b1 7f 0 0 41 0 5c ec
b1 7f 78 3c 40 0 2b 0 0 0
14 38 e6 2a 34 eb b1 7f 0 0
0 0 0 0 0 0 2 0 0 0
INQUIRY SCSI status=0xfe
masked_status=0x13
INQUIRY host_status=0x3f47
INQUIRY driver_status=0x93c8
Related
I am trying to write a C++ program for my Computer Machine Organization class in which I perform a memory dump in hex on some address stored in memory. I don't really understand what a memory dump is, and am pretty new to writing C++. My questions are:
How can I create a method that takes two arguments in which they specify address in memory?
How can I further modify those arguments to specify a word address that is exactly 4 bytes long?
How can I then convert those addresses into hex values?
I know that this is a lot, but thank you for any suggestions.
For anyone who needs it, here is my code so far:
#include <stdio.h>
// Create something to do the methods on
char array[3] = {'a', 'b', 'c'};
void mdump(char start, char end){
// Create pointers to get the address of the starting and ending characters
char* pointer1 = (char *)& start;
char* pointer2 = (char *)& end;
// Check to see if starting pointer is in lower memory than ending pointer
if(pointer1 < pointer2){
printf("Passed");
}
else{
printf("Failed");
}
// Modify both the arguments so that each of them are exactly 4 bytes
// Create a header for the dump
// Iterate through the addresses, from start pointer to end pointer, and produce lines of hex values
// Declare a struct to format the values
// Add code that creates printable ASCII characters for each memory location (print "cntrl-xx" for values 0-31, or map them into a blank)
// Print the values in decimal and in ASCII form
}
int main(){
mdump(array[0], array[2]);
return 0;
}
How to write a Hex dump tool while learning C++:
Start with something simple:
#include <iostream>
int main()
{
char test[32] = "My sample data";
// output character
std::cout << test[0] << '\n';
}
Output:
M
Live demo on coliru
Print the hex-value instead of the character:
#include <iostream>
int main()
{
char test[32] = "My sample data";
// output a character as hex-code
std::cout << std::hex << test[0] << '\n'; // Uh oh -> still a character
std::cout << std::hex << (unsigned)(unsigned char)test[0] << '\n';
}
Output:
M
4d
Live demo on coliru
Note:
The stream output operator for char is intended to print a character (of course). There is another stream output operator for unsigned which fits better. To achieve that it's used, the char has to be converted to unsigned.
But be prepared: The C++ standard doesn't mandate whether char is signed or unsigned—this decision is left to the compiler vendor. To be on the safe side, the 'char' is first converted to 'unsigned char' then converted to unsigned.
Print the address of the variable with the character:
#include <iostream>
int main()
{
char test[32] = "My sample data";
// output an address
std::cout << &test[0] << '\n'; // Uh oh -> wrong output stream operator
std::cout << (const void*)&test[0] << '\n';
}
Output:
My sample data
0x7ffd3baf9b70
Live demo on coliru
Note:
There is one stream output operator for const char* which is intended to print a (zero-terminated) string. This is not what is intended. Hence, the (ugly) trick with the cast to const void* is necessary which triggers another stream output operator which fits better.
What if the data is not a 2 digit hex?
#include <iomanip>
#include <iostream>
int main()
{
// output character as 2 digit hex-code
std::cout << (unsigned)(unsigned char)'\x6' << '\n'; // Uh oh -> output not with two digits
std::cout << std::hex << std::setw(2) << std::setfill('0')
<< (unsigned)(unsigned char)'\x6' << '\n';
}
Output:
6
06
Live demo on coliru
Note:
There are I/O manipulators which can be used to modify the formatting of (some) stream output operators.
Now, put it all together (in loops) et voilà: a hex-dump.
#include <iomanip>
#include <iostream>
int main()
{
char test[32] = "My sample data";
// output an address
std::cout << (const void*)&test[0] << ':';
// output the contents
for (char c : test) {
std::cout << ' '
<< std::hex << std::setw(2) << std::setfill('0')
<< (unsigned)(unsigned char)c;
}
std::cout << '\n';
}
Output:
0x7ffd345d9820: 4d 79 20 73 61 6d 70 6c 65 20 64 61 74 61 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Live demo on coliru
Make it nice:
#include <algorithm>
#include <iomanip>
#include <iostream>
int main()
{
char test[32] = "My sample data";
// hex dump
const size_t len = sizeof test;
for (size_t i = 0; i < len; i += 16) {
// output an address
std::cout << (const void*)&test[i] << ':';
// output the contents
for (size_t j = 0, n = std::min<size_t>(len - i, 16); j < n; ++j) {
std::cout << ' '
<< std::hex << std::setw(2) << std::setfill('0')
<< (unsigned)(unsigned char)test[i + j];
}
std::cout << '\n';
}
}
Output:
0x7fffd341f2b0: 4d 79 20 73 61 6d 70 6c 65 20 64 61 74 61 00 00
0x7fffd341f2c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Live demo on coliru
Make it a function:
#include <algorithm>
#include <iomanip>
#include <iostream>
void hexdump(const char* data, size_t len)
{
// hex dump
for (size_t i = 0; i < len; i += 16) {
// output an address
std::cout << (const void*)&data[i] << ':';
// output the contents
for (size_t j = 0, n = std::min<size_t>(len - i, 16); j < n; ++j) {
std::cout << ' '
<< std::hex << std::setw(2) << std::setfill('0')
<< (unsigned)(unsigned char)data[i + j];
}
std::cout << '\n';
}
}
int main()
{
char test[32] = "My sample data";
std::cout << "dump test:\n";
hexdump(test, sizeof test);
std::cout << "dump 4 bytes of test:\n";
hexdump(test, 4);
std::cout << "dump an int:\n";
int n = 123;
hexdump((const char*)&n, sizeof n);
}
Output:
dump test:
0x7ffe900f4ea0: 4d 79 20 73 61 6d 70 6c 65 20 64 61 74 61 00 00
0x7ffe900f4eb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
dump 4 bytes of test:
0x7ffe900f4ea0: 4d 79 20 73
dump an int:
0x7ffe900f4e9c: 7b 00 00 00
Live demo on coliru
Note:
(const char*)&n may look a bit adventurous. In fact, conversion of pointers is always something which should be at best not necessary. However, for the dump tool this is the easiest way to access the bytes of arbitrary data. (This is one of the rare cases which is explicitly allowed by the standard.)
An even nicer hexdump can be found in
SO: How would I create a hex dump utility in C++?
(which I recommended OP beforehand).
I try applied XTR-DH for Key Agreement with this example:
//////////////////////////////////////////////////////////////////////////
// Alice
// Initialize the Diffie-Hellman class with a random prime and base
AutoSeededRandomPool rngA;
DH dhA;
dh.Initialize(rngA, 128);
// Extract the prime and base. These values could also have been hard coded
// in the application
Integer iPrime = dhA.GetGroupParameters().GetModulus();
Integer iGenerator = dhA.GetGroupParameters().GetSubgroupGenerator();
SecByteBlock privA(dhA.PrivateKeyLength());
SecByteBlock pubA(dhA.PublicKeyLength());
SecByteBlock secretKeyA(dhA.AgreedValueLength());
// Generate a pair of integers for Alice. The public integer is forwarded to Bob.
dhA.GenerateKeyPair(rngA, privA, pubA);
//////////////////////////////////////////////////////////////////////////
// Bob
AutoSeededRandomPool rngB;
// Initialize the Diffie-Hellman class with the prime and base that Alice generated.
DH dhB(iPrime, iGenerator);
SecByteBlock privB(dhB.PrivateKeyLength());
SecByteBlock pubB(dhB.PublicKeyLength());
SecByteBlock secretKeyB(dhB.AgreedValueLength());
// Generate a pair of integers for Bob. The public integer is forwarded to Alice.
dhB.GenerateKeyPair(rngB, privB, pubB);
//////////////////////////////////////////////////////////////////////////
// Agreement
// Alice calculates the secret key based on her private integer as well as the
// public integer she received from Bob.
if (!dhA.Agree(secretKeyA, privA, pubB))
return false;
// Bob calculates the secret key based on his private integer as well as the
// public integer he received from Alice.
if (!dhB.Agree(secretKeyB, privB, pubA))
return false;
// Just a validation check. Did Alice and Bob agree on the same secret key?
if (VerifyBufsEqualp(secretKeyA.begin(), secretKeyB.begin(), dhA.AgreedValueLength()))
return false;
return true;
And here my code :
//Alice
AutoSeededRandomPool aSRPA;
XTR_DH xtrA(aSRPA, 512, 256);
Integer iPrime = xtrA.GetModulus();
Integer i_qnumber = xtrA.GetSubgroupOrder();
Integer iGeneratorc1 = xtrA.GetSubgroupGenerator().c1;
Integer iGeneratorc2 = xtrA.GetSubgroupGenerator().c2;
SecByteBlock privateA(xtrA.PrivateKeyLength());
SecByteBlock publicA(xtrA.PublicKeyLength());
SecByteBlock secretKeyA(xtrA.AgreedValueLength());
xtrA.GenerateKeyPair(aSRPA, privateA, publicA);
//Bob
AutoSeededRandomPool aSRPB;
XTR_DH xtrB(iPrime, i_qnumber, iGeneratorc1); // Use c1 or c2 or both ???
SecByteBlock privB(xtrB.PrivateKeyLength());
SecByteBlock publB(xtrB.PublicKeyLength());
SecByteBlock secretKeyB(xtrB.AgreedValueLength());
xtrB.GenerateKeyPair(aSRPB, privateB, publicB);
// Agreement
// Alice calculates the secret key based on her private integer as well as the
// public integer she received from Bob.
if (!xtrA.Agree(secretKeyA, privateA, publicB))
return false;
// Bob calculates the secret key based on his private integer as well as the
// public integer he received from Alice.
if (!xtrB.Agree(secretKeyB, privateB, publicA))
return false;
// Just a validation check. Did Alice and Bob agree on the same secret key?
if (VerifyBufsEqualp(secretKeyA.begin(), secretKeyB.begin(), xtrA.AgreedValueLength()))
return false;
return true;
I got this error
Severity Code Description Project File Line Suppression State
Error C2664 'CryptoPP::XTR_DH::XTR_DH(CryptoPP::XTR_DH &&)': cannot convert argument 3 from 'CryptoPP::Integer' to 'const CryptoPP::GFP2Element &' ConsoleApplication1 d:\tugas akhir\code\consoleapplication1\consoleapplication1\consoleapplication1.cpp 91
My question is :
Number of generator is c1 and c2. Is it need both for make xtrB or just one ?
I have tried take number of p, q and g from xtrA and input it for initiate for xtrB but its too long for integer. What the solution ?
Thanks before
XTR_DH xtrB(iPrime, i_qnumber, iGeneratorc1); // Use c1 or c2 or both ???
You should use the the following constructor from XTR-DH | Constructors:
XTR_DH (const Integer &p, const Integer &q, const GFP2Element &g)
There are two ways to setup xtrB. First, the way that uses the constructor (and artificially small parameters):
$ cat test.cxx
#include "cryptlib.h"
#include "osrng.h"
#include "xtrcrypt.h"
#include <iostream>
int main()
{
using namespace CryptoPP;
AutoSeededRandomPool aSRP;
XTR_DH xtrA(aSRP, 170, 160);
const Integer& iPrime = xtrA.GetModulus();
const Integer& iOrder = xtrA.GetSubgroupOrder();
const GFP2Element& iGenerator = xtrA.GetSubgroupGenerator();
XTR_DH xtrB(iPrime, iOrder, iGenerator);
std::cout << "Prime: " << std::hex << xtrB.GetModulus() << std::endl;
std::cout << "Order: " << std::hex << xtrB.GetSubgroupOrder() << std::endl;
std::cout << "Generator" << std::endl;
std::cout << " c1: " << std::hex << xtrB.GetSubgroupGenerator().c1 << std::endl;
std::cout << " c2: " << std::hex << xtrB.GetSubgroupGenerator().c2 << std::endl;
return 0;
}
And then:
$ g++ -DNDEBUG -g2 -O3 -fPIC -pthread test.cxx ./libcryptopp.a -o test.exe
$ ./test.exe
Prime: 2d4c4f9f4de9e32e84a7be42f019a1a4139e0fe7489h
Order: 89ab07fa5115443f51ce9a74283affaae2d7748fh
Generator
c1: 684fedbae519cb297f3448d5e564838ede5ed1fb81h
c2: 39112823212ccd7b01f10377536f51bf855752c7a3h
Second, the way that stores the domain parameters in an ASN.1 object (and artificially small parameters):
$ cat test.cxx
#include "cryptlib.h"
#include "osrng.h"
#include "files.h"
#include "xtrcrypt.h"
#include <iostream>
int main()
{
using namespace CryptoPP;
AutoSeededRandomPool prng;
XTR_DH xtrA(prng, 170, 160);
xtrA.DEREncode(FileSink("params.der").Ref());
XTR_DH xtrB(FileSource("params.der", true).Ref());
std::cout << "Prime: " << std::hex << xtrB.GetModulus() << std::endl;
std::cout << "Order: " << std::hex << xtrB.GetSubgroupOrder() << std::endl;
std::cout << "Generator" << std::endl;
std::cout << " c1: " << std::hex << xtrB.GetSubgroupGenerator().c1 << std::endl;
std::cout << " c2: " << std::hex << xtrB.GetSubgroupGenerator().c2 << std::endl;
return 0;
}
And then:
$ g++ -DNDEBUG -g2 -O3 -fPIC -pthread test.cxx ./libcryptopp.a -o test.exe
$ ./test.exe
Prime: 2ee076b3254c1520151bbe0391a77971f92e277ba37h
Order: f7674a8c2dd68d32c3da8e74874a48b9adf00fcbh
Generator
c1: 2d469e63b474ac45578a0027a38864f303fad03ba9h
c2: 1d5e5714bc19ef25eee0535584176889df8f26c4802h
And finally:
$ dumpasn1 params.der
0 94: SEQUENCE {
2 22: INTEGER 02 EE 07 6B 32 54 C1 52 01 51 BB E0 39 1A 77 97 1F 92 E2 77 BA 37
26 21: INTEGER 00 F7 67 4A 8C 2D D6 8D 32 C3 DA 8E 74 87 4A 48 B9 AD F0 0F CB
49 21: INTEGER 2D 46 9E 63 B4 74 AC 45 57 8A 00 27 A3 88 64 F3 03 FA D0 3B A9
72 22: INTEGER 01 D5 E5 71 4B C1 9E F2 5E EE 05 35 58 41 76 88 9D F8 F2 6C 48 02
: }
In practice you probably want to use something like this, which validates the parameters after loading them. You should always validate your security parameters.
// Load the domain parameters from somewhere
const Integer& iPrime = ...;
const Integer& iOrder = ...;
const GFP2Element& iGenerator = ...;
// Create the key agreement object using the parameters
XTR_DH xtrB(iPrime, iOrder, iGenerator);
// Verify the the parameters using the key agreement object
if(xtrB.Validate(aSRP, 3) == false)
throw std::runtime_error("Failed to validate parameters");
You are probably going to use something like the second method shown above. That is, you are going to generate your domain parameters once, and then both parties will use them. Below both parties xtrA and xtrB use params.der:
int main()
{
using namespace CryptoPP;
AutoSeededRandomPool prng;
XTR_DH xtrA(FileSource("params.der", true).Ref());
XTR_DH xtrB(FileSource("params.der", true).Ref());
if(xtrA.Validate(prng, 3) == false)
throw std::runtime_error("Failed to validate parameters");
if(xtrB.Validate(prng, 3) == false)
throw std::runtime_error("Failed to validate parameters");
...
}
I am using the following code to convert the raw data values to a hexstring so I can find some information. But I am getting FFFFFFFF where I was supposed to get FF.
For example, the result should be "FF 01 00 00 EC 00 00 00 00 00 00 00 00 00 E9", but I am getting "FFFFFFFFF 01 00 00 FFFFFFEC 00 00 00 00 00 00 00 00 00 FFFFFFE9".
Does anyone know what is happening here?
std::vector<unsigned char> buf;
buf.resize( ANSWER_SIZE);
// Read from socket
m_pSocket->Read( &buf[0], buf.size() );
string result( buf.begin(), buf.end() );
result = ByteUtil::rawByteStringToHexString( result );
std::string ByteUtil::int_to_hex( int i )
{
std::stringstream sstream;
sstream << std::hex << i;
return sstream.str();
}
std::string ByteUtil::rawByteStringToHexString(std::string str)
{
std::string aux = "", temp = "";
for (unsigned int i=0; i<str.size(); i++) {
temp += int_to_hex(str[i]);
if (temp.size() == 1) {
aux += "0" + temp + " "; // completes with 0
} else if(i != (str.size() -1)){
aux += temp + " ";
}
temp = "";
}
// System.out.println(aux);
return aux;
}
UPDATE: Debugging, I noticed that the int_to_hex is returning FFFFFFFF instead of FF. How can I fix that?
Note the use of unsigned instead of int in int_to_hex().
#include <iostream>
#include <sstream>
std::string int_to_hex(unsigned i)
{
std::stringstream sstream;
sstream << std::hex << i;
return sstream.str();
}
int main() {
std::cout << int_to_hex(0xFF) << "\n";
}
Output
[1:58pm][wlynch#watermelon /tmp] ./foo
ff
Additionally...
We also can see in the question you are looking at, that they do a static_cast to achieve the same result.
ss << std::setw(2) << static_cast<unsigned>(buffer[i]);
OK Guys, sorry for the delay, I ran into the weekend and had some FIFA World Cup games to watch.
I was getting the same result no matter the change I made, so I decided to make some changes in the code before and I switched the input param from
std::string ByteUtil::rawByteStringToHexString(std::string str)
to
std::string ByteUtil::rawByteStringToHexString(vector<unsigned char> v)
and also kept the changes suggested by #sharth. Now I am getting the correct result.
Thank you all for the help!!
I'm having the famous segmentation fault. I've tracked it down to a single line in the code (getline). Here's someone with a similar issue, also on Ubuntu:
http://www.daniweb.com/software-development/cpp/threads/329191
Note that getline returns -1 after the segmentation fault, but it couldn't have been really the end of the stream (in my case).
When the stream is smaller, everything goes ok. As we can deduce from the output, the segmentation fault is on line 98.
1 /*
2 * File: RequestDispatcher.cpp
3 * Author: albert
4 *
5 * Created on July 8, 2011, 7:15 PM
6 */
7
8 #include "iostream"
9 #include "fstream"
10 #include "stdlib.h"
11 #include "stdio.h"
12 #include "cstring"
13 #include "algorithm"
14
15 #include "RequestDispatcher.h"
16 #include "Functions.h"
17
18 #define PROXIES 1
19
20 RequestDispatcher::RequestDispatcher()
21 {
22 }
23
24 RequestDispatcher::RequestDispatcher(const RequestDispatcher& orig)
25 {
26 }
27
28 RequestDispatcher::~RequestDispatcher()
29 {
30 }
31
32 int RequestDispatcher::addRequest(string host, string request, IResponseReceiver* response_receiver)
33 {
34 RequestInfo info;
35 info.request_index = request_info.size();
36 info.host = host;
37 info.request = request;
38 info.response_receiver = response_receiver;
39 request_info.push_back(info);
40 return info.request_index;
41 }
42
43 void RequestDispatcher::run()
44 {
45 if (request_info.size()==0)
46 {
47 return;
48 }
49 FILE* pipe[PROXIES];
50 int per_proxy = (request_info.size() + PROXIES - 1) / PROXIES;
51 int count_pipes = (request_info.size() + per_proxy - 1) / per_proxy;
52 for (int pipe_index=0; pipe_index<count_pipes; ++pipe_index)
53 {
54 int from = pipe_index * per_proxy;
55 int to = min(from + per_proxy, int(request_info.size()));
56 cout << "FROM: "<< from << "; TO: " << to;
57 const char* cmd = generateCmd(from, to);
58 pipe[pipe_index] = popen(cmd, "r");
59 if (!pipe[pipe_index])
60 {
61 cerr << "Error executing command in RequestDispatcher::run()";
62 }
63 }
64 string result[PROXIES];
65 bool finished[PROXIES];
66 for (int pipe_index=0; pipe_index<count_pipes; pipe_index++)
67 {
68 finished[pipe_index] = false;
69 }
70 int count_finished = 0;
71 char* buffer;
72 size_t buffer_length=1024;
73 buffer = (char *) malloc (buffer_length + 1);
74 while (count_finished < count_pipes)
75 {
76 cout << "D\n";
77 fflush(stdout);
78 for(int pipe_index=0; pipe_index<count_pipes; ++pipe_index)
79 {
80 cout << "E\n";
81 fflush(stdout);
82 if (finished[pipe_index])
83 {
84 continue;
85 }
86 cout << "Getline" << buffer_length << "\n";
87 ssize_t bytes_read = getline(&buffer, &buffer_length, pipe[pipe_index]);
88 cout << "Getline Done ("<<bytes_read<< "," << buffer_length << ")\n";
89 fflush(stdout);
90 while (bytes_read>0)
91 {
92 for (int i=0; i<bytes_read; i++)
93 {
94 result[pipe_index] += buffer[i];
95 }
96 cout << "P\n";
97 fflush(stdout);
98 bytes_read = getline(&buffer, &buffer_length, pipe[pipe_index]);
99 cout << "Bytes read ("<<bytes_read<<","<< buffer_length << ")\n";
100 fflush(stdout);
101
102 }
103 if (bytes_read == -1) // then finished this pipe
104 {
105 string* r = &result[pipe_index];
106 //cout << *r;
107 finished[pipe_index] = true;
108 ++count_finished;
109 cout << "HI\n";
110 fflush(stdout);
111 // delete trailing '\0' from result
112 pclose(pipe[pipe_index]);
113 result[pipe_index] = result[pipe_index].substr(0, result[pipe_index].length()-1);
114 int pos = r->find("RESPONSE_DATA");
115 int valuepos, endvaluepos;
116 int request_index, length;
117 string headers;
118 int headerslength;
119 string body;
120 int bodypos, bodylength;
121 while (pos!=r->npos)
122 {
123 valuepos = r->find("REQUEST_INDEX=", pos) + 14;
124 endvaluepos = r->find("\n", valuepos);
125 request_index = pipe_index * per_proxy + atoi(r->substr(valuepos, endvaluepos-valuepos).c_str());
126
127 cout << "REQUEST_INDEX " << request_index;
128
129 valuepos = r->find("LENGTH=", pos) + 7;
130 endvaluepos = r->find("\n", valuepos);
131 length = atoi(r->substr(valuepos, endvaluepos-valuepos).c_str());
132
133 pos = r->find("START", pos)+5;
134 bodypos = r->find("\r\n\r\n", pos)+4;
135 headerslength = bodypos-pos-4;
136 bodylength = length-headerslength-4;
137 headers = r->substr(pos, headerslength);
138 body = r->substr(bodypos, bodylength);
139 request_info[request_index].response_receiver->notifyResponse(headers, body, request_index);
140
141 pos=r->find("RESPONSE_DATA", pos+length);
142 }
143 }
144 }
145 }
146 cout << "\n?\n";
147 fflush(stdout);
148 free(buffer);
149 request_info.clear();
150 }
151
152 const char* RequestDispatcher::generateCmd(int first_request, int to_request)
153 {
154 string r("/home/albert/apachebench-standalone-read-only/ab -a");
155 for (int i=first_request; i<to_request; i++)
156 {
157 r.append(" '");
158 r.append(request_info.at(i).request);
159 r.append("'");
160 }
161 ofstream out("/home/albert/apachebench-standalone-read-only/debug");
162 if(! out)
163 {
164 cerr<<"Cannot open output file\n";
165 return "";
166 }
167 out << r.c_str();
168 out.close();
169 return "/home/albert/apachebench-standalone-read-only/debug";
170 /*int size = strlen("/home/albert/apachebench-standalone-read-only/ab -a");
171 for (int i=first_request; i<to_request; i++)
172 {
173 size += 2+strlen(request_info.at(i).request)+1;
174 cout << "len: " << strlen(request_info.at(i).request) << "\n";
175 cout << "total: " << size << "\n";
176 }
177 size += 1;
178 char* cmd = new char[size];
179 strcpy(cmd, "/home/albert/apachebench-standalone-read-only/ab -a");
180 for (int i=first_request; i<to_request; i++)
181 {
182 cout << "LEN: " << strlen(cmd) << "\n";
183 cout << "NEXT: " << strlen(request_info.at(i).request) << "\n";
184 fflush(stdout);
185 strcat(cmd, " '");
186 strcat(cmd, request_info.at(i).request);
187 strcat(cmd, "'");
188 }
189 cout << "LEN: " << strlen(cmd) << "\n";
190 fflush(stdout);
191 return cmd;*/
192 }
When I run /home/albert/apachebench-standalone-read-only/debug from the command line everything works perfectly fine. It returns binary data.
The end of the output is:
P
Bytes read (272,6828)
P
Bytes read (42,6828)
P
Bytes read (464,6828)
P
Bytes read (195,6828)
P
Bytes read (355,6828)
P
Bytes read (69,6828)
P
Bytes read (111,6828)
P
Segmentation fault
Bytes read (368,6828)
P
Bytes read (-1,6828)
HI
REQUEST_INDEX 46REQUEST_INDEX 48REQUEST_INDEX 44REQUEST_INDEX 0REQUEST_INDEX 45
?
Mind the "?" for exiting the loop. After this, the program is finished.
By the way, I always thought the program would terminate on a segmentation fault (edit: I did not do anything to catch it).
In reply to some answers: There seem to be different versions of getline and I seem to be using the one documented here:
http://www.kernel.org/doc/man-pages/online/pages/man3/getline.3.html
So after some thought the issue I believe is that your buffer is being written to as you're reading it. In some cases the buffer is not done being written to and you remove some of the data from it (which could mean that you may read an empty buffer because the write isn't done). This is because you are using popen and simply piping data from another process. What I would recommend is that for one you use the C++ standard for getline (although both are somewhat unsafe) and that you have some leeway for reading data from the pipe. Retry logic might be what you need as I can't think of a clean way to solve this. If anyone knows please post it, I'm posting this because this is what I believe to be the likely culprit of the problem.
Also if you're coding in C++ I highly recommend that you use the C++ libraries so that you're not constantly mixing or casting between types (such as string to char * and such, it just saves you some hassle) and that you use the safer versions of methods so you avoid errors such as buffer overflows.
I'm in trouble using std::string::find(). I read strings from console through the following code:
50 while(command.find(exitString) != 0) {
51 std::cout << "$ ";
52 getline(std::cin, command);
53
54 doSwitch(command);
55 }
and then I "switch" on them, through the following function:
59 void Console::doSwitch(std::string command) {
60 if(command.find(helpString) == 0) {
61 help();
62 } else if(command.find(loadString) == 0) {
63 try {
64 doLoad(command);
65 } catch(std::string str) {
66 std::cout << str << std::endl;
67 }
68 } else if(command.find(dumpProcString) == 0) {
69 try {
70 doDumpProc(command);
71 } catch(std::string str) {
72 std::cout << str << std::endl;
73 }
74 } else if(command.find(dumpMemString) == 0) {
75 doDumpMem();
76 } else if(command.find(defmemString) == 0) {
77 try {
78 doDefmem(command);
79 } catch(std::string str) {
80 std::cout << str << std::endl;
81 } catch(char *str) {
82 std::cout << str << std::endl;
83 }
84 } else if(command.find(resetString) == 0) {
85 try {
86 doReset();
87 } catch(std::string str) {
88 std::cout << str << std::endl;
89 }
90 } else {
91 std::cout << "Comando inválido." << std::endl;
92 }
93 }
but sometimes it simply doesn't switch correctly. Any clues?
Thanks in advance,
EDIT:
I've done some tests and I detected it was falling on the last else-if statement, instead of falling on the last else.
Then I checked my code again and found that the root cause was that I forgot to initialize resetString.
Problem solved!
Thank you everyone.
You might be expecting that find returns zero when it found the string, kind of like the way strcmp works.
But that's not how find works. find returns the first index of the found string, which might be zero, or might be something else if the string you're looking for is prepended with spaces, other strings, etc.
If find doesn't find what you're looking for, it returns string::npos. So your if...else block should be checking to find if the strings were found or not found, not checking to see if they were at index zero. Like this:
if(command.find(helpString) != string::npos ) {
help();
} else if /// ... etc...
You are reading a line and then calling doSwitch() without checking if its exitString. In that case, when the input is exitString, else block at the end of doSwitch() function is executed, causing the program to print "Command Invalido" before exiting the loop.
Is this what you observed?
If its something else, please let us know for what input your code behaves incorrectly and what is the input and output.