I'm using popen to read output from shell commands. I will use fgets to read line by line.
My question is how to choose the best buffer size for my char* buffer? I remember from a professor telling us to include <limits.h> and use LINE_MAX for such things. It works fine on my Mac, but there's no LINE_MAX on Linux.
This mailing list archive poses the same question, but no answer to my question
http://bytes.com/topic/c/answers/843278-not-able-locate-line_max-limits-h
When <limits.h> does not define LINE_MAX, look at _POSIX2_LINE_MAX, which is required to be at least 2048. I usually use 4096.
Also look for the (new) POSIX functions getline() and getdelim() - both at the same URL. These allocate memory as necessary.
Program (posix2_line_max.c)
#include "posixver.h"
#include <limits.h>
#include <stdio.h>
int main(void)
{
printf("%d\n", _POSIX2_LINE_MAX);
return 0;
}
Output:
2048
posixver.h
#ifndef JLSS_ID_POSIXVER_H
#define JLSS_ID_POSIXVER_H
/*
** Include this file before including system headers. By default, with
** C99 support from the compiler, it requests POSIX 2001 support. With
** C89 support only, it requests POSIX 1997 support. Override the
** default behaviour by setting either _XOPEN_SOURCE or _POSIX_C_SOURCE.
*/
/* _XOPEN_SOURCE 700 is loosely equivalent to _POSIX_C_SOURCE 200809L */
/* _XOPEN_SOURCE 600 is loosely equivalent to _POSIX_C_SOURCE 200112L */
/* _XOPEN_SOURCE 500 is loosely equivalent to _POSIX_C_SOURCE 199506L */
#if !defined(_XOPEN_SOURCE) && !defined(_POSIX_C_SOURCE)
#if __STDC_VERSION__ >= 199901L
#define _XOPEN_SOURCE 600 /* SUS v3, POSIX 1003.1 2004 (POSIX 2001 + Corrigenda) */
#else
#define _XOPEN_SOURCE 500 /* SUS v2, POSIX 1003.1 1997 */
#endif /* __STDC_VERSION__ */
#endif /* !_XOPEN_SOURCE && !_POSIX_C_SOURCE */
#endif /* JLSS_ID_POSIXVER_H */
Tested on an Ubuntu 12.04 derivative; command line:
gcc -g -O3 -std=c99 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes -Werror posix2_line_max.c -o posix2_line_max
man getline
Also see http://www.gnu.org/s/libc/manual/html_node/Line-Input.html and the discussion of getline() vs. fgets() vs. gets(). Has been subject on SO more often than I can count as well.
You could use malloc() and expand if necessary, or use the source and look at how a GNU utility does it.
check the line for an '\n', if not exists expand the buffer before you call the next fgets.
POSIX systems have getline which will allocate a buffer for you.
On non-POSIX systems, you can use Chuck B. Falconer's public domain ggets function, which is similar. (Chuck Falconer's website is no longer available, although archive.org has a copy, and I've made my own page for ggets.)
Related
When I try to compile this on Linux with gcc -std=c99, the compiler complains about not knowing struct timespec. However if I compile this without -std=c99 everything works fine.
#include <time.h>
int main(void)
{
struct timespec asdf;
return 0;
}
Why is this and is there a way to still get it to work with -std=c99?
Explicitly enabling POSIX features
The timespec comes from POSIX, so you have to 'enable' POSIX definitions:
#if __STDC_VERSION__ >= 199901L
#define _XOPEN_SOURCE 600
#else
#define _XOPEN_SOURCE 500
#endif /* __STDC_VERSION__ */
#include <time.h>
void blah(struct timespec asdf)
{
}
int main()
{
struct timespec asdf;
return 0;
}
The stanza at the top is what I currently use - it triggers the definitions from Single UNIX Specification (SUS) based on whether you're using a C99 or C89 compiler.
If you want the POSIX 2008 (SUS v4) material, use _XOPEN_SOURCE 700
If you want the POSIX 2004 (SUS v3) material, use _XOPEN_SOURCE 600
If you want the POSIX 1995 (SUS v2, 1997) material, use _XOPEN_SOURCE 500
As noted in the comments, using _XOPEN_SOURCE strictly enables the XSI (X/Open System Interface) extensions over strict POSIX, but it is very rare for you to want POSIX and not XSI. You should normally specify _XOPEN_SOURCE and not futz with _POSIX_C_SOURCE. See (POSIX 2018) on The Compilation Environment for more information about feature macros.
For my systems in 2010, POSIX 2008 was not as widely available as POSIX 2004, so that's what I used - but YMMV. Note that SUS v3 and v4 both require C99 compilation. On Solaris, at least, using C89 failed.
GCC provides -std=gnuXX options
If you specify -std=c11 to GCC (or Clang emulating GCC), then only the standard C definitions are enabled. If you use -std=gnu11, then POSIX and other extensions to standard C are visible by default.
Note that GCC 4.x and earlier used -std=gnu90 (corresponding to C90 plus extensions) by default. GCC 5.x and later use -std=gnu11 by default. There was never a version of GCC that enabled -std=gnu99 by default.
Use a header to control the POSIX version information
I now (2019) use a header to encapsulate this information so that future changes only require the change to a single header, not to every source file that uses POSIX features. It was painful editing the old stanza out of multiple source files as time passed and POSIX 2008 became prevalent.
/*
#(#)File: $RCSfile: posixver.h,v $
#(#)Version: $Revision: 1.4 $
#(#)Last changed: $Date: 2017/06/18 00:15:42 $
#(#)Purpose: Request appropriate POSIX and X/Open Support
#(#)Author: J Leffler
#(#)Copyright: (C) JLSS 2010-2017
*/
/*TABSTOP=4*/
#ifndef JLSS_ID_POSIXVER_H
#define JLSS_ID_POSIXVER_H
/*
** Include this file before including system headers. By default, with
** C99 support from the compiler, it requests POSIX 2008 support. With
** C89 support only, it requests POSIX 1997 support. Override the
** default behaviour by setting either _XOPEN_SOURCE or _POSIX_C_SOURCE.
*/
/* _XOPEN_SOURCE 700 is loosely equivalent to _POSIX_C_SOURCE 200809L */
/* _XOPEN_SOURCE 600 is loosely equivalent to _POSIX_C_SOURCE 200112L */
/* _XOPEN_SOURCE 500 is loosely equivalent to _POSIX_C_SOURCE 199506L */
#if !defined(_XOPEN_SOURCE) && !defined(_POSIX_C_SOURCE)
#if defined(__cplusplus)
#define _XOPEN_SOURCE 700 /* SUS v4, POSIX 1003.1 2008/13 (POSIX 2008/13) */
#elif __STDC_VERSION__ >= 199901L
#define _XOPEN_SOURCE 700 /* SUS v4, POSIX 1003.1 2008/13 (POSIX 2008/13) */
#else
#define _XOPEN_SOURCE 500 /* SUS v2, POSIX 1003.1 1997 */
#endif /* __STDC_VERSION__ */
#endif /* !_XOPEN_SOURCE && !_POSIX_C_SOURCE */
#endif /* JLSS_ID_POSIXVER_H */
You may use the information from this header without the attribution and copyright notice normally required by the "CC by-sa 3.0" licence used by Stack Overflow. This code is available in my SOQ (Stack Overflow Questions) repository on GitHub as file posixver.h in the src/libsoq sub-directory.
C11 defines struct timespec
Note that C11 defines struct timespec, and does so in a way that is compatible with POSIX (which defined it first).
The header <time.h> defines the type. Three of the functions that use it are declared in <threads.h> and the other is in <time.h>:
cnd_timedwait()
mtx_timedlock()
thrd_sleep()
timespec_get()
These are also part of C17 (C18) of course. You would have to be compiling with -std=c11 or similar (GCC 9.2.0 seems to recognize both -std=c17 and -std=c18, and -std=c2x for the next version of the standard) for the type struct timespec to be defined automatically.
I would recommend compiling with -std=gnu99.
To elaborate on this. By default, gcc compiles with -std=gnu89. Here are the results for the following source code.
#include <time.h>
int main() {
struct timespec asdf;
return 0;
}
[1:25pm][wlynch#cardiff /tmp] gcc -std=gnu89 foo.c
[1:26pm][wlynch#cardiff /tmp] gcc -std=gnu99 foo.c
[1:25pm][wlynch#cardiff /tmp] gcc -std=c89 foo.c
foo.c: In function ‘main’:
foo.c:4: error: storage size of ‘asdf’ isn’t known
[1:26pm][wlynch#cardiff /tmp] gcc -std=c99 foo.c
foo.c: In function ‘main’:
foo.c:4: error: storage size of ‘asdf’ isn’t known
Adding -D_GNU_SOURCE to your CFLAGS will also work.
gcc test.c -o test -std=c99 -D_GNU_SOURCE
Have a look at /usr/include/time.h. This is the preprocessor conditional that wraps the timespec definition. _GNU_SOURCE enables __USE_POSIX199309.
#if (!defined __timespec_defined \
&& ((defined _TIME_H \
&& (defined __USE_POSIX199309 \
|| defined __USE_ISOC11)) \
|| defined __need_timespec))
# define __timespec_defined 1
struct timespec
{
__time_t tv_sec; /* Seconds. */
__syscall_slong_t tv_nsec; /* Nanoseconds. */
};
I tried to write a short own traceroute program in C for Linux using raw sockets,
but when I compile I get the error message “dereferencing pointer to incomplete type” struct ip.
These are the headers I include:
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <errno.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <ifaddrs.h>
and then how I use the ip header
struct ip *myIpHeader = (struct ip*)buffr;
followed by a bunch of stuff...then:
myIpHeader->ip_v = 4;
myIpHeader->ip_hl = 5;
myIpHeader->ip_tos = 0;
myIpHeader->ip_len = 20+8;
myIpHeader->ip_off = 0;
myIpHeader->ip_p = IPPROTO_ICMP;
inet_pton(AF_INET, argv[1], &(myIpHeader->ip_dst));
inet_pton(AF_INET, ownip->h_name, &(myIpHeader->ip_src));
myIpHeader->ip_sum = 0;
myIpHeader->ip_id = htonl(12345);
myIpHeader->ip_ttl = ttl;
And then I use it for sending:
sendto(mysock, buffr, sizeof myIpHeader + sizeof myicmphead, 0, (struct sockaddr*)&cliAddr, sizeof cliAddr);
Transferring a comment into an answer.
On a Mac, the header <netinet/ip.h> does contain a struct ip — but that is not a header standardized by POSIX. It's also there in Linux (Ubuntu 16.04). So, it appears that when you do the dereferencing, you don't have the header included, or the contents of the header are 'invisible'.
Are you compiling with -std=gnu11 or -std=c11? If the latter, you probably need to enable POSIX (or GNU) definitions. That's most easily fixed by using -std=gnu11 instead. Alternatively, use -D_GNU_SOURCE or -D_XOPEN_SOURCE=700 or similar on the command line, or the equivalent #define in the source code.
For better or worse, I use a home-brew header posixver.h:
/*
#(#)File: $RCSfile: posixver.h,v $
#(#)Version: $Revision: 1.4 $
#(#)Last changed: $Date: 2017/06/18 00:15:42 $
#(#)Purpose: Request appropriate POSIX and X/Open Support
#(#)Author: J Leffler
#(#)Copyright: (C) JLSS 2010-2017
*/
/*TABSTOP=4*/
#ifndef JLSS_ID_POSIXVER_H
#define JLSS_ID_POSIXVER_H
/*
** Include this file before including system headers. By default, with
** C99 support from the compiler, it requests POSIX 2008 support. With
** C89 support only, it requests POSIX 1997 support. Override the
** default behaviour by setting either _XOPEN_SOURCE or _POSIX_C_SOURCE.
*/
/* _XOPEN_SOURCE 700 is loosely equivalent to _POSIX_C_SOURCE 200809L */
/* _XOPEN_SOURCE 600 is loosely equivalent to _POSIX_C_SOURCE 200112L */
/* _XOPEN_SOURCE 500 is loosely equivalent to _POSIX_C_SOURCE 199506L */
#if !defined(_XOPEN_SOURCE) && !defined(_POSIX_C_SOURCE)
#if defined(__cplusplus)
#define _XOPEN_SOURCE 700 /* SUS v4, POSIX 1003.1 2008/13 (POSIX 2008/13) */
#elif __STDC_VERSION__ >= 199901L
#define _XOPEN_SOURCE 700 /* SUS v4, POSIX 1003.1 2008/13 (POSIX 2008/13) */
#else
#define _XOPEN_SOURCE 500 /* SUS v2, POSIX 1003.1 1997 */
#endif /* __STDC_VERSION__ */
#endif /* !_XOPEN_SOURCE && !_POSIX_C_SOURCE */
#endif /* JLSS_ID_POSIXVER_H */
You may use that if you wish, with or without attribution. You can find a version of the file at https://github.com/jleffler/soq/tree/master/src/libsoq.
When I use --std=c99 GCC defines __STRICT_ANSI__ and when it is on, the BSD and System V features don't kick in. It implies __USE_MISC and __USE_POSIX are left undefined.
-- stdio.h --
...
#if defined __USE_POSIX || defined __USE_MISC
extern int getc_unlocked (FILE *__stream);
extern int getchar_unlocked (void);
#endif /* Use POSIX or MISC. */
...
In the result, functions that I would like to use are omitted. My question is how can I realize I/O operations on standard streams in C99 but without locking ?
Use -std=gnu99 instead of -std=c99 and it will work the way you want.
POSIX actually says that all portable programs should define macro _POSIX_C_SOURCE with version of the Posix standard they want the headers to adher to, prior to including any headers. Thus:
#define _POSIX_C_SOURCE 200809L
#include <stdio.h>
I am trying to use the posix function isatty() in my C code, to tell if the output is being redirected. However, to do this I need a file descriptor, and from my research it looks like fileno() is no longer included with stdio.h. Are there any alternative methods of getting a file descriptor?
It's still there, but you may have to explicitly turn on POSIX features. In particular, under Linux, fileno is only available if POSIX or XOPEN features are enabled. From the fileno(3) manpage:
Feature Test Macro Requirements for glibc (see feature_test_macros(7)):
fileno(): _POSIX_C_SOURCE >= 1 || _XOPEN_SOURCE || _POSIX_SOURCE
So, compile with -D_POSIX_SOURCE.
If you just want to know if output is being redirected, you can use:
#include <unistd.h>
...
if (isatty(STDOUT_FILENO))
error("redirect output.");
STDOUT_FILENO is generally 1.
fileno() is still the POSIX-standard way of getting the file descriptor associated with a file stream.
What compilation options are you using, on which platform(s)? Are you enabling the POSIX extensions?
gcc -std=gnu99 ...
This should make fileno() visible. (Using gcc -std=c99 -pedantic may make them invisible.)
Alternatively, add a variation on this stanza to your code, or put it in a header and include that at the start of your code:
#ifndef JLSS_ID_POSIXVER_H
#define JLSS_ID_POSIXVER_H
/*
** Include this file before including system headers. By default, with
** C99 support from the compiler, it requests POSIX 2001 support. With
** C89 support only, it requests POSIX 1997 support. Override the
** default behaviour by setting either _XOPEN_SOURCE or _POSIX_C_SOURCE.
*/
/* _XOPEN_SOURCE 700 is loosely equivalent to _POSIX_C_SOURCE 200809L */
/* _XOPEN_SOURCE 600 is loosely equivalent to _POSIX_C_SOURCE 200112L */
/* _XOPEN_SOURCE 500 is loosely equivalent to _POSIX_C_SOURCE 199506L */
#if !defined(_XOPEN_SOURCE) && !defined(_POSIX_C_SOURCE)
#if __STDC_VERSION__ >= 199901L
#define _XOPEN_SOURCE 600 /* SUS v3, POSIX 1003.1 2004 (POSIX 2001 + Corrigenda) */
#else
#define _XOPEN_SOURCE 500 /* SUS v2, POSIX 1003.1 1997 */
#endif /* __STDC_VERSION__ */
#endif /* !_XOPEN_SOURCE && !_POSIX_C_SOURCE */
#endif /* JLSS_ID_POSIXVER_H */
For my purposes, _XOPEN_SOURCE set to 600 is better than 700; it works out of the box on more machine types. You may be able to use 700. I keep this in a file posixver.h and my code starts
#include "posixver.h"
before any of the system headers. This allows me to change the rules (600 to 700, for example) centrally and I only need to recompile, not edit every source file.
I started studying POSIX timers, so I started also doing some exercises, but I immediately had some problems with the compiler.
When compiling this code, I get some strange messages about macros like CLOCK_MONOTONIC. Those are defined in various libraries like time.h etc. but the compiler gives me errors as if they are not defined.
It is strange because I am using a Fedora 16, and some of my friends with Ubuntu get less compiler errors than I :-O
I am compiling with gcc -O0 -g3 -Wall -c -fmessage-length=0 -std=c99 -lrt
Here the errors I get:
struct sigevent sigeventStruct gives:
storage size of ‘sigeventStruct’ isn’t known
unused variable ‘sigeventStruct’ [-Wunused-variable]
Type 'sigevent' could not be resolved
unknown type name ‘sigevent’
sigeventStruct.sigev_notify = SIGEV_SIGNAL gives:
‘SIGEV_SIGNAL’ undeclared (first use in this function)
request for member ‘sigev_notify’ in something not a structure or union
Field 'sigev_notify' could not be resolved
if(timer_create(CLOCK_MONOTONIC, sigeventStruct, numero1) == -1) gives:
implicit declaration of function ‘timer_create’ [-Wimplicit-function- declaration]
‘CLOCK_MONOTONIC’ undeclared (first use in this function)
Symbol 'CLOCK_MONOTONIC' could not be resolved
Here is the code:
#include <stdio.h>
#include <fcntl.h>
#include <time.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <signal.h>
int main()
{
timer_t numero1;
struct sigevent sigeventStruct;
sigeventStruct.sigev_notify = SIGEV_SIGNAL;
if(timer_create(CLOCK_MONOTONIC, sigeventStruct, numero1) == -1)
{
printf( "Errore: %s\n", strerror( errno ) );
}
return 0;
}
Firstly, you can compile your code with -std=gnu99 instead of -std=c99 if you want to have the identifiers SIGEV_SIGNAL, sigeventStruct, and CLOCK_MONOTONIC available.
As noted by #adwoodland these identifiers are declared when _POSIX_C_SOURCE is set to a value >= 199309L, which is the case with -std=gnu99. You can also use -D_POSIX_C_SOURCE=199309L -std=c99 or have the macro defined in source code.
Secondly, see the timer_create prototype, you have to pass pointers as the second and the third argument to the function:
timer_create(CLOCK_MONOTONIC, &sigeventStruct, &numero1)
^ ^
Also you have to include the standard header string.h for strerror function declaration.
If you are using -std=c99 you need to tell gcc you're still using recent versions of POSIX:
#define _POSIX_C_SOURCE 199309L
before any #include, or even with -D on the command line.
Other errors:
Missing #include <string.h>
You need a pointer for timer_create, i.e. &sigeventStruct instead of just sigeventStruct
The other answers suggest _POSIX_C_SOURCE as the enabling macro. That certainly works, but it doesn't necessarily enable everything that is in the Single Unix Specification (SUS). For that, you should set _XOPEN_SOURCE, which also automatically sets _POSIX_C_SOURCE. I have a header I call "posixver.h" which contains:
/*
** Include this file before including system headers. By default, with
** C99 support from the compiler, it requests POSIX 2001 support. With
** C89 support only, it requests POSIX 1997 support. Override the
** default behaviour by setting either _XOPEN_SOURCE or _POSIX_C_SOURCE.
*/
/* _XOPEN_SOURCE 700 is loosely equivalent to _POSIX_C_SOURCE 200809L */
/* _XOPEN_SOURCE 600 is loosely equivalent to _POSIX_C_SOURCE 200112L */
/* _XOPEN_SOURCE 500 is loosely equivalent to _POSIX_C_SOURCE 199506L */
#if !defined(_XOPEN_SOURCE) && !defined(_POSIX_C_SOURCE)
#if __STDC_VERSION__ >= 199901L
#define _XOPEN_SOURCE 600 /* SUS v3, POSIX 1003.1 2004 (POSIX 2001 + Corrigenda) */
#else
#define _XOPEN_SOURCE 500 /* SUS v2, POSIX 1003.1 1997 */
#endif /* __STDC_VERSION__ */
#endif /* !_XOPEN_SOURCE && !_POSIX_C_SOURCE */
It is tuned for the systems I work with which don't all recognize the 700 value. If you are working on a relatively modern Linux, I believe you can use 700. It's in a header so that I only have to change one file when I want to alter the rules.
Referring to the CLOCK_MONOTONIC not being defined problem:
As Caterpillar pointed out this is an eclipse bug, more precisely a CDT-Indexer bug with a workaround at eclipse bugs, comment 12
I solved a lot of problems with -std=gnu99 (without specifing any POSIX versions) but I am still having
CLOCK_MONOTONIC could not be resolved
Searching on internet I found some Eclipse bugreports with people complaining about this. Have to check better if is an Eclipse bug, because with
gcc -Wall -w -o Blala timer.c -std=gnu99 -lrt
it compiles