C89: getaddrinfo() on Windows? - c

I'm new to C89, and trying to do some socket programming:
void get(char *url) {
struct addrinfo *result;
char *hostname;
int error;
hostname = getHostname(url);
error = getaddrinfo(hostname, NULL, NULL, &result);
}
I am developing on Windows. Visual Studio complains that there is no such file if I use these include statements:
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
What should I do? Does this mean that I won't have portability to Linux?

On Windows, instead of the includes you have mentioned, the following should suffice:
#include <winsock2.h>
#include <windows.h>
You'll also have to link to ws2_32.lib. It's kind of ugly to do it this way, but for VC++ you can do this via: #pragma comment(lib, "ws2_32.lib")
Some other differences between Winsock and POSIX include:
You will have to call WSAStartup() before using any socket functions.
close() is now called closesocket().
Instead of passing sockets as int, there is a typedef SOCKET equal to the size of a pointer. You can still use comparisons with -1 for error, though Microsoft has a macro called INVALID_SOCKET to hide this.
For things like setting non-blocking flags, you'll use ioctlsocket() instead of fcntl().
You'll have to use send() and recv() instead of write() and read().
As for whether or not you will lose portability with Linux code if you start coding for Winsock... If you are not careful, then yes. But you can write code that tries to bridge the gaps using #ifdefs..
For example:
#ifdef _WINDOWS
/* Headers for Windows */
#include <winsock2.h>
#include <windows.h>
#else
/* Headers for POSIX */
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
/* Mimic some of the Windows functions and types with the
* POSIX ones. This is just an illustrative example; maybe
* it'd be more elegant to do it some other way, like with
* a proper abstraction for the non-portable parts. */
typedef int SOCKET;
#define INVALID_SOCKET ((SOCKET)-1)
/* OK, "inline" is a C99 feature, not C89, but you get the idea... */
static inline int closesocket(int fd) { return close(fd); }
#endif
Then once you do something like this, you can code against the functions which appear in both OS's, using these wrappers where appropriate.

Related

'SO_USELOOPBACK' was not declared in this scope

I am checking socket options and I got this error when I compile. I tried to google it and it looks like no one has encountered this problem before.
#include <netinet/tcp.h>
#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdlib.h>
static char *sock_str_flag(union val *, int);
struct sock_opts {
const char *opt_str;
int opt_level;
int opt_name;
char *(*opt_val_str)(union val *, int);
}sock_opts[] = {
{ "SO_USELOOPBACK", SOL_SOCKET, SO_USELOOPBACK, sock_str_flag } //this is the error
};
The socket option SO_USELOOPBACK is not a POSIX standard. The man page setsockopt() describes the nature of SO_USELOOPBACK in detail.
The SO_USELOOPBACK is a [Digital] standard. Text paragraphs preceded by [Digital] document features that are included in the DIGITAL UNIX software but are not currently specified by any standard that applies to the interface being described. Use these features when source code portability across multiple UNIX platforms is less important than the capabilities that the features provide.
For portability, you need to have ifdef checks.
struct sock_opts {
const char *opt_str;
int opt_level;
int opt_name;
char *(*opt_val_str)(union val *, int);
}sock_opts[] = {
/* .... */
#ifdef SO_USELOOPBACK
{"SO_USELOOPBACK", SOL_SOCKET, SO_USELOOPBACK, sock_str_flag }
#endif
/* .... */
};

How to correctly use inet_pton rotine in Windows 10?

I'd noticed that arpa/inet.h lib is not available for Windows platform. Also read that winsock2.h implements an analog function InetPton to converts an IPv4 or IPv6 Internet network address. Then I tried to build some instructions like:
#include <winsock2.h>
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
struct sockaddr_in sa;
InetPton(AF_INET, "10.20.30.40", &(sa.sin_addr));
}
And get below compilation error:
undefined reference to `InetPton'
What I need to do/include to use this function on Windows (10)?
You need to include the ws2_32.lib library. That contains the Winsock functions.
See the MSDN page for InetNtop for more details.

Can't use sa_sigaction - "sigaction doens't have a field sa_sigaction"

Hey guys I am messing around with signals, and have a weird error:
I want to set a value to the member sa_sigaction but IDE and compiler seem to not find it..
#define _POSIX_SOURCE
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <signal.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/wait.h>
#include <bits/siginfo.h>
struct sigaction new_action;
void SIGUSR1_handler(int sig, siginfo_t *siginfo, void *context) {
......
}
memset(&new_action, '\0', sizeof(new_action)); //cleaning the memory
new_action.sa_sigaction = SIGUSR1_handler; //setting the handler for the signal
new_action.sa_flags = SA_SIGINFO;
I only posted the relevant part of the code.
Can anybody help me out here?
EDIT: And how can I put something in the siginfo struct or context pointer?
You don't specify your OS so I can't be sure, but I think the problem is that you're inadvertently requesting an ancient version of POSIX that lacks it via the following incorrect feature test macro usage:
#define _POSIX_SOURCE
The _POSIX_SOURCE macro itself is deprecated; you should be using _POSIX_C_SOURCE and defining it to the version of the API you want. To ensure the availability of a working sigaction, you probably want:
#define _POSIX_C_SOURCE 200809L
since it was (if I recall correctly) an XSI extension in earlier versions of the standard. Alternatively you might use:
#define _XOPEN_SOURCE 600 /* or 700 */
since the functionality you want was available as an XSI extension in Issue 6.

What is the proper #include for the function 'sleep()'?

I am using the Big Nerd Ranch book Objective-C Programming, and it starts out by having us write in C in the first few chapters. In one of my programs it has me create, I use the sleep function. In the book it told me to put #include <stdlib.h> under the #include <stdio.h> part. This is supposed to get rid of the warning that says "Implicit declaration of function 'sleep' is invalid in C99". But for some reason after I put #include <stdlib.h>, the warning does not go away.. This problem does not stop the program from running fine, but I was just curious on which #include I needed to use!
The sleep man page says it is declared in <unistd.h>.
Synopsis:
#include <unistd.h>
unsigned int sleep(unsigned int seconds);
sleep is a non-standard function.
On UNIX, you shall include <unistd.h>.
On MS-Windows, Sleep is rather from <windows.h>.
In every case, check the documentation.
this is what I use for a cross-platform code:
#ifdef _WIN32
#include <Windows.h>
#else
#include <unistd.h>
#endif
int main()
{
pollingDelay = 100
//do stuff
//sleep:
#ifdef _WIN32
Sleep(pollingDelay);
#else
usleep(pollingDelay*1000); /* sleep for 100 milliSeconds */
#endif
//do stuff again
return 0;
}
What is the proper #include for the function 'sleep()'?
sleep() isn't Standard C, but POSIX so it should be:
#include <unistd.h>
sleep(3) is in unistd.h, not stdlib.h. Type man 3 sleep on your command line to confirm for your machine, but I presume you're on a Mac since you're learning Objective-C, and on a Mac, you need unistd.h.
Given that sleep is a non-standard function, I created a sleep function with the standard library time.h
#include <time.h>
void sleep(double s) {
time_t cur_time = time(NULL);
while ((difftime(time(NULL), cur_time)) < s);
}

How do I find the MAC address programatically on IRIX?

How do I find the MAC address of a network card on IRIX? I'd rather not shell out to something that displays it and parse the output.
I'm coding C.
Methods that require root access are acceptable.
#include <net/raw.h>
#include <net/if.h>
#include <net/soioctl.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
...
struct ifreq ifdat;
int s;
s = socket (PF_RAW, SOCK_RAW, RAWPROTO_SNOOP);
strcpy (ifdat.ifr_name, "en0");
ioctl (s, SIOCGIFADDR, &ifdat);
...
Clean it up a little, and ifdat should contain your MAC address.
I don't know about programmatically, but you could try /etc/nvram eaddr, I suppose you could exec() that.
On some platforms (Linux, for example) ioctl() allows to obtain MAC address. You need to check on IRIX as ioctl() is platform-dependent.

Resources