I am writing a packet sniffer using c and libpcap functions. following is the source code.
#include <pcap.h>
#include <stdlib.h>
#include <stdio.h>
#include "YYY.h"
void pcap_fatal(const char *failed_in, const char *errbuf){
printf("Fata Error in %s: %s\n", failed_in, errbuf);
exit(1);
}
int main(){
struct pcap_pkthdr header;
const u_char *packet;
char errbuf[PCAP_ERRBUF_SIZE];
char *device;
pcap_t *pcap_handle;
int i;
device = pcap_lookupdev(errbuf);
if(device == NULL)
pcap_fatal("pcap_lookupdev", errbuf);
printf("Sniffing of device %s\n", device);
pcap_handle = pcap_open_live(device, 4096, 1, 0, errbuf);
for(i=0;i<3;i++){
packet = pcap_next(pcap_handle, &header);
printf("Got a %d bute packet\n", header.len);
dump(packet, header.len);
}
pcap_close(pcap_handle);
}
However when I tried to compile it with gcc it gives the following warning as follows.
libcap_sniff.c: In function ‘main’:
libcap_sniff.c:20:2: warning: ‘pcap_lookupdev’ is deprecated: use 'pcap_findalldevs' and use the first device [-Wdeprecated-declarations]
20 | device = pcap_lookupdev(errbuf);
| ^~~~~~
In file included from /usr/include/pcap.h:43,
from libcap_sniff.c:1:
/usr/include/pcap/pcap.h:394:16: note: declared here
394 | PCAP_API char *pcap_lookupdev(char *)
| ^~~~~~~~~~~~~~
can anyone help me with this. I don't yet know what a deprecated warnning is.
Use pcap_findalldevs instead of pcap_lookupdev.
Deprecating software means that it may be usable but is regarded as obsolete and that it should be avoided. Usually deprecated software has been replaced by an alternative.
GCC has features for marking functions has deprecated. When a program uses a function that is marked as deprecated, GCC warns you about it, so that you can modify the code to use more modern functions. Deprecated functions may be removed in future versions of the software they are part of.
This documentation indicates that you can use pcap_findalldevs to perform the function of the pcap_lookupdev routine.
gcc has a non-standard extension called function attributes which can be used for all manner of things, such as inlining or declaring functions in a certain memory section. They are used by writing __attribute__ (arg) after a function declaration (not after a function definition).
One of these attributes is called deprecated, which tells gcc to give the application programmer a warning about an obsolete function getting called. Optionally, deprecated can be given a message argument. Example:
#include <stdio.h>
void foo (void) __attribute__((deprecated("consider using bar instead")));
void foo (void)
{
puts("foo");
}
int main (void)
{
foo();
}
This gives:
warning: 'foo' is deprecated: consider using bar instead [-Wdeprecated-declarations]
foo();
This warning is enabled by default. To shut it up, one needs to explicitly use the compiler option -Wno-deprecated-declarations.
As for why your specific function is deprecated, you have to consult the (lacking) documentation for it. man doesn't mention why it is deprecated.
Beware: the beginning of the question is about the generic warning. The correct answer to the actual question is later in the post.
Although the standard only defines the #error directive, most common implementations accepts a non fatal #warning one. They can be used by libraries writer to raise errors or warnings when something can be detected at compilation time.
This just means that the guys from libpcap have deprecated usage of pcap_lookupdev and that it is likely to be removed in a later version. They just warn users of their library to stop using it in new code.
But here a different mechanism is involved. Gnu C compiler (but maybe others) have a specific attribute to indicate deprecation. It is intended to be used with the special option -Wdeprecated-declarations to switch deprecation warnings on, and -Wno-deprecated-declaration to switch them off.
Related
I get the following compiler error, even though there is no "do" expression in my code.
gcc -Wall -g -c main.c -lasound
In file included from /usr/include/alsa/asoundlib.h:49:0,
from main.c:2:
main.c: In function ‘main’:
main.c:8:5: error: expected expression before ‘do’
if(snd_pcm_hw_params_alloca(¶ms) < 0) {
^
main.c:6:30: warning: unused variable ‘params’ [-Wunused-variable]
snd_pcm_hw_params_t *params;
^~~~~~
Makefile:15: recipe for target 'main.o' failed
make: *** [main.o] Error 1
From the following minimal reproducible example:
#include <stdio.h>
#include <alsa/asoundlib.h>
int main(int argc, char **argv)
{
snd_pcm_hw_params_t *params;
if(snd_pcm_hw_params_alloca(¶ms) < 0) {
return 0;
}
exit(0);
}
I'm aware this is not a valid ALSA program. I'm also aware that it appears snd_pcm_hw_params_alloca() doesn't even return anything worthwhile to check for errors against? That's not relevant though, this should valid C code regardless, even if it abuses the API.
Where is the "do" expression? If I go to /usr/include/alsa/asoundlib.h and poke around there, I don't see anything obvious that would indicate a problem.
If I remove the conditional if test, and get:
#include <stdio.h>
#include <alsa/asoundlib.h>
int main(int argc, char **argv)
{
snd_pcm_hw_params_t *params;
snd_pcm_hw_params_alloca(¶ms);
exit(0);
}
This will compile with no errors.
What is this?
If I look in pcm.h, I see:
#define snd_pcm_hw_params_alloca(ptr) __snd_alloca(ptr, snd_pcm_hw_params)
int snd_pcm_hw_params_malloc(snd_pcm_hw_params_t **ptr);
void snd_pcm_hw_params_free(snd_pcm_hw_params_t *obj);
void snd_pcm_hw_params_copy(snd_pcm_hw_params_t *dst, const snd_pcm_hw_params_t *src);
However, this doesn't tell me anything. Why does the compiler produce this error?
I'm also aware that it appears snd_pcm_hw_params_alloca() doesn't even return anything worthwhile to check for errors against? That's not relevant though, this should valid C code regardless, even if it abuses the API.
No, if snd_pcm_hw_params_alloca() does not have a value you cannot compare it against 0. For example, the following is also invalid:
void func(void) { }
void other(void) {
if (func() < 0) { // Error
}
}
In reality, snd_pcm_hw_params_alloca() is a macro, and it’s a wrapper for another macro, __snd_alloca. The do is there to make it behave more like a statement. You can only call it as a statement on its own line, or anywhere else where a do loop is legal.
snd_pcm_hw_params_alloca(¶ms);
You cannot check for errors because alloca() does not check for errors. If alloca() fails, it will just stomp on your stack, and bad things will happen. You can’t do anything about it, except not use alloca() (this is why you might hear advice to avoid alloca).
For an explanation of why the do loop is used, see: C multi-line macro: do/while(0) vs scope block
For more information about how alloca() works, see: Why is the use of alloca() not considered good practice?
I'm running OS X Sierra and trying to compile a c program that uses strcpy_s, but my installed clang compiler is using the c99 standard, but from what I've read strcpy_s requires c11.
Here's the code I'm trying to compile
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char source[] = "Test string";
char destination[50];
if(strcpy_s(destination, sizeof(destination), source))
printf("string copied - %s",destination);
return 0;
}
And here's the command I'm using to compile
$ clang copytest.c -o copytest
copytest.c:11:5: warning: implicit declaration of function 'strcpy_s' is invalid in C99 [-Wimplicit-function-declaration]
if(strcpy_s(copied_string, sizeof(copied_string), source))
^
1 warning generated.
Undefined symbols for architecture x86_64:
"_strcpy_s", referenced from:
_main in copytest-e1e05a.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
I've tried compiling with the standard flag...
clang -std=c11 copytest.c -o copytest
but I get the same exact "invalid in c99" warning. I've also tried compiling with gcc instead, and I still get the same c99 warning.
I tried upgrading via homebrew which shows the following
Warning: gcc 9.2.0 is already installed and up-to-date
I have clang version 9.0.0
$ clang -v
Apple LLVM version 9.0.0 (clang-900.0.39.2)
My xcode version is Xcode 9.2, which from everything I've read should come with c11 support.
Am I doing something wrong with the compiling, is my code itself incorrect? This is the only similar question I found on here, but it didn't even have an answer. Thanks
The _s functions are an optional component of the 2011 C standard (Annex K), and, to the best of my knowledge, they have never been implemented as an integrated part of any C library. Portable code cannot rely on their availability. (Microsoft's C compilers for Windows implement an overlapping set of functions with the same names but different semantics (and sometimes even a different argument list), and at least one bolt-on implementation does exist. See this old answer, and the much longer question and answer it links to, for more detail.)
Also, the _s functions do not solve the problem that they were intended to solve (unsafe string handling); it is necessary to put actual thought into a proper fix for each use of strcpy, instead of globally search-and-replacing strcpy with strcpy_s, etc., as was the hope of the authors of Annex K. If you do put appropriate amounts of thought into a proper fix, you won't need any of the _s functions to implement it. For instance, here's a fixed version of your example program:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char source[] = "Test string";
char destination[50];
size_t srclen = strlen(source);
if (srclen + 1 > sizeof destination) {
fprintf(stderr, "string too long to copy - %zu bytes, need %zu\n",
sizeof destination, srclen + 1);
return 1;
} else {
memcpy(destination, source, srclen + 1);
printf("string copied - %s\n", destination);
return 0;
}
}
And here's an even better version:
#define _XOPEN_SOURCE 700
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
if (argc != 2) {
fprintf(stderr, "usage: ./test 'message of arbitrary length'\n");
return 1;
}
char *destination = strdup(argv[1]);
if (!destination) {
perror("strdup");
return 1;
}
printf("string copied - '%s'\n", destination);
free(destination);
return 0;
}
Therefore: Never use any of the _s functions. If you need to write a program that compiles on Windows with no warnings, put #define _CRT_SECURE_NO_WARNINGS 1 at the top of each file to make MSVC stop giving you bad advice.
If all, or even most, programmers wrote the suggested solutions above all the time, then these functions wouldn't be needed. We have a lot of evidence that many programmers do not write such careful code, going back to Spaf's notes on the Robert T Morris finger worm in the late 1980's.
You also would prefer not to have to duplicate 10 lines of code for every call site of strcpy. That leads to unreadable code. More so, what zwol suggests is really just an implementation of the function he claims we don't need. A good programmer would take that, stick it in a header, and name it something helpful, maybe checked_strcpy? Or even strcpy_s?
The second suggested implementation, which is purportedly better is not - it would cause an allocation when we might already have a buffer. Allocations are expensive, using this approach everywhere would be bad for perf. It also introduces new complexity because now we'd have to free every duplicated string - imagine doing that with repeated calls to strcat.
There is a fairly nicely done cross-platform implementation here:
https://github.com/intel/safestringlib
I'm also not sure whether this is actually any different, but worth taking a look - https://github.com/coruus/safeclib
I'm creating a cross-system application. It uses, for example, the function itoa, which is implemented on some systems but not all. If I simply provide my own itoa implementation:
header.h:115:13: error: conflicting types for 'itoa'
extern void itoa(int, char[]);
In file included from header.h:2:0,
from file.c:2:0,
c:\path\to\mingw\include\stdlib.h:631:40: note: previous declaration of 'itoa' was here
_CRTIMP __cdecl __MINGW_NOTHROW char* itoa (int, char*, int);
I know I can check if macros are predefined and define them if not:
#ifndef _SOME_MACRO
#define _SOME_MACRO 45
#endif
Is there a way to check if a C function is pre-implemented, and if not, implement it? Or to simply un-implement a function?
Given you have already written your own implementation of itoa(), I would recommend that you rename it and use it everywhere. At least you are sure you will get the same behavior on all platforms, and avoid the linking issue.
Don't forget to explain your choice in the comments of your code...
I assume you are using GCC, as I can see MinGW in your path... there's one way the GNU linker can take care of this for you. So you don't know whether there is an itoa implementation or not. Try this:
Create a new file (without any headers) called my_itoa.c:
char *itoa (int, char *, int);
char *my_itoa (int a, char *b, int c)
{
return itoa(a, b, c);
}
Now create another file, impl_itoa.c. Here, write the implementation of itoa but add a weak alias:
char* __attribute__ ((weak)) itoa(int a, char *b, int c)
{
// implementation here
}
Compile all of the files, with impl_itoa.c at the end.
This way, if itoa is not available in the standard library, this one will be linked. You can be confident about it compiling whether or not it's available.
Ajay Brahmakshatriya's suggestion is a good one, but unfortunately MinGW doesn't support weak definition last I checked (see https://groups.google.com/forum/#!topic/mingwusers/44B4QMPo8lQ, for instance).
However, I believe weak references do work in MinGW. Take this minimal example:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
__attribute__ ((weak)) char* itoa (int, char*, int);
char* my_itoa (int a, char* b, int c)
{
if(itoa != NULL) {
return itoa(a, b, c);
} else {
// toy implementation for demo purposes
// replace with your own implementation
strcpy(b, "no itoa");
return b;
}
}
int main()
{
char *str = malloc((sizeof(int)*3+1));
my_itoa(10, str, 10);
printf("str: %s\n", str);
return 0;
}
If the system provides an itoa implementation, that should be used and the output would be
str: 10
Otherwise, you'll get
str: no itoa
There are two really important related points worth making here along the "don't do it like this" lines:
Don't use atoi because it's not safe.
Don't use atoi because it's not a standard function, and there are good standard functions (such as snprintf) which are available to do what you want.
But, putting all this aside for one moment, I want to introduce you to autoconf, part of the GNU build system. autoconf is part of a very comprehensive, very portable set of tools which aim to make it easier to write code which can be built successfully on a wide range of target systems. Some would argue that autoconf is too complex a system to solve just the one problem you pose with just one library function, but as any program grows, it's likely to face more hurdles like this, and getting autoconf set up for your program now will put you in a much stronger position for the future.
Start with a file called Makefile.in which contains:
CFLAGS=--ansi --pedantic -Wall -W
program: program.o
program.o: program.c
clean:
rm -f program.o program
and a file called configure.ac which contains:
AC_PREREQ([2.69])
AC_INIT(program, 1.0)
AC_CONFIG_SRCDIR([program.c])
AC_CONFIG_HEADERS([config.h])
# Checks for programs.
AC_PROG_CC
# Checks for library functions.
AH_TEMPLATE([HAVE_ITOA], [Set to 1 if function atoi() is available.])
AC_CHECK_FUNC([itoa],
[AC_DEFINE([HAVE_ITOA], [1])]
)
AC_CONFIG_FILES([Makefile])
AC_OUTPUT
and a file called program.c which contains:
#include <stdio.h>
#include "config.h"
#ifndef HAVE_ITOA
/*
* WARNING: This code is for demonstration purposes only. Your
* implementation must have a way of ensuring that the size of the string
* produced does not overflow the buffer provided.
*/
void itoa(int n, char* p) {
sprintf(p, "%d", n);
}
#endif
int main(void) {
char buffer[100];
itoa(10, buffer);
printf("Result: %s\n", buffer);
return 0;
}
Now run the following commands in turn:
autoheader: This generates a new file called config.h.in which we'll need later.
autoconf: This generates a configuration script called configure
./configure: This runs some tests, including checking that you have a working C compiler and, because we've asked it to, whether an itoa function is available. It writes its results into the file config.h for later.
make: This compiles and links the program.
./program: This finally runs the program.
During the ./configure step, you'll see quite a lot of output, including something like:
checking for itoa... no
In this case, you'll see that the config.h find contains the following lines:
/* Set to 1 if function atoi() is available. */
/* #undef HAVE_ITOA */
Alternatively, if you do have atoi available, you'll see:
checking for itoa... yes
and this in config.h:
/* Set to 1 if function atoi() is available. */
#define HAVE_ITOA 1
You'll see that the program can now read the config.h header and choose to define itoa if it's not present.
Yes, it's a long way round to solve your problem, but you've now started using a very powerful tool which can help you in a great number of ways.
Good luck!
I'm exploring high-precision time functions in C. I came across clock_gettime and read about it here:
http://man7.org/linux/man-pages/man2/clock_gettime.2.html
I notice it says:
Link with -lrt (only for glibc versions before 2.17).
I wonder why I can use lower-precision time functions without needing to add anything to my gcc compile line? Is there a way for me to use the high-precision code differently so I don't need to add anything on my compile line?
I understand my system is using an old....old version of glibc, which is why I have to do this in my case, but I'm asking for the sake of those (such as myself) who are unable to update glibc.
Code in progress:
#include <stdio.h>
#include <time.h>
int main(int argc, char **argv)
{
int result;
struct timespec tp;
clockid_t clk_id;
// clk_id = CLOCK_REALTIME;
clk_id = CLOCK_MONOTONIC;
// clk_id = CLOCK_BOOTTIME;
// clk_id = CLOCK_PROCESS_CPUTIME_ID;
// int clock_gettime(clockid_t clk_id, struct timespec *tp);
result = clock_gettime(clk_id, &tp);
printf("result: %i\n", result);
printf("tp.tv_sec: %lld\n", tp.tv_sec);
printf("tp.tv_nsec: %ld\n", tp.tv_nsec);
result = clock_getres(clk_id, &tp);
printf("result: %i\n", result);
printf("tp.tv_sec: %lld\n", tp.tv_sec);
printf("tp.tv_nsec: %ld\n", tp.tv_nsec);
}
The functions that you can call without mentioning a library are located in libc. The -lc option to link to this library is silently added for you.
To call functions in other libraries, you must add the corresponding -l (and possibly -L) option to your linking command. This is normal, and you shouldn't feel like this means something is wrong.
There is no rational explanation for which functions are included in libc and which ones aren't. It's just historical accident. Just be thankful to the nice people who write the man pages for putting the necessary linker options are right their at the top of the page so you don't have to hunt for them.
clock_gettime() is a wrapper of the system call. If you are on a limited environment (where librt is not available), you may use syscall() directly to bypass the libc wrapper. You can see an example in BusyBox libbb/time.c.
How do I compile the lex file with gcc without receiving the following warnings?
lex.yy.c: In function `yy_init_buffer':
lex.yy.c:1688: warning: implicit declaration of function `fileno'
lex.l: In function `storeLexeme':
lex.l:134: warning: implicit declaration of function `strdup'
These are the libraries I included.
%{
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
%}
The function yy_init_buffer is not in the file. The following is the function storeLexeme.
int storeLexeme() {
for (int i = 0; i < count; i++) {
char *curr = *(symbolTable + i);
if (strcmp(curr, yytext) == 0) {
return i;
}
}
char *lexeme = (char *)malloc(sizeof(char *));
lexeme = (char *)strdup(yytext);
symbolTable[count] = lexeme;
count++;
return (count - 1);
}
How do I remove the warnings?
Neither strdup nor fileno are ISO C functions, they're part of POSIX.
Now whether they're available on your platform depends on your platform.
If you are using the Microsoft tools, you may want to look into _fileno for the latter (fileno was deprecated in VC2005). A rather excellent version of strdup can be found here.
Although, having blown my own horn with that code, you could also use _strdup since it replaces the also-deprecated strdup :-)
These should hopefully work okay as-is since they're in stdio.h and string.h, two of the include files you're already using.
If you're on a UNIX derivative, those functions should be available in stdio.h (for fileno) and string.h (for strdup). Given that it looks like you're already including those files, the problem is likely elsewhere.
One possibility is if you're compiling in one of the strict modes like __STRICT_ANSI__ in gcc), where neither would be defined.
You should have a look at the top of your generated lex.yy.c and lex.l files to confirm that the header files are being included and also check the command line parameters you're passing to the compiler.
I suggest this option (tell the compiler you are using POSIX):
#define _POSIX_C_SOURCE 1
People seem to have tightened up the feature controls in recent years and hopefully when the consistency is good and widespread we can throw away the automake garbage.
I also had this problem while using flex.
I used -std=gnu99rather than -std=c99 which solved the problem.
flex lang.l && gcc -o lexer -std=gnu99 lex.yy.c -lfl
Consider adding the following line:
extern char *strdup(const char *s);
I faced the problem when I compiled with -std=c99 -pedantic -pedantic-errors. Adding the above line solved the problem for me.
You declare the function before you use it:
//declare the function
int storeLexeme();
//use the function here
or include the header where the function is declared.
C implicitly assumes undeclared functions have return type int and deduces the parameters from how you call the function. This is deprecated in C++.
just place your function below the library calls it will be alright;