Let's say I have this code for my apache module:
#include <iostream>
#include <string>
#include <httpd.h>
#include <http_core.h>
#include <http_protocol.h>
#include <http_request.h>
#include <apr_strings.h>
int count = 0;
static void my_child_init(apr_pool_t *p, server_rec *s)
{
count = 1000; //starts up with this number!
}
static int my_handler(request_rec *r)
{
count++; //Increments here
ap_rputs(std::to_string(count).c_str(), r);
return OK;
}
static void register_hooks(apr_pool_t *pool)
{
ap_hook_child_init(my_child_init, NULL, NULL, APR_HOOK_MIDDLE);
ap_hook_handler(my_handler, NULL, NULL, APR_HOOK_LAST);
}
module AP_MODULE_DECLARE_DATA myserver_module =
{
STANDARD20_MODULE_STUFF,
NULL, // Per-directory configuration handler
NULL, // Merge handler for per-directory configurations
NULL, // Per-server configuration handler
NULL, // Merge handler for per-server configurations
NULL, // Any directives we may have for httpd
register_hooks // Our hook registering function
};
Now if I open my browser and go to localhost/my_server I see my count incrementing every time I refresh my page, creating a new HTTP request to Apache.
1001 //from connection 1
1002 //from connection 1
1003 //from connection 1
1004 //from connection 1
...
I was expecting that everytime I refresh, I see the count incrementing. But sometimes I see that apache probably created another connection and the module is instantiated again.. and I have now two equal connections running:
1151 //from connection 1
1152 //from connection 1
1001 // from connection 2
1153 //from connection 1
1002 // from connection 2
1003 // from connection 2
1154 //from connection 1
...
Is there anyway I prevent apache reloading the same module?
Most Apache MPM / common configurations will create multiple child processes. You can configure them to use a single process with many threads instead, or use shared memory for your counter.
The simplest way to use shared memory in a portable way is to depend on the "slotmem" and "slotmem_shm" modules. mod_proxy_balancer uses this. An alternate way is to how server/scoreboard.c uses shared memory directly.
On Mac OS X, using C and/or C++, I want to change the creation time of a file to an arbitrary date/time. I have found a number of solutions, notably this StackOverflow answer, that allow to set the creation time to an older date, but this is not sufficient for me - I also want to be able to set a newer date. Using the utimes() function therefore is not the solution I am looking for.
I know that setting a newer creation time must be possible somehow, because the SetFile utility from Apple's developer command line tools can do it, but so far my search-fu has failed to uncover any hints that bring me closer to a solution.
Does anyone know of a way how I can achieve my goal?
Why do I want to do this myself, why can't I use SetFile?
The SetFile command line utility is deprecated (see man SetFile), so it's bound to go away some time in the future
I want to create a utility that allows me to specify a time delta to add to/subtract from the current creation time. The SetFile utility does not have any convenient command line arguments to do this.
Last but not least: Curiosity!
Haven't tried it, but according to the docs, the NSURL resource value under the key NSURLCreationDateKey is read-write. Since you specified C or C++, you'd use the corresponding CFURL API. So, you'd call:
CFURLRef url = /* ... */
CFDateRef date = /* ... */
CFErrorRef error;
if (!CFURLSetResourcePropertyForKey(url, kCFURLCreationDateKey, date, &error))
/* handle error */;
EDIT: A minimal example
const char* fileName = "/path/to/file";
size_t fileNameStringLength = strlen(fileName);
Boolean isDirectory = false;
CFURLRef url = CFURLCreateFromFileSystemRepresentation(
kCFAllocatorDefault,
(const UInt8*)fileName,
fileNameStringLength,
isDirectory);
// Seconds since 1 January, 2001 00:00:00 GMT
CFAbsoluteTime absTime = CFAbsoluteTimeGetCurrent();
CFAbsoluteTime adjustedCreationTime = absTime - 3600;
CFDateRef date = CFDateCreate(
kCFAllocatorDefault,
adjustedCreationTime);
CFErrorRef error;
if (!CFURLSetResourcePropertyForKey(url, kCFURLCreationDateKey, date, &error))
{
fprintf(stderr, "an error occurred\n");
exit(1);
}
CFRelease(url);
CFRelease(date);
BTW, I have no idea if this is safe, secure, whatever. So, do this at your own risk.
On OS X, you can sort of do this by setting the time of the day to the future and then copying the file (and renaming it back). It is not the same file with its creation time modified; it is a copy with the creation time you set.
Some code (I got the code to set the time of the day from here):
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <copyfile.h>
#include <unistd.h>
int main(int argc, char *argv[]) {
struct timeval tv_now, tv_set;
copyfile_state_t s;
struct stat st;
// retrieve original stat
if (stat(argv[2], &st) < 0)
perror("stat");
// get current time of day
if (gettimeofday(&tv_now, 0) == -1)
perror("gettimeofday");
// set time of day to +argv[1] days
tv_set = tv_now;
tv_set.tv_sec += 86400 * atoi(argv[1]);
if (settimeofday(&tv_set, 0) == -1)
perror("settimeofday to future");
// copy the file to a temporary, copy everythig except stat
s = copyfile_state_alloc();
if (copyfile(argv[2], ".eighty_eight_miles_per_hour", s, COPYFILE_ACL | COPYFILE_XATTR | COPYFILE_DATA) < 0)
perror("copy file");
copyfile_state_free(s);
// rename it back to original name
if (rename(".eighty_eight_miles_per_hour", argv[2]) < 0)
perror("rename file");
// restore file owner, group, and mode
if (chown(argv[2], st.st_uid, st.st_gid) < 0)
perror("chown");
if (chmod(argv[2], st.st_mode) < 0)
perror("chmod");
// reset current time of day
if (settimeofday(&tv_now, 0) == -1)
perror("settimeofday back to now");
return 0;
}
I call this program the flux_capacitor. The first command line argument is the number of days forward to set the file's creation date, and the second argument is the file name. You have to run this program as root to set the time.
Observe, as I send the delorean forward in time by 2 days.
[ronin:~/Documents/CPP] aichao% touch delorean
[ronin:~/Documents/CPP] aichao% ls -l delorean
-rw-r--r-- 1 aichao staff 0 Aug 10 11:43 delorean
[ronin:~/Documents/CPP] aichao% su
Password:
sh-3.2# ./flux_capacitor 2 delorean
sh-3.2# exit
exit
[ronin:~/Documents/CPP] aichao% ls -l delorean
-rw-r--r-- 1 aichao staff 0 Aug 12 2016 delorean
[ronin:~/Documents/CPP] aichao% date
Wed Aug 10 11:43:47 EDT 2016
and in the Finder:
Note that I only restore the original owner, group, and mode from the stat for the file. I don't think you can or want to do more than that, but I don't know. Obviously, links to the file will be broken.
I have multithread applications. In one thread I want to waiting for data, and if this datas will not appear through some time, I just close whole application. Function select() is runs in another thread and thread is detach
A piece sorce some class
#define STDIN 0
A::A(){
runFunction1();
runFunction2();
thread listen(&A::isData , this);
listen.detach();
}
// and function with select
void A::isData{
struct timeval tv;
fd_set readfds;
tv.tv_sec = 50; // wait to 50 seconds
tv.tv_usec = 500000;
FD_ZERO(&readfds);
FD_SET(STDIN, &readfds);
for(;;) {
select(STDIN+1, &readfds, NULL, NULL, &tv);
if (FD_ISSET(STDIN, &readfds)){
cout << "I something catch :)" << endl;
// reset time
}else{
cout << "I nothing catch ! By By :(" << endl;
exit(1);
break;
}
}
}
If my program run then I get pid, so I have tryed write to file descriptor some datas in below way:
$ cd /proc/somePID/fd
$ echo 1 >> 0
Then I should be get info I something catch :) but in console IDE I only get 1 , however if time is out I get I nothing catch ! By By :( to console in IDE.
EDIT: SOLVED
#Vladimir Kunschikov gave me correct tip. Basic on this I show how I do it in C/C++
It will be posible send something to process using command echo we must create pipe. Pipe using function
A::A(){
fd[2]; //two file descriptor for pipes write/read
pipe(fd); // c function to create pipes
runFunction1();
runFunction2();
thread listen(&A::isData , this);
listen.detach();
}
Then in our proces will create other two new file descriptor as below:
lrwx------ 1 user user 64 gru 15 14:02 0 -> /dev/pts/0
lrwx------ 1 user user 64 gru 15 14:02 1 -> /dev/pts/0
lrwx------ 1 user user 64 gru 15 14:02 2 -> /dev/pts/1
lr-x------ 1 user user 64 gru 15 14:02 3 -> pipe:[1335197]
lrwx------ 1 user user 64 gru 15 14:02 4 -> socket:[1340788]
l-wx------ 1 user user 64 gru 15 14:02 5 -> pipe:[1335197]
pipe:[1335197] is descriptor to read in this proces. Now command echo will be works if we will write some to descriptor 3. Using is simply:
$ cd /proc/PID/fd
$ echo 1 > 3
Then we also can using this in select() function but descriptor number is 3 so define should be looks like .
#define STDIN 3
And works
You have wrong assumption that writing to the /proc/pidof application/fd/0 will put data to the stdin stream of the application.
Just read answers to this question: Sending command to java -jar using stdin via /proc/{pid}/fd/0
I need to perform an action every day after September 5. I wrote this program
#include <windows.h>
int main()
{
SYSTEMTIME time;
GetLocalTime(&time);
if((time.wMonth = 9 && time.wDay >= 6) || time.wMonth > 9)
{
//perform action
MessageBox(GetForegroundWindow(), "Action performed. Month is " + std::to_string((long long)wMonth), "Alarm!", MB_OK | MB_SYSTEMMODAL);
}
}
I ran this program and the message box displays. But today is August 22, I checked my computer's clock. What am I doing wrong?
Reference SYSTEMTIME
Update:
After writing this question I checked the values of wMonth and wDay and these are 1 and 22, i.e. Jan 22.
Seems like a bug. What do I do to get correct month?
if((time.wMonth = 9 ... needs to be :
if((time.wMonth == 9 ...
^^^^
If you reverse your test (and many C++ programmers do), the compiler will emit an error :
if((9 = time.wMonth ... // error !
Which is a way of catching this frequent typo.
I think is better to use the cron manager (Linux) or Task Manager (Windows) to schedule your job
If I call setuid in a loop to become root and reset the uid, this works only once.
I have the following code:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int my_func(int i) {
int current_uid = getuid();
int ret;
fprintf(stderr,
"### i=%d ###: My UID is: %d. My GID is: %d, before 'system(id)'\n",
i, current_uid, getgid());
system("/usr/bin/id");
fprintf(stderr,"\n\n### i=%d ###: before 'setuid(0)'\n", i);
if (setuid(0)) {
perror("setuid");
return 1;
}
fprintf(stderr,"after 'setuid(0)'\n\n");
//I am now root!
fprintf(stderr,
"### i=%d ###: I an now root: My UID is: %d. My GID is: %d, before 'system(id)'\n",
i, getuid(), getgid());
system("/usr/bin/id");
//Time to drop back to regular user priviledges
fprintf(stderr,"\n\nbefore 'setuid(%d)'\n",current_uid);
ret=setuid(current_uid);
fprintf(stderr,
"### i=%d ###: My UID is: %d. My GID is: %d, before 'system(id)\n",
i, getuid(), getgid());
system("/usr/bin/id");
}
int main(void) {
int i;
for (i=0;i<3;i++) {
my_func(i);
sleep(5);
fprintf(stderr,"\n\n");
}
return 0;
}
I set the SUID bit and run this program as ordinary user rose. The output is:
rose#condor:/home/rose/Txt/src/Test/C/Setuid(5)$ ll /usr/local/bin/multiple_setuid_test
-rws--x--x 1 root root 13589 11. Dez 08:41 /usr/local/bin/multiple_setuid_test*
rose#condor:/home/rose/Txt/src/Test/C/Setuid(6)$ /usr/local/bin/multiple_setuid_test
i=0 ###: My UID is: 1203. My GID is: 100, before 'system(id)'
uid=1203(rose) gid=100(users) Gruppen=100(users),4(adm),6(disk),7(lp),10(wheel),14(uucp),18(audio),19(cdrom),27(video),35(games),60(mysql),250(portage),1001(haldaemon),1002(plugdev),1008(scanner),1027(vboxusers),1028(kvm),1029(qemu),1036(gsm),1039(pulse-access),1040(pulse),1041(tuntap)
i=0 ###: before 'setuid(0)'
after 'setuid(0)'
i=0 ###: I an now root: My UID is: 0. My GID is: 100, before 'system(id)'
uid=0(root) gid=100(users) Gruppen=0(root),4(adm),6(disk),7(lp),10(wheel),14(uucp),18(audio),19(cdrom),27(video),35(games),60(mysql),100(users),250(portage),1001(haldaemon),1002(plugdev),1008(scanner),1027(vboxusers),1028(kvm),1029(qemu),1036(gsm),1039(pulse-access),1040(pulse),1041(tuntap)
before 'setuid(1203)'
i=0 ###: My UID is: 1203. My GID is: 100, before 'system(id)
uid=1203(rose) gid=100(users) Gruppen=100(users),4(adm),6(disk),7(lp),10(wheel),14(uucp),18(audio),19(cdrom),27(video),35(games),60(mysql),250(portage),1001(haldaemon),1002(plugdev),1008(scanner),1027(vboxusers),1028(kvm),1029(qemu),1036(gsm),1039(pulse-access),1040(pulse),1041(tuntap)
i=1 ###: My UID is: 1203. My GID is: 100, before 'system(id)'
uid=1203(rose) gid=100(users) Gruppen=100(users),4(adm),6(disk),7(lp),10(wheel),14(uucp),18(audio),19(cdrom),27(video),35(games),60(mysql),250(portage),1001(haldaemon),1002(plugdev),1008(scanner),1027(vboxusers),1028(kvm),1029(qemu),1036(gsm),1039(pulse-access),1040(pulse),1041(tuntap)
i=1 ###: before 'setuid(0)'
setuid: Operation not permitted
i=2 ###: My UID is: 1203. My GID is: 100, before 'system(id)'
uid=1203(rose) gid=100(users) Gruppen=100(users),4(adm),6(disk),7(lp),10(wheel),14(uucp),18(audio),19(cdrom),27(video),35(games),60(mysql),250(portage),1001(haldaemon),1002(plugdev),1008(scanner),1027(vboxusers),1028(kvm),1029(qemu),1036(gsm),1039(pulse-access),1040(pulse),1041(tuntap)
i=2 ###: before 'setuid(0)'
setuid: Operation not permitted
rose#condor:/home/rose/Txt/src/Test/C/Setuid(7)$ uname -a
Linux condor 3.12.4 #1 SMP Mon Dec 9 11:37:38 CET 2013 x86_64 Intel(R) Core(TM)2 CPU 6600 # 2.40GHz GenuineIntel GNU/Linux
Any hint is appreciated.
Linux (just like other unixes) store two values: your real user id, which is set by setuid, corresponds to your login, and is not changed by the s-bit, and your effective user id, which is set by seteuid, and gets changed when you execute a program that has the s-bit set. To be allowed to use setuid(), either your real or your effective user id need to be zero, but if you use setuid() to drop privileges (change from 0 to anything else), your effective user id will be changed as well. So your first setuid(1203) sets the effective user id to 1203 as well, which prevents you from regaining privileges later.
To change from and to root several times, you have to use the setreuid() call to swap both - setreuid(1203, 0) would change your real user id to 1203, and the effective user id to 0, thus allowing you to set the uid to 0 later.
Note that, as long as either of the two uids is 0, you have root privileges. With uid=1203 and euid=0, files you create will belong to you (user id 1203), but you'll still have root access. So check your program for security implications very carefully.
If you need to have root access every now and then throughout your program, it's much safer to create a pipe(), fork() off a child process that keeps root privileges, drop privileges in the parent process, and send some command down the pipe for the child to execute when you need something done as root. That way, you have to security audit only the child process, which is presumably much smaller than your whole program.
Once you give up root privileges by using setuid to change to a non-root user, you no longer have the privileges necessary to use setuid to become root once again.