C runtime and date command on cygwin - c

Background
$ uname -a
CYGWIN_NT-6.1 Owner-PC 1.7.34(0.285/5/3) 2015-02-04 12:14 x86_64 Cygwin
PS: just updated Cygwin 15 days ago. Should be razor close to current.
$ date --version
date (GNU coreutils) 8.23
Packaged by Cygwin (8.23-4)
Copyright (C) 2014 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Written by David MacKenzie.
Extracted from man date page on cygwin:
%c locale's date and time (e.g., Thu Mar 3 23:05:25 2005)
output from C runtime (dtime is tiny piece of code):
$ ./dtime -f "%c"
Tue Feb 5 17:04:45 2030
Looks good to me...
To avert questions like: what does the code look like:
strcpy(p->fmt, "%c");
....
strftime(tmp, 80, p->fmt, localtime(&lt));
printf("%s\n", tmp);
dtime and other time routines I wrote in the C library behave as expected per standards. No problem.
On the other hand the date command is not correct AFAICT:
Owner#Owner-PC ~
$ date
Sun, Feb 22, 2015 11:41:44 AM
Owner#Owner-PC ~
$ date +%c
Sun, Feb 22, 2015 11:41:55 AM
The second line of output does not match the man page - or standards, I believe.
Question:
A bug? Something else I am missing?
Edit: per suggestion quote the format string. No. That is only need if there are white spaces in the format
Owner#Owner-PC ~
$ date '+%c'
Sun, Feb 22, 2015 3:13:51 PM

This seems related to the locale settings. Your C program uses the C locale by default, date will behave according to the environment variables LANG, LC_TIME and LC_ALL. What are the values of these variables ? Can you test this:
LC_ALL="C" date '+%c'

Related

C program delivers only the UTC time as localtime on Linux using GCC

I have a C program that runs on two different RHEL6 servers that are configured with the same timezone. The C program uses the time functions from time.h. On one of the servers the local time is correctly determined, on the other one the UTC (default) time is displayed independent from the configured timezone.
I've tried to see if the link to /etc/localtime is broken but it's a correct softlink to /usr/share/zoneinfo/<timezone> (in this case Europe/Berlin).
I've inspected the timezone file with zdump and the content of the file is correct. The timezone and time of the system is also correctly displayed using date. There is no definition of the $TZ variable in my bash or anywhere else!
As an additional test I have run the follwing code with and without a $TZ variable:
::time_t aclock;
::tm tm_tmp;
::tm *newtime;
setenv("TZ", "Europe/Berlin", 1);
tzset();
::time( &aclock );
newtime = ::localtime_r( &aclock, &tm_tmp );
printf("\nDEBUG TIME: %d ", aclock);
printf("\nDEBUG TIMEZONE: %s \n", newtime->tm_zone);
printf("DEBUG HOUR: %d \n", newtime->tm_hour);
Using the code above and setting TZ parameter differently I get the following outputs on the faulty server, assuming that the server time is Europe/Berlin, CEST at this moment:
without setenv:
DEBUG TIME: 1524241319
DEBUG TIMEZONE: UTC
DEBUG HOUR: 16
setenv("TZ", "Europe/Berlin", 1);
DEBUG TIME: 1524241319
DEBUG TIMEZONE: Europe
DEBUG HOUR: 16
setenv("TZ", "/etc/localtime", 1);
DEBUG TIME: 1524241319
DEBUG TIMEZONE: CEST
DEBUG HOUR: 18
So it looks like the "Europe/Berlin" time cannot be found, as the UTC time is displayed and the timezone "Europe" is invalid.
As I said the output / behavior on the other machine is the expected one:
without setenv:
DEBUG TIME: 1524241711
DEBUG TIMEZONE: CEST
DEBUG HOUR: 18
setenv("TZ", "Europe/Berlin", 1);
DEBUG TIME: 1524241711
DEBUG TIMEZONE: CEST
DEBUG HOUR: 18
setenv("TZ", "/etc/localtime", 1);
DEBUG TIME: 1524241711
DEBUG TIMEZONE: CEST
DEBUG HOUR: 18
P.S. the same gcc version 4.4.7 is used on both machines.
Is it possible that my timezone database is corrupt on the faulty server? Has someone faced similar problem and solve it?
I finally figured out, that the problem was the libc.so library, which was differently compiled for one of the machines and only used for some C applications excepting linux himself. This explains why date delivers the wright output but the C program not.
Using ldd libc.so I've found out that the linker was also set to be at the path /home/mqm/lib as default, which dosn't fit to my server /home/mqm/lib/lib/ld-linux-x86-64.so.2 => /lib64/ld-linux-x86-64.so.2. To resume, here is the full solution:
Problem: Your Linux system is delivering the wright date and time using date or some applications but wrong output using C programs.
Solution: After ensuring that there is no programming error in your code, check with
strace -e trace=open,close,read,write,connect,accept yourCProgram
which path is used to get the time/timezone. You can also check ldd libc.so to see where the default path of the linker is.
If the paths are not corresponding to your linux system configuration, consider recompiling the C library to fit to your system configuration or set $TZ='fullpathtotimezone' as a hotfix / workaround.

What Unix command-line program prints holidays?

Ages ago, I remember there was a command-line Unix program that
would print out major holidays in the USA. With command-line
options, it could print out Islamic, Discordian, and even Canadian
holidays.
I can't seem to find this program now. The closest I can get is
emacs' "list-holidays" function. It's possible the program I
remember just called an emacs function from the command line or
something.
EDIT: In addition to 'calendar', 'gcal' will do this too.
Are you looking for calendar?
This will show all the upcoming holidays.
$ calendar
Jul 26 Bilbo rescued from Wargs by Eagles
Jul 26 Independence Day in Liberia
Jul 26 National Day in Maldives
This shows all US bank holidays upcoming in the next +1 days.
$ calendar -f /usr/share/calendar/calendar.usholiday -W +1
Nov 11 Veterans' Day
This package is maintained by the BSD community and can be installed in debian and ubuntu from bsdmainutils.

Why would PK11_GenerateRandom() return an error -8023?

I am looking through the Internet trying to find the source of the PK11_GenerateRandom() function to see why would the function fail. I have a program that perfectly uses this function but when we moved to a new flavor of Linux, it fails after forking (fork())
Since I do not believe there is a problem with NSS, I suspect that we are doing something incorrectly which was disregarded in the older versions of Linux but with the new one there is an issue.
The OpenSSL package is the same on the 'good' and the 'bad' server:
OpenSSL 0.9.8e-fips-rhel5 01 Jul
NSS rpm differs though.
The 'good' has
nss-3.12.2.0-2.el5
and the bas has this version
nss-3.15.3-4.el5_10
The 'good' server uses quite obsolete Linux:
Linux GOOD 2.6.18-128.el5 #1 SMP Wed Jan 21 08:45:05 EST 2009 x86_64 x86_64 x86_64 GNU/Linux
Enterprise Linux Enterprise Linux Server release 5.3 (Carthage)
Red Hat Enterprise Linux Server release 5.3 (Tikanga)
The 'bad' server is newer:
Linux BAD 2.6.18-371.4.1.el5 #1 SMP Wed Jan 29 11:05:49 PST 2014 x86_64 x86_64 x86_64 GNU/Linux
Oracle Linux Server release 5.10
Red Hat Enterprise Linux Server release 5.10 (Tikanga)
Any clue as to where could I find the source or what could be the reason for failure (like side effect coming from fork()) would be greatly appreciated.
Greg
Edit
Here is the code, which is so simple, that I did not think it is needed.
/* random points to properly allocated memory, let=32 */
SECStatus rv = PK11_GenerateRandom((unsigned char *)random, (int)len);
if ( rv != SECSuccess )
printf( "PK11_GenerateRandom error = %d\n", PR_GetError()) ;
and the output message is, of course:
PK11_GenerateRandom error = -8023
Greg
The source of the PK11_GenerateRandom() function: http://mxr.mozilla.org/mozilla-central/source/security/nss/lib/pk11wrap/pk11slot.c#2285
Based on my calculation the -8023 corresponds error SEC_ERROR_PKCS11_DEVICE_ERROR
The reason (thanks to jariq's hints) is described here: https://bugzilla.mozilla.org/show_bug.cgi?id=331096
It is that in the past, it was okay to fork and continue using PKCS11 functions. They decided that it cannot be like that, and now, conclusion is that the parent should not initialize these functions if a child after forking is expected to use them.
PKCS11 internal functions are checking if there was forking (they use various methods dependently on what platform the code is built.) For example, they stored pid of the process in an internal memory, and in some expensive functions or called not so often they compare this preserved pid with current getpid().
The fix for our problem will require redesigning the code.

Adding some extra info in uname -v output string in linux kernel

On my Linux machine when i run
uname -v
it gives me
#83-Ubuntu SMP Wed Jan 4 11:12:07 UTC 2012
Now i am building my custom kernel and i need to show some flag/text info about build in this string ..
i want something like
if some config are on then add BUILD-XYZ in that string
#83-Ubuntu SMP Wed Jan 4 11:12:07 UTC 2012 BUILD-XYZ
if not then add BUILD-ABC in that.
#83-Ubuntu SMP Wed Jan 4 11:12:07 UTC 2012 BUILD-ABC
The variable CONFIG_LOCALVERSION (inside your kernel .config file) let you set a custom string that will be appended to the kernel release number, thus shown when using 'uname'.
Is that what you want?
There's a few ways to do this using GNU awk, here's one:
uname -v | awk '{ printf (/some config/) ? $0" BUILD-XYZ\n" : $0" BUILD-ABC\n" }'

Bash parameter expansion and array index operations

The ${parameter,,pattern} parameter expansion converts alphabetic characters in parameter to lower-case.
On cygwin 1.7.11-1 Bash 4.1.10(4) and also on my debian squeeze Bash 4.1.5(1);
if i run the following, i get a curious result:
$ declare -a a=(Zero One Two Three); n=0; echo "${a[n],,}->${n}"; echo "${a[++n]}->${n}"; echo "${a[++n],,}->${n}"
zero->0
One->1
three->3
$
NB: similar results happen:
for ,,* or ^^ case conversion;
for some other expansions such as ${parameter##word};
for using either prefix/postfix ++ or -- operator;
for using $((++n)) instead of just ++n.
However, the length expansion ${#parameter} works as i might expect:
in the above snippet, echo "${#a[++n]}->${n}" instead of echo "${a[++n],,}->${n} would yield 3->2 instead of three->3 ~& the length of a[2]="two" is indeed 3 characters.
I imagine that the parameter expansion is happening twice. But why is this happening?
I grabbed the latest bash source & it appears that this issue is resolved for this version:
$ ./bash --version
GNU bash, version 4.2.24(1)-release (x86_64-unknown-linux-gnu)
Copyright (C) 2011 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
$
Note however that on my Debian Squeeze stable, I have:
$ apt-cache policy bash
bash:
Installed: 4.1-3
Candidate: 4.1-3
Version table:
*** 4.1-3 0
500 http://ftp.uk.debian.org/debian/ squeeze/main amd64 Packages
100 /var/lib/dpkg/status
$
$ bash --version
GNU bash, version 4.1.5(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2009 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
I think this means that currently on Debian Squeeze, the latest stable version of bash is 4.1.5(1) & contains this bug. Also on Cygwin 1.7.11-1 currently the latest available bash package appears to be version 4.1.10(4) & contains this bug. Of course the issue is easy to work around, so no real need to build the 4.2 sources.
I got
Zero->0
One->1
Two->2
However I think "${a[++n]}->${n}" may not be well defined.
try substitute with
let n=$n+1 ; echo "${a[n],,}->${n}";
To inject the notion of sequence.

Resources