I'm trying to write the simpliest client in RPC with this code:
#include <stdio.h>
#include <stdlib.h>
#include <rpc/rpc.h>
int main(int argc, char *argv[]){
int stat;
char out;
char in='f';
if(stat=callrpc(argv[1],0x20000001, 1, 1, (xdrproc_t)xdr_void, &in, (xdrproc_t)xdr_char, &out)!=0){
clnt_perrno(stat);
exit(1);
}
exit(0);
}
It compiles, but when I try to run it, it gives me a "RPC: Can't encode arguments"
EDIT: Actually the server do not recieve any argument neither it send back anything, that's why I put a xdr_void added &in and &out to avoid segmentation fault error.
You are missing some parentheses:
if (stat = callrpc(...) != 0)
is evaluated to
if (stat = (callrpc(...) != 0))
which always assigns 1 to stat in case of an error, which is RPC_CANTENCODEARGS. You need
if ((stat = callrpc(...)) != 0)
to get the real error code and message printed in
clnt_perrno(stat);
Related
I'm trying to retrieve the information from a share using the C Windows API. For compilation I'm using the MINGW64 flavor of MSYS2 (https://www.msys2.org/docs/environments/). But I'm having problems when I try to convert the SIDs in the security descriptor to plain text names. This is a simplified version of my code:
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <lm.h>
#include <ntstatus.h>
#include <ntsecapi.h>
int main(int argc, char **argv) {
NET_API_STATUS res1;
NTSTATUS res2;
// Get info from share
SHARE_INFO_502 *info;
res1 = NetShareGetInfo(L"domain.tld", L"test", 502, (LPBYTE *)&info);
if (res1 != 0) {
fprintf(stderr,
"NetShareGetInfo failed with error %d\n",
res1);
exit(EXIT_FAILURE);
}
// Validate security descriptor
SECURITY_DESCRIPTOR *sd = info->shi502_security_descriptor;
if (IsValidSecurityDescriptor(sd) == 0) {
fprintf(stderr, "Security descriptor is not valid\n");
exit(EXIT_FAILURE);
}
// Open policy handle
LSA_HANDLE polHandle;
LSA_OBJECT_ATTRIBUTES polAttrs;
memset(&polAttrs, '\0', sizeof(polAttrs)); // must be zero according to docs
res2 = LsaOpenPolicy(NULL, &polAttrs, POLICY_EXECUTE, &polHandle);
if (res2 != STATUS_SUCCESS) {
fprintf(stderr,
"LsaOpenPolicy failed with error %d (converted from %lX)\n",
LsaNtStatusToWinError(res2), res2);
exit(EXIT_FAILURE);
}
// Translate owner SID
LSA_TRANSLATED_NAME *names;
LSA_REFERENCED_DOMAIN_LIST *domains;
res2 = LsaLookupSids2(polHandle, 0, 1, &sd->Owner, &domains, &names);
if (res2 != STATUS_SUCCESS) {
fprintf(stderr,
"LsaLookupSids2 failed with error %d (converted from %lX)\n",
LsaNtStatusToWinError(res2), res2);
exit(EXIT_FAILURE);
}
// do something here with names and domains
LsaFreeMemory(names);
LsaFreeMemory(domains);
return 0;
}
I then compile it and execute it:
C:\Users\myname\Desktop\c-tests\sdproblem>main.exe
LsaLookupSids2 failed with error 87 (converted from C000000D)
Error 87 means "The parameter is incorrect". It seems I'm not passing the arguments correctly to the LsaLookupSids2 function. But I'm not able to see what I'm doing wrong. I've tried passing some flags in the second argument instead of 0 to no avail. I've also tried to use LsaLookupSids (and remove the second argument) but still no luck. The share exists and the permissions can be retrieved by icacls:
C:\Users\myname\Desktop\c-tests\sdproblem>icacls \\domain.tld\test
\\domain.tld\test Everyone:(OI)(CI)(F)
Can someone help me with this issue?
The code below returns EFAULT (errno == 14). I would appreciate help figuring out why.
I've also tried to implement the code using select() but still got the same error code.
I've got very similar code running on Python with no issues.
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
int read_fail1(int fd)
{
int n;
char buf[500];
for (;;)
{
buf[strlen(buf)-1] = 0;
n = read(fd, buf, strlen(buf)-1);
if (n == -1)
{
if (errno == EFAULT)
{
fprintf(stderr, "EFAULT");
return 42;
}
}
else if (n > 0)
{
fprintf(stderr, "%s", buf);
}
}
}
int main(int argc, const char *argv[])
{
const char *myfifo = "pipeMUD";
mkfifo(myfifo, 0666);
int fd = open(myfifo, O_RDWR | O_NONBLOCK);
if (fd <= 0)
return 42;
read_fail1(fd);
return 0;
}
POST ANSWER EDIT:
As mentioned in the post linked below, if an invalid address is passed to the kernel, it throws the EFAULT. I guess that on Linux, based on the above code, passing a 0 length count parameter to read() will also cause EFAULT to be retured.
unix socket error 14: EFAULT (bad address)
This line:
buf[strlen(buf)-1] = 0;
buf if a local variable, and thus is not initialized in C.
strlen looks for '\0' (null character) value, and thus will give unpredictable result on uninitialized array.
But, as long as you declare buf statically as you do, you can use sizeof instead.
Though it would be a better practice to use a macro instead:
#define READ_BUFFER_SIZE 500
char buf[READ_BUFFER_SIZE];
n = read(fd, buf, READ_BUFFER_SIZE - 1);
I'm relatively new to C and I'm starting to work with threads and the command line; I just need help with a bit of debugging and error handling. I've run into a segmentation fault every time I try and process the code. It works fine if there is an argument for argv[1]. However, when trying to catch any errors, such as only entering "./example" and nothing else, it finds a segmentation fault.
I have tried variations of the following code to no avail, including looking to see if argc < 1:
int main(int argc, char * argv[]){
pthread_t worker1;
int in;
if(arv[1] == NULL){
printf("ERROR HERE");
}else{
in = strtol(argv[1], &endptr, 10);
}
if(*endptr > in || *endptr == in){
printf("please eneter a number larger than zero");
return EXIT_FAILURE;
}else{
pthread_create(&worker1, NULL, worker, &in);
pthread_join(worker1, NULL);
}
return EXIT_SUCCESS;
}
Below is the current code which I am using, I'm pretty sure it's something small that I'm overlooking. I have never used strtol before and was using atoi before, I have heard it's a better practice to do this. I'm relatively sure the error is in the code provided as when I test the thread function, it works fine; if more is needed please let me know!
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <time.h>
int main(int argc, char * argv[]){
pthread_t worker1;
int in = strtol(argv[1], &endptr, 10);
if(*endptr > in || *endptr == in){
printf("please eneter a number larger than zero");
return EXIT_FAILURE;
}else{
pthread_create(&worker1, NULL, worker, &in);
pthread_join(worker1, NULL);
}
return EXIT_SUCCESS;
}
You are trying to access an array without doing any kind of bounds checking first:
int main(int argc, char * argv[]){
pthread_t worker1;
int in = strtol(argv[1], &endptr, 10);
...
Who is to say that argv[1] exists? Certainly not your program, because it doesn't check that condition first. Add a check on argc to make sure you are getting the number of arguments you expect before trying to use them.
if (argc > 1) {
int in = strtol(argv[1], &endptr, 10);
}
Programming Language C
below is the code that uses multiple threads to print out a file. There are no errors, however the code doesn't work correctly. However, when compiled it shows this warning 5 times:
'cast from pointer to integer of different size'
I've tried everything I can think of to resolve this issue, but haven't been success and now are just shooting in the dark. Does anyone see where my mistake is? Any help is greatly appreciated and will gladly provide any other information upon request.
Thanks.
#include <sys/mman.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#define NUM_THREAD 4
struct fileParams {
int fd;
int size;
};
void *printFile(void *stuff)
{
struct fileParams *params = stuff;
int addr;
addr=(unsigned char *)mmap(NULL, (int) ¶ms->size, PROT_READ,
MAP_PRIVATE,(int) ¶ms->fd,0);
write(STDOUT_FILENO, addr, (int)¶ms->size);
}
int main (int argc, char * argv[])
{
pthread_t threads[NUM_THREAD];
unsigned char *addr;
int fd,rc;
struct stat sb;
int numCPU=sysconf(_SC_NPROCESSORS_ONLN);
struct fileParams params;
printf("Number of aviable cores: %d\n",numCPU);
printf("Using 4 processors\n");
if (argc != 2 || strcmp(argv[1], "—help") == 0)
printf("Usage: %s file\n", argv[0]);
fd=open(argv[1],O_RDONLY);
if (fd == -1)
{
printf("File open fdailed.\n");
exit(EXIT_FAILURE);
}
if (fstat(fd, &sb) == -1)
{
printf ("fstat error\n");
exit(EXIT_FAILURE);
}
params.fd=fd;
params.size=sb.st_size/4;
for (int n = 0; n<4; n++)
rc=pthread_create(&threads[n],NULL,printFile,¶ms);
exit(EXIT_SUCCESS);
}
You need provide inputs to functions that match the function - passing pointers where integers are wanted (or the other way around) will generate warnings or errors depending on compile options.
mmap takes an size_t as the 2nd parameter, but you are giving it a cast int to a pointer (¶ms->size), the same with mmaps 5th parameter.
Get rid of the '&' so it is just a int.
mmap also returns a void *, which you are then assigning to addr (an int).
Change int to a void * pointer type which should also fix the 5th warning.
I'm currently learning the C language in college so this is a homework assignment but I have a small problem. I'm guessing I've just misjudged the syntax or are missing something really obvious. My compiler is telling me that there is:
expected declaration specifiers or "..." before constant
and pointing to the O_RDWR.
I've googled and searched on Stack Exchange but there doesn't seem anything specific to it. Following the syntax in a C reference it's fine. I've looked around and it says I have not predefined the typedef but I've tried that to no avail.
I've starred the section that is causing the problem according to the compiler with **
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
int main (int argc, char *argv[])
{
int count;
printf ("This program was called \"%s\".\n",argv[0]);
if (argc > 1)
{
for (count = 1; count < argc; count++)
{
printf("argv[%d] = %s\n", count, argv[count]);
}
}
else
{
printf("The command had no arguments.\n");
}
if (argc == 4)
{
printf("There are the correct number of arguments(4)");
}
else
{
printf("Not enough arguments! please try again");
}
**int open(const char *argv[1], O_RDWR);
return 0;**
}
int open(const char *argv[1], O_RDWR);
What are you trying to do by this statement? Compiler treats this as function declaration, not function call. And it fails because O_RDWR is not a type name. If you need to call open(), syntax shall be like this:
int fd = open(argv[1], O_RDWR);
if(fd != -1)
{
// File opened OK. Proceed with file operations.
}
else
{
// File failed to open. Handle error occured
}
Try open(argv[1], O_RDWR); - you don't need to specify the arg's type or the return value.
... and I'm assuming the **'s are just to highlight the problem area - if not, they should go too... edit: just noticed you said that in the question!
The open call returns a HANDLE to the specified file of type int. So you only have to declare an int type HANDLE to collect from open. So,
int FileDesc ;
FileDesc = open( argv[1], O_RDWRD ) ;
// Check for Errors here