use a shell script to update version - linux

#include "calcmarks.h"
// calcmarks, version 1, released Thu Mar 23 13:16:49 WST 2017
int main(int argc, char *argv[])
{
int nmarks = 0;
if(argc == 1) {
nmarks += readmarks(stdin);
Don't care what this code is, what I want is a shellscript to update and version.After do the shellscript,the comment above will become
// calcmarks, version 2, released (time you execute the script)
Tried to do below which didn't work.
a=$(date)
sed -i "_bak" s'/Thu Mar 23 13:16:49 WST 2017/$a/g' "calcmarks.c"

Here is a list of commands that will perform the trick.
Nota : If you are using a different -version-numbering system (2.1, 2.1.1, etc), you'll need to change it slightly.
prev_version=$(sed -n '\%.*// calcmarks, version %!d;s///;s/ .*//p' "$file")
new_version=$((prev_version+1))
curr_date=$(date "+%a %b %d %H:%M:%S %Z %Y")
sed -i -e "s#\(// calcmarks, version \)${prev_version}.*#\1${new_version}, released ${curr_date}#g" "$file"

Related

Unable to apply patch with nested directories

I am trying to create simple patch but file is in different directory.
My Directory structure is:
/-|hello_new.c
|-1/-|
|-2/-|
|-3/hello.c
//hello_new.c:
#include <stdio.h>
int main(int argc, char *argv[]) {
printf("Hello World\n");
}
//hello.c:
#include <stdio.h>
int main()
{
printf("Hello World\n");
}
I create the patch using:
diff -u 1/2/3/hello.c hello_new.c > hello.patch
My patch file is hello.patch:
--- 1/2/3/hello.c 2016-02-09 13:31:04.904763020 +0530
+++ hello_new.c 2016-02-08 18:35:47.299940190 +0530
## -1,6 +1,5 ##
#include <stdio.h>
-int main()
-{
+int main(int argc, char *argv[]) {
printf("Hello World\n");
}
Now I apply patch using:
patch < hello.patch
But I get patching file hello_new.c
Reversed patch detected.
You would solve this using the -p option of patch:
-p number
--strip=number
Set the file name strip count to number. See patch Directories.
If the before/after levels in your patch-file differ, keep in mind that patch gives precedence to the number of levels in the before part (the first line of the header). So you could do
patch -p3 < hello.patch
to avoid the reversed-patch issue for this instance.
This being GNU patch, you can preview the result by adding the --dry-run option (to avoid the nuisance of giving correct responses to the reversed-patch message):
$ patch -p3 --dry-run < hello.patch
patching file hello.c
Hunk #1 succeeded at 2 with fuzz 2 (offset 1 line).
When testing patches, e.g., if they did not match exactly (such as tab/space conversion, carriage-return line-endings), I preview patches, and may add a -l option to help patch make fewer rejects.

The method parse_datetime from Perl's DateTime::Format::Strptime can't parse timezone name

I have a laptop with ubuntu 12.04.
The execution of date command at the console result this:
$ date
Thu May 8 15:28:12 WIB 2014
The perl script below will be running well.
#!/usr/bin/perl
use DateTime::Format::Strptime;
$parser = DateTime::Format::Strptime->new( pattern => "%a %b %d %H:%M:%S %Y %Z");
$date = "Fri Sep 20 08:22:42 2013 WIB";
$dateimap = $parser->parse_datetime($date);
$date = $dateimap->strftime("%d-%b-%Y %H:%M:%S %z");
print "$date\n";
$date = "Fri Jan 8 16:49:34 2010 WIT";
$dateimap = $parser->parse_datetime($date);
$date = $dateimap->strftime("%d-%b-%Y %H:%M:%S %z");
print "$date\n";
The result is
20-Sep-2013 08:22:42 +0700
08-Jan-2010 16:49:34 +0900
But, why the timezone name "WIT" is converted to timezone "+0900" ?
AFAIK, WIT is Western Indonesian Time. IMHO it should has timezone "+0700" not "+0900".
The other computer has a running CentOS 5.9.
The execution of date command at the CentOS result:
$ date
Thu May 8 15:38:24 WIT 2014
But the execution of the perl script above result like this:
20-Sep-2013 08:22:42 +0700
Can't call method "strftime" on an undefined value at strptime.pl line 14.
Actually the method parse_datetime can't parse the date which contain "WIT" timezone.
The returned value $dateimap is empty or undef.
The CentOS have been set to localtime Asia/Jakarta.
$ ls -l /etc/localtime
lrwxrwxrwx 1 root root 32 Sep 23 2013 /etc/localtime -> /usr/share/zoneinfo/Asia/Jakarta
Any suggestion ?
Thank you.
Actually the problem happens because the version of module DateTime::Format::Strptime at CentOS 5.9 is 1.2000 while at ubuntu 12.04 is 1.54.
Another problem using the older version of DateTime::Format::Strptime.
$ perl -e '
> use DateTime::Format::Strptime;
> $parser = DateTime::Format::Strptime->new( pattern => "%a %b %d %H:%M:%S %Y");
> $datembox = "Wed Jan 1 06:42:18 2014 WIT";
> $date = $parser->parse_datetime($datembox);
> print "$date\n";'
$
If we remove double spaces at variable $datembox.
$ perl -e '
> use DateTime::Format::Strptime;
> $parser = DateTime::Format::Strptime->new( pattern => "%a %b %d %H:%M:%S %Y");
> $datembox = "Wed Jan 1 06:42:18 2014 WIT";
> $datembox =~ s/[\s]+/ /g;
> $date = $parser->parse_datetime($datembox);
> print "$date\n";'
2014-01-01T06:42:18
$

Random errors when using rexec

I have a very odd error when using rexec. The code is very simple, I am just calling rexec in a loop:
#include <stdio.h>
#include <errno.h>
#include <netdb.h>
int main() {
char buffData[1024];
int i;
ssize_t j;
char * l_ahost = "cwp01";
struct servent * l_servInfo = getservbyname("exec", "tcp");
for (i = 0; i < 2000; i++) {
int err = rexec(&l_ahost, l_servInfo->s_port, NULL, NULL, "echo -n .", NULL);
if (err <= 0) {
perror("Rexec error");
} else {
if (read(err, buffData, 1024) > 0) printf ("'%c' %d\n", *buffData, i);
close(err);
}
}
return 0;
}
The output is:
muftak : > gcc tst_rexec.c ; ./a.out
'.' 0
'.' 1
'.' 2
'.' 3
'.' 4
...
'.' 47
'.' 48
'.' 49
cwp01.eurocontrol.fr: Connection reset by peer
Rexec error: Illegal seek
'.' 51
'.' 52
'.' 53
'.' 54
...
Why does rexec work correctly almost always, but not always ? Non determinist behaviour for such a simple case disturbs me a lot. I have no clue of where to search an explanation for this (except stackoverflow, of course).
I am using Red Hat Enterprise Linux Server release 5.8 (Tikanga)
i don't know that much about TCP and even less about rexec. have you tried the command version yet. your code suggests you could use the rexec (1) as opposed to rexec (3).
good luck.
First, you should read the man page for rexec to know why you must not use it.
Second, "non determinist behaviour" is quite common in network programming (and it is a big difference with local programming and a reason why fully distributed systems, where you do not even know that code is run remotely, is very hard to achieve). From the error message, it looks like the server cwp01.eurocontrol.fr simply rebooted during your test.

is there a way to turn off "A append-to-register?

from :help "A
"Vim fills these registers only when you say so. Specify them as lowercase
letters to replace their previous contents or as uppercase letters to append
to their previous contents"
Is there a way to turn this off?
it's super annoying: when I hold down shift to type double quote " to append to a register, its pretty often the case I hold the shift for a split second too long and input "A instead of "a (so it appends to register a instead of replacing it altogether)
If you wish to implement what #romainl has suggested it can be done in a six lines (three if you don’t mind having magic numbers, leaving unneeded variables and remapping in operator-pending mode):
let s:capshift=char2nr('A')-char2nr('a')
for s:ch in range(char2nr('A'), char2nr('B'))
execute 'nnoremap "'.nr2char(s:ch).' "'.nr2char(s:ch-s:capshift)
execute 'vnoremap "'.nr2char(s:ch).' "'.nr2char(s:ch-s:capshift)
endfor
unlet s:capshift s:ch
. But this solution has a drawback: you now loose ability to wait indefinitely between pressing " and A (unless you want to set notimeout which has problems on its own).
i ended up writing a small patch which adds a "registerappend" option
...with this you can:set noregisterappend to disable it!
diff -r 4cb1f10316ca -r aedf9e836670 src/ops.c
--- a/src/ops.c Thu Oct 11 04:44:33 2012 +0200
+++ b/src/ops.c Tue Oct 16 01:28:47 2012 -0700
## -894,7 +894,8 ## get_yank_register(regname, writing)
else if (ASCII_ISUPPER(i))
{
i = CharOrdUp(i) + 10;
- y_append = TRUE;
+ if(p_regappend)
+ y_append = TRUE;
}
else if (regname == '-')
i = DELETION_REGISTER;
diff -r 4cb1f10316ca -r aedf9e836670 src/option.c
--- a/src/option.c Thu Oct 11 04:44:33 2012 +0200
+++ b/src/option.c Tue Oct 16 01:28:47 2012 -0700
## -2068,6 +2068,9 ## static struct vimoption
(char_u *)NULL, PV_NONE,
#endif
{(char_u *)2000L, (char_u *)0L} SCRIPTID_INIT},
+ {"registerappend", NULL, P_BOOL,
+ (char_u *)&p_regappend, PV_NONE,
+ {(char_u *)TRUE, (char_u *)TRUE} SCRIPTID_INIT},
{"relativenumber", "rnu", P_BOOL|P_VI_DEF|P_RWIN,
(char_u *)VAR_WIN, PV_RNU,
{(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT},
diff -r 4cb1f10316ca -r aedf9e836670 src/option.h
--- a/src/option.h Thu Oct 11 04:44:33 2012 +0200
+++ b/src/option.h Tue Oct 16 01:28:47 2012 -0700
## -495,6 +495,7 ## EXTERN char_u *p_popt; /* 'printoptions'
EXTERN char_u *p_header; /* 'printheader' */
#endif
EXTERN int p_prompt; /* 'prompt' */
+EXTERN int p_regappend; /* 'registerappend' */
#ifdef FEAT_GUI
EXTERN char_u *p_guifont; /* 'guifont' */
# ifdef FEAT_XFONTSET

What is the maximum size of a Linux environment variable value?

Is there a limit to the amount of data that can be stored in an environment variable on Linux, and if so: what is it?
For Windows, I've found following KB article which summarizes to:
Windows XP or later: 8191 characters
Windows 2000/NT 4.0: 2047 characters
I don't think there is a per-environment variable limit on Linux. The total size of all the environment variables put together is limited at execve() time. See "Limits on size of arguments and environment" here for more information.
A process may use setenv() or putenv() to grow the environment beyond the initial space allocated by exec.
Here's a quick and dirty program that creates a 256 MB environment variable.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main(void)
{
size_t size = 1 << 28; /* 256 MB */
char *var;
var = malloc(size);
if (var == NULL) {
perror("malloc");
return 1;
}
memset(var, 'X', size);
var[size - 1] = '\0';
var[0] = 'A';
var[1] = '=';
if (putenv(var) != 0) {
perror("putenv");
return 1;
}
/* Demonstrate E2BIG failure explained by paxdiablo */
execl("/bin/true", "true", (char *)NULL);
perror("execl");
printf("A=%s\n", getenv("A"));
return 0;
}
Well, it's at least 4M on my box. At that point, I got bored and wandered off. Hopefully the terminal output will be finished before I'm back at work on Monday :-)
export b1=A
export b2=$b1$b1
export b4=$b2$b2
export b8=$b4$b4
export b16=$b8$b8
export b32=$b16$b16
export b64=$b32$b32
export b128=$b64$b64
export b256=$b128$b128
export b512=$b256$b256
export b1k=$b512$b512
export b2k=$b1k$b1k
export b4k=$b2k$b2k
export b8k=$b4k$b4k
export b16k=$b8k$b8k
export b32k=$b16k$b16k
export b64k=$b32k$b32k
export b128k=$b64k$b64k
export b256k=$b128k$b128k
export b512k=$b256k$b256k
export b1m=$b512k$b512k
export b2m=$b1m$b1m
export b4m=$b2m$b2m
echo $b4m
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
: : : : : : : : : : : :
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
If you're worried that 4M may not be enough for your environment variable, you may want to rethink how you're doing things.
Perhaps it would be a better idea to put the information into a file and then use an environment variable to reference that file. I've seen cases where, if the variable is of the form #/path/to/any/fspec, it gets the actual information from the file path/to/any/fspec. If it doesn't begin with #, it uses the value of the environment variable itself.
Interestingly enough, with all those variables set, every single command starts complaining that the argument list is too long so, even though it lets you set them, it may not be able to start programs after you've done it (since it has to pass the environment to those programs).
Here are two helpful commands:
getconf -a | grep ARG_MAX
true | xargs --show-limits
I did a quick test on my Linux box with the following snippet:
a="1"
while true
do
a=$a$a
echo "$(date) $(numfmt --to=iec-i --suffix=B --padding=7 ${#a})"
done
On my box (Gentoo 3.17.8-gentoo-r1) this results in (last lines of output):
Wed Jan 3 12:16:10 CET 2018 16MiB
Wed Jan 3 12:16:11 CET 2018 32MiB
Wed Jan 3 12:16:12 CET 2018 64MiB
Wed Jan 3 12:16:15 CET 2018 128MiB
Wed Jan 3 12:16:21 CET 2018 256MiB
Wed Jan 3 12:16:33 CET 2018 512MiB
xrealloc: cannot allocate 18446744071562068096 bytes
So: the limit is quite high!
Don't know exactly but a quick experiment shows that no error occurs e.g. with 64kB of value:
% perl -e 'print "#include <stdlib.h>\nint main() { return setenv(\"FOO\", \"", "x"x65536, "\", 1); }\n";'\
| gcc -x c -o envtest - && ./envtest && echo $?
0
I used this very quick and dirty php code (below), modifying it for different values, and found that it works for variable lengths up to 128k. After that, for whatever reason, it doesn't work; no exception is raised, no error is reported, but the value does not show up in the subshell.
Maybe this is a php-specific limit? Maybe there are php.ini settings that might affect it? Or maybe there's a limit on the size of vars that a subshell will inherit? Maybe there are relevant kernel or shell config settings..
Anyway, by default, in CentOS, the limit for setting a var in the environment via putenv in php seems to be about 128k.
<?php
$s = 'abcdefghijklmnop';
$s2 = "";
for ($i = 0; $i < 8100; $i++) $s2 .= $s;
$result = putenv('FOO='.$s2);
print shell_exec('echo \'FOO: \'${FOO}');
print "length of s2: ".strlen($s2)."\n";
print "result = $result\n";
?>
Version info -
[root#localhost scratch]# php --version
PHP 5.2.6 (cli) (built: Dec 2 2008 16:32:08)
<..snip..>
[root#localhost scratch]# uname -a
Linux localhost.localdomain 2.6.18-128.2.1.el5 #1 SMP Tue Jul 14 06:36:37 EDT 2009 x86_64 x86_64 x86_64 GNU/Linux
[root#localhost scratch]# cat /etc/redhat-release
CentOS release 5.3 (Final)
The command line (with all argument) plus the environment variable should be less then 128k.
In my case it was due to buffer was limited when accepting a variable input value with read command. Solution was to add -e
Before read accessToken
After read -e accessToken
Docs: http://linuxcommand.org/lc3_man_pages/readh.html

Resources