How to pass input to soap_call in gsoap client application? - client

I have problem to pass request variable in my gsoap client app. The error is Segmentation Fault (core dump).
This is my header file:
class _ns1__NewTransactionDataRequest;
class _ns1__NewTransactionDataResponse;
class _ns1__GetTransactionResultRequest;
class _ns1__GetTransactionResultResponse;
class _ns1__NewTransactionDataRequest
{
public:
char* UserID 1;
char* UserPwd 1;
char* TransID 1;
char* TransDate 1;
char* A_NO 1;
char* B_NO 1;
char* Denom 1;
char* TransType 1;
struct soap *soap ;
};
class _ns1__NewTransactionDataResponse
{ public:
char* TransID 1;
char* ResultCode 1;
char* ResultDesc 1;
struct soap *soap ;
};
class _ns1__GetTransactionResultRequest
{
public:
char* UserID 1;
char* UserPwd 1;
char* TransID 1;
char* TransDate 1;
char* A_NO 1;
char* B_NO 1;
char* Status 1;
char* Remark 1;
struct soap *soap ;
};
class _ns1__GetTransactionResultResponse
{
public:
char* TransID 1;
char* ResultCode 1;
char* ResultDesc 1;
struct soap *soap ;
};
int __ns1__NewTransactionData(_ns1__NewTransactionDataRequest* ns1__NewTransactionDataRequest, _ns1__NewTransactionDataResponse* ns1__NewTransactionDataResponse
);
int __ns1__GetTransactionResult(_ns1__GetTransactionResultRequest*ns1__GetTransactionResultRequest,_ns1__GetTransactionResultResponse* ns1__GetTransactionResultResponse
);
This is the client app that I try to compile:
int main(int argc, char **argv)
{
struct soap soap;
_ns1__GetTransactionResultRequest *ns1__GetTransactionResultRequest;
_ns1__GetTransactionResultResponse *ns1__GetTransactionResultResponse;
_ns1__NewTransactionDataRequest *ns1__NewTransactionDataRequest;
_ns1__NewTransactionDataResponse *ns1__NewTransactionDataResponse;
(*ns1__GetTransactionResultRequest).UserID = "myuserid"; //<--fail at this line
(*ns1__GetTransactionResultRequest).UserPwd = "userpwd";
(*ns1__GetTransactionResultRequest).TransID = "amwani";
(*ns1__GetTransactionResultRequest).TransDate = "2013-09-09 01:01:01";
(*ns1__GetTransactionResultRequest).A_NO = "mynumber";
(*ns1__GetTransactionResultRequest).B_NO = "yournumber";
(*ns1__GetTransactionResultRequest).Status = "success";
(*ns1__GetTransactionResultRequest).Remark = "done";
printf("Content-type: text/html\r\n\r\n<html><h1>Magic Square of Rank</h1><pre>\n");
if (soap_call___ns1__GetTransactionResult(&soap, server, NULL, ns1__GetTransactionResultRequest, ns1__GetTransactionResultResponse))
{
soap_print_fault(&soap, stderr);
soap_print_fault_location(&soap, stderr);
}
else
{
printf("%s", (*ns1__GetTransactionResultRequest).TransID);
}
printf("</pre></html>\n");
soap_destroy(&soap);
soap_end(&soap);
soap_done(&soap);
}
I did not get any error during compilaton, but few warnings:
xpulsaclient.cpp: In function ‘int main(int, char**)’:
xpulsaclient.cpp:46: warning: deprecated conversion from string constant to ‘char*’
xpulsaclient.cpp:47: warning: deprecated conversion from string constant to ‘char*’
xpulsaclient.cpp:48: warning: deprecated conversion from string constant to ‘char*’
xpulsaclient.cpp:49: warning: deprecated conversion from string constant to ‘char*’
xpulsaclient.cpp:50: warning: deprecated conversion from string constant to ‘char*’
xpulsaclient.cpp:51: warning: deprecated conversion from string constant to ‘char*’
xpulsaclient.cpp:52: warning: deprecated conversion from string constant to ‘char*’
xpulsaclient.cpp:53: warning: deprecated conversion from string constant to ‘char*’
xpulsaclient.cpp:42: warning: unused variable ‘ns1__NewTransactionDataRequest’
xpulsaclient.cpp:43: warning: unused variable ‘ns1__NewTransactionDataResponse’
xpulsaclient.cpp:46: warning: ‘ns1__GetTransactionResultRequest’ is used uninitialized in this function
xpulsaclient.cpp:57: warning: ‘ns1__GetTransactionResultResponse’ may be used uninitialized in this function
Maybe the way I initialize variable in class ns1_GetTransactionResultRequest is not correct that caused the segmentation fault?. Can anyone help me? I have been stuck at this point for 2 days....Thanks!

You're right - you're not initializing ns1__GetTransactionResultRequest (or any of the other pointers). The variables you've declared are pointers, but they're never assigned to a new object. You can either instantiate objects, or declare the variables on the stack instead.
I've posted a simple gSOAP client app in another response. It includes assignment to a gSOAP request object property, which should help you out.
Example: making a web services query using gSoap with query arguments

Related

std::shared_ptr<double[2]> constructor problems

The current C++ compilers fail to find a suitable overload for std::shared_ptr when using a C-array as a type.
I can make it a real std::array object and that works, but the library I'm linking against (fftw3) has already created the typedef and uses it in all of it's C-API calls.
#include <memory>
typedef double fftw_complex[2];
int main(int argc, char* argv[])
{
fftw_complex bob; //works fine
bob[0]=2; bob[1]=-1; //works fine
std::shared_ptr<fftw_complex> handle; //works fine
std::shared_ptr<double> other(new double[35]); //works fine
handle = std::shared_ptr<fftw_complex>(new fftw_complex[35]);//can't find constructor
return 0;
}
Up until a few months ago this worked fine with all compilers. With the update to gcc to version 7.3, 8.2, and 9 I now get an error when trying to compile the non-void constructor. I suspect it is because of the "improvements" to std::shared_ptr to automatically handle when T is an array type.
I get the error
complex_shared.cpp:12:61: error: no matching function for call to 'std::shared_ptr<double [2]>::shared_ptr(double (*)[2])'
12 | handle = std::shared_ptr<fftw_complex>(new fftw_complex[35]);
and the somewhat difficult to parse error message
note: candidate: 'template<class _Yp, class> std::shared_ptr<_Tp>::shared_ptr(_Yp*)'
139 | shared_ptr(_Yp* __p) : __shared_ptr<_Tp>(__p) { }
| ^~~~~~~~~~
/usr/local/Cellar/gcc/9.2.0/include/c++/9.2.0/bits/shared_ptr.h:139:2: note: template argument deduction/substitution failed:
/usr/local/Cellar/gcc/9.2.0/include/c++/9.2.0/bits/shared_ptr.h: In substitution of 'template<class _Tp> template<class ... _Args> using _Constructible = typename std::enable_if<std::is_constructible<std::__shared_ptr<_Tp>, _Args ...>::value>::type [with _Args = {double (*)[2]}; _Tp = double [2]]':
/usr/local/Cellar/gcc/9.2.0/include/c++/9.2.0/bits/shared_ptr.h:137:30: required from here
/usr/local/Cellar/gcc/9.2.0/include/c++/9.2.0/bits/shared_ptr.h:106:8: error: no type named 'type' in 'struct std::enable_if<false, void>'
106 | using _Constructible = typename enable_if<
it seems you have to let std::shared_ptr know that this is not a normal pointer but is indeed a pointer to an array
#include <memory>
typedef double fftw_complex[2];
int main(int argc, char* argv[])
{
fftw_complex bob;
bob[0]=2; bob[1]=-1;
std::shared_ptr<fftw_complex[]> handle;
std::shared_ptr<double> other(new double[35],[](double* p){ delete[] p;});
std::shared_ptr<double[]> nother(new double[35]); //std::shared_ptr will call delete[]
handle = std::shared_ptr<fftw_complex[]>(new fftw_complex[35], [](fftw_complex* p){ /* special delete logic*/;});
return 0;
}
to be clear, I have to use the fftw_malloc and fftw_free functions for this memory, so I will be providing my own deleter for the fftw_complex type. delete[] is incorrect for these library-provided data elements.

running boost: lock free queues globally across multiple files

I would like to run a variant of example 46.3 from this website
http://theboostcpplibraries.com/boost.lockfree. I am on a linux system.
I would like to have the queue q be defined in a header file. I would like to have the produce and consume functions be in different files. So I would like to have global.h contain
static boost::lockfree::queue<int> q{100};
static std::atomic<int> sum{0};
void *produce (void*);
void *consume (void*);
I would then like to have a produce.cpp contain:
void *produce( void*)
{
for (int i = 1; i <= 10000; ++i)
q.push(i);
}
and I would like to have a consume.cpp contain
void *consume (void*)
{
int i;
while (q.pop(i))
sum += i;
}
I would then like to have my main.cpp contain
#include iosteam
#include iomanip
#include global
#include pthread
int main ()
{pthread_t t1;
pthread_t t2;
pthread_t t3;
int t1_iret;
t1_iret = pthread_create( &t1, NULL, produce, NULL);
if(t1_iret)
{
fprintf(stderr,"Error - pthread_create() return code: %d\n",t1_iret);
exit(EXIT_FAILURE);
}
int t2_iret;
t2_iret = pthread_create( &t2, NULL, consume, NULL);
if(t2_iret)
{
fprintf(stderr,"Error - pthread_create() return code: %d\n",t2_iret);
exit(EXIT_FAILURE);
}
int t3_iret;
t3_iret = pthread_create( &t3, NULL, consume, NULL);
if(t3_iret)
{
fprintf(stderr,"Error - pthread_create() return code: %d\n",t3_iret);
exit(EXIT_FAILURE);
}
pthread_join( t1, NULL);
pthread_join( t2, NULL);
pthread_join( t3, NULL);
return 0; }
Additionally, I was wondering if it would be possible to do what I have described with strings rather then integers.
edit1: when I try and make the queue be queue of strings I get::
/usr/local/include/boost/lockfree/queue.hpp: In instantiation of ‘class boost::l ockfree::queue >’:
/home/ubuntu/Project/src/main.cpp:15:37: required from here
/usr/local/include/boost/lockfree/queue.hpp:87:5: error: static assertion failed : (boost::has_trivial_destructor::value)
BOOST_STATIC_ASSERT((boost::has_trivial_destructor::value));
^
/usr/local/include/boost/lockfree/queue.hpp:91:5: error: static assertion failed : (boost::has_trivial_assign::value)
BOOST_STATIC_ASSERT((boost::has_trivial_assign::value));
^
In file included from /usr/local/include/boost/lockfree/queue.hpp:21:0,
from /home/ubuntu/Project/src/main.cpp:5:
/usr/local/include/boost/lockfree/detail/copy_payload.hpp: In instantiation of ‘ static void boost::lockfree::detail::copy_constructible_and_copyable::copy(T&, U &) [with T = std::basic_string; U = int]’:
/usr/local/include/boost/lockfree/detail/copy_payload.hpp:49:25: required from ‘void boost::lockfree::detail::copy_payload(T&, U&) [with T = std::basic_string ; U = int]’
/usr/local/include/boost/lockfree/queue.hpp:402:61: required from ‘bool boost: :lockfree::queue::pop(U&) [with U = int; T = std::basic_string; A0 = boost::parameter::void_; A1 = boost::parameter::void_; A2 = boost::par ameter::void_]’
/home/ubuntu/Project/src/main.cpp:21:24: required from here
/usr/local/include/boost/lockfree/detail/copy_payload.hpp:38:11: error: invalid cast from type ‘std::basic_string’ to type ‘int’
u = U(t);
You need to declare, but not define, your variables in global.h:
extern boost::lockfree::queue<int> q;
extern std::atomic<int> sum;
Then you need to define them in a separate file, global.cpp:
boost::lockfree::queue<int> q{100};
std::atomic<int> sum{0};
I think this should fix your issue. For details, see How do I use extern to share variables between source files?
As for the second part, asking why you can't make a lock-free queue of strings, well, that is answered by the error message: has_trivial_destructor is false for std::string, because it's a dynamically-sized string which allocates memory. You won't be able to use it in this sort of lock-free queue. You can try using a fixed-size string class instead, or std::array<char, N>.

How to dump/list all kernel symbols with addresses from Linux kernel module?

In a kernel module, how to list all the kernel symbols with their addresses?
The kernel should not be re-compiled.
I know "cat /proc/kallsyms" in an interface, but how to get them directly from kernel data structures, using functions like kallsyms_lookup_name.
Example
Working module code:
#include <linux/module.h>
#include <linux/kallsyms.h>
static int prsyms_print_symbol(void *data, const char *namebuf,
struct module *module, unsigned long address)
{
pr_info("### %lx\t%s\n", address, namebuf);
return 0;
}
static int __init prsyms_init(void)
{
kallsyms_on_each_symbol(prsyms_print_symbol, NULL);
return 0;
}
static void __exit prsyms_exit(void)
{
}
module_init(prsyms_init);
module_exit(prsyms_exit);
MODULE_AUTHOR("Sam Protsenko");
MODULE_DESCRIPTION("Module for printing all kernel symbols");
MODULE_LICENSE("GPL");
Explanation
kernel/kallsyms.c implements /proc/kallsyms. Some of its functions are available for external usage. They are exported via EXPORT_SYMBOL_GPL() macro. Yes, your module should have GPL license to use it. Those functions are:
kallsyms_lookup_name()
kallsyms_on_each_symbol()
sprint_symbol()
sprint_symbol_no_offset()
To use those functions, include <linux/kallsyms.h> in your module. It should be mentioned that CONFIG_KALLSYMS must be enabled (=y) in your kernel configuration.
To print all the symbols you obviously have to use kallsyms_on_each_symbol() function. The documentation says next about it:
/* Call a function on each kallsyms symbol in the core kernel */
int kallsyms_on_each_symbol(int (*fn)(void *, const char *, struct module *,
unsigned long), void *data);
where fn is your callback function that should be called for each symbol found, and data is a pointer to some private data of yours (will be passed as first parameter to your callback function).
Callback function must have next signature:
int fn(void *data, const char *namebuf, struct module *module,
unsigned long address);
This function will be called for each kernel symbol with next parameters:
data: will contain pointer to your private data you passed as last argument to kallsyms_on_each_symbol()
namebuf: will contain name of current kernel symbol
module: will always be NULL, just ignore that
address: will contain address of current kernel symbol
Return value should always be 0 (on non-zero return value the iteration through symbols will be interrupted).
Supplemental
Answering the questions in your comment.
Also, is there a way to output the size of each function?
Yes, you can use sprint_symbol() function I mentioned above to do that. It will print symbol information in next format:
symbol_name+offset/size [module_name]
Example:
psmouse_poll+0x0/0x30 [psmouse]
Module name part can be omitted if symbol is built-in.
I tried the module and see the result with "dmesg". But a lot of symbols are missing such as "futex_requeue". The output symbol number is about 10K, while it is 100K when I use "nm vmlinux".
This is most likely because your printk buffer size is insufficient to store all the output of module above.
Let's improve above module a bit, so it provides symbols information via miscdevice. Also let's add function size to the output, as requested. The code as follows:
#include <linux/device.h>
#include <linux/fs.h>
#include <linux/kallsyms.h>
#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/sizes.h>
#include <linux/uaccess.h>
#include <linux/vmalloc.h>
#define DEVICE_NAME "prsyms2"
/* 16 MiB is sufficient to store information about approx. 200K symbols */
#define SYMBOLS_BUF_SIZE SZ_16M
struct symbols {
char *buf;
size_t pos;
};
static struct symbols symbols;
/* ---- misc char device definitions ---- */
static ssize_t prsyms2_read(struct file *file, char __user *buf, size_t count,
loff_t *pos)
{
return simple_read_from_buffer(buf, count, pos, symbols.buf,
symbols.pos);
}
static const struct file_operations prsyms2_fops = {
.owner = THIS_MODULE,
.read = prsyms2_read,
};
static struct miscdevice prsyms2_misc = {
.minor = MISC_DYNAMIC_MINOR,
.name = DEVICE_NAME,
.fops = &prsyms2_fops,
};
/* ---- module init/exit definitions ---- */
static int prsyms2_store_symbol(void *data, const char *namebuf,
struct module *module, unsigned long address)
{
struct symbols *s = data;
int count;
/* Append address of current symbol */
count = sprintf(s->buf + s->pos, "%lx\t", address);
s->pos += count;
/* Append name, offset, size and module name of current symbol */
count = sprint_symbol(s->buf + s->pos, address);
s->pos += count;
s->buf[s->pos++] = '\n';
if (s->pos >= SYMBOLS_BUF_SIZE)
return -ENOMEM;
return 0;
}
static int __init prsyms2_init(void)
{
int ret;
ret = misc_register(&prsyms2_misc);
if (ret)
return ret;
symbols.pos = 0;
symbols.buf = vmalloc(SYMBOLS_BUF_SIZE);
if (symbols.buf == NULL) {
ret = -ENOMEM;
goto err1;
}
dev_info(prsyms2_misc.this_device, "Populating symbols buffer...\n");
ret = kallsyms_on_each_symbol(prsyms2_store_symbol, &symbols);
if (ret != 0) {
ret = -EINVAL;
goto err2;
}
symbols.buf[symbols.pos] = '\0';
dev_info(prsyms2_misc.this_device, "Symbols buffer is ready!\n");
return 0;
err2:
vfree(symbols.buf);
err1:
misc_deregister(&prsyms2_misc);
return ret;
}
static void __exit prsyms2_exit(void)
{
vfree(symbols.buf);
misc_deregister(&prsyms2_misc);
}
module_init(prsyms2_init);
module_exit(prsyms2_exit);
MODULE_AUTHOR("Sam Protsenko");
MODULE_DESCRIPTION("Module for printing all kernel symbols");
MODULE_LICENSE("GPL");
And here is how to use it:
$ sudo insmod prsyms2.ko
$ sudo cat /dev/prsyms2 >symbols.txt
$ wc -l symbols.txt
$ sudo rmmod prsyms2
File symbols.txt will contain all kernel symbols (both built-in and from loaded modules) in next format:
ffffffffc01dc0d0 psmouse_poll+0x0/0x30 [psmouse]
It seems that I can use kallsyms_lookup_name() to find the address of the function, can then use a function pointer to call the function?
Yes, you can. If I recall correctly, it's called reflection. Below is an example how to do so:
typedef int (*custom_print)(const char *fmt, ...);
custom_print my_print;
my_print = (custom_print)kallsyms_lookup_name("printk");
if (my_print == 0) {
pr_err("Unable to find printk\n");
return -EINVAL;
}
my_print(KERN_INFO "### printk found!\n");

Some warnings being treated as errors while making a modified ver of ext2 kernel module under ubuntu

I have succeeded in making a modified version of ext2 (so called myext2.ko) and tested it for mount and umount, and something else; the problem occurs when I add the following code into my fs/myext2/file.c and tried to implement a simple "encryption" func, that is, negating the last bit of the read-in string :
ssize_t my_new_sync_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos)
{
struct iovec iov; //changed
struct kiocb kiocb;
struct iov_iter iter;
ssize_t ret;
//inserted by adward - begin
size_t i;
char buff[len];
for (i=0;i<len;i++){
buff[i] = buf[i] ^ 1;
}
iov.iov_base = (void __user *)buff;
iov.iov_len = len;
printk("Inside my_new_sync_write");
//inserted by adward - end
init_sync_kiocb(&ki_nbytesocb, filp);
kiocb.ki_pos = *ppos;
kiocb.ki_nbytes = len;
iov_iter_init(&iter, WRITE, &iov, 1, len);
ret = filp->f_op->write_iter(&kiocb, &iter);
if (-EIOCBQUEUED == ret)
ret = wait_on_sync_kiocb(&kiocb);
*ppos = kiocb.ki_pos;
return ret;
}
ssize_t my_new_sync_read(struct file *filp, char __user *buf, size_t len, loff_t *ppos)
{
struct iovec iov = { .iov_base = buf, .iov_len = len };
struct kiocb kiocb;
struct iov_iter iter;
ssize_t ret;
//inserted by adward - begin
size_t i;
//inserted by adward - end
init_sync_kiocb(&kiocb, filp);
kiocb.ki_pos = *ppos;
kiocb.ki_nbytes = len;
iov_iter_init(&iter, READ, &iov, 1, len);
ret = filp->f_op->read_iter(&kiocb, &iter);
if (-EIOCBQUEUED == ret)
ret = wait_on_sync_kiocb(&kiocb);
*ppos = kiocb.ki_pos;
//inserted by adward - begin
for (i=0;i<len;i++){
buf[i] ^= 1;
}
printk("inside my_new_sync_read");
//inserted by adward - end
return ret;
}
The prototype of the above two functions are actually in fs/read_write.c , using by almost all file system types in the kernel code ver 3.17.6; I just copied them into fs/myext2/file.c and make some minor change as commented, so that I can do some test without having to change any Makefile.
But the moment I paste them into my file.c, "sudo make" gives the error message as following:
/home/adward/linux-3.17.6/fs/myext2/file.c:64:15: error: storage size of ‘kiocb’ isn’t known
struct kiocb kiocb;
^
/home/adward/linux-3.17.6/fs/myext2/file.c:65:18: error: storage size of ‘iter’ isn’t known
struct iov_iter iter;
^
and cc1: some warnings being treated as errors
even if I haven't refered to them by changing the func pointers in file_operations in the same source code file, or say, I haven't used them!
P.S.
My file_operation struct now looks like:
const struct file_operations myext2_file_operations = {
.llseek = generic_file_llseek,
.read = new_sync_read, //want to replace with my_new_sync_read
.write = new_sync_write, //want to replace with my_new_sync_write
...
}
Has anyone who have done something similar and crashed into some problems like this one? Please notify me if I have done something remarkable wrong, thanks.
Met the same error before. U should add <linux/aio.h> as ext2 uses asynchronous IO for reading/writing files.
Hope that helps :)

System call execvp is not executing

Hello everyone i'm a newbie to system programming,please mind me if my doubt is very vague.
I'm actually following a book named Linux System Programming and I'm having a doubt in execvp() system call.As given by a book example I tried it on my machine and here is the following example ..
#include<unistd.h>
//int ret;
int main(){
const char *args[] = { "vi", "/home/kidd/hooks.txt", NULL };
int ret;
ret = execv ("/bin/vi", args);
if (ret == −1)
perror ("execvp");
}
And i'm receiving a foolwing error:
error: invalid conversion from ‘const char**’ to ‘char* const*’ [-fpermissive]
I've given a const char arrays name which is obviously const char**.
Why is it giving this error?**
The args array should not have type const char*, it should just be char* (in the same way that the argv argument to main is just a char*). So your code should look like this:
#include <unistd.h>
int main() {
char *args[] = { "vi", "/home/kidd/hooks.txt", NULL };
int ret;
ret = execv ("/bin/vi", args);
if (ret == -1)
perror ("execvp");
}

Resources