This program I wrote is supposed to restart tor, wait 5 seconds, then look for a PID number using regex.
It compiles and runs fine but the regex logic never displays "good".
I'm confused.

#include <sys/types.h>
#include <regex.h>
#include <stdio.h>
#include <string.h>

// gcc -o tor_restart tor_restart.c
// chown root tor_restart
// chmod +s tor_restart

int main( int argc, char **argv ) {
	regex_t regex;
	int reti;
	FILE *in;
	extern FILE *popen();
	char buff[512];
	
	reti = regcomp(&regex, "[0-9]+", 0);
	if (reti) {
		fprintf(stderr, "Could not compile regex\n");
		return 1;
	}
	setuid(geteuid());
	system("/etc/init.d/tor restart > /dev/null 2>&1");
	
	sleep(5);
	
	if (!(in = popen("pidof tor", "r"))) {
		return 1;
	}
	while (fgets(buff, sizeof(buff), in) != NULL ) {
		//printf("Output: %s", buff);
		if (regexec(&regex, buff, 0, NULL, 0) == 0) {
			puts("good");
		}
	}
		
	regfree(&regex);
	pclose(in);
	return 0;
}

Dani AI

Generated

Good troubleshooting by and the POSIX reminder from . Root cause: regcomp(..., 0) uses POSIX Basic RE syntax, where + is not a repetition metacharacter (you must escape it as \+). Using REG_EXTENDED (or escaping +) makes "[0-9]+" behave as expected. A couple of practical follow-ups that add value beyond the thread’s code:

Use regexec to capture the matched text instead of only testing match/no-match. That lets the program extract the PID string cleanly:

regmatch_t m;
if (regexec(&regex, buff, 1, &m, 0) == 0) {
    int len = (int)(m.rm_eo - m.rm_so);
    char pid[32];
    if (len >= (int)sizeof(pid)) len = sizeof(pid)-1;
    memcpy(pid, buff + m.rm_so, len);
    pid[len] = '\0';
    printf("pid: %s\n", pid);
}

If you don’t need regex at all, tokenizing pidof output is simpler and more robust (handles multiple PIDs):

char *tok = strtok(buff, " \t\n");
while (tok) {
    long pid = strtol(tok, NULL, 10);
    if (pid > 0) printf("found pid %ld\n", pid);
    tok = strtok(NULL, " \t\n");
}

Operational and security notes: SUID binaries that call system()/popen() are risky—paths, shells, and environment can be abused. Prefer a narrowly-scoped sudo rule (NOPASSWD for the specific restart command), a dedicated helper daemon, or use service managers (systemctl) and PID files (e.g., /var/run/tor.pid or pgrep) where available. Also use regerror() after regcomp/regexec to get textual error messages when something fails.

Recommended Answers

All 4 Replies

Which compiler have you used? I can not run this program in Dev c++.
If you tell your compiler's name I can try it.
Thank you.

Which compiler have you used? I can not run this program in Dev c++.
If you tell your compiler's name I can try it.
Thank you.

Actually, the compiler information was provided in the comments at the top of the program: he is using gcc running under a Unix variant, probably either Linux or MacOS. The compiler is the same as used by Dev-C++ (though the one used by Dev-C++ is now woefully out of date); the issue is the operating system it runs under.

This last part is relevant because the program uses the POSIX regular expression library, which would not be present in a default Dev-C++ package. The system requirement is underscored by the fact that it also uses popen() and setuid() , Unix system calls which are not supported under Windows. In other words, this won't compile with any Windows compiler, even a port of the same compiler the OP is using.

Hello Schoil-R-LEA,
Thanks for your reply. I did not know this.

I figured it out.

Here is my code for future reference.
I am using CentOS 6.0 x64

#include <sys/types.h>
#include <regex.h>
#include <stdio.h>
#include <string.h>

// gcc -o tor_restart tor_restart.c
// chown root tor_restart
// chmod +s tor_restart

int main( int argc, char **argv ) {
	regex_t regex;
	int reti;
	FILE *in;
	extern FILE *popen();
	char buff[512];
	
	reti = regcomp(&regex, "[0-9]+", REG_EXTENDED);
	if (reti) {
		fprintf(stderr, "Could not compile regex\n");
		return 1;
	}
	setuid(geteuid());
	system("/etc/init.d/tor restart > /dev/null 2>&1");
	
	sleep(5);
	
	if (!(in = popen("pidof tor", "r"))) {
		return 1;
	}
	while (fgets(buff, sizeof(buff), in) != NULL ) {
		//printf("Output: %s", buff);
		reti = regexec(&regex, buff, 0, NULL, 0);
		if (!reti) {
				puts("good");
		} else {
				puts("bad");
				//printf("Failed to match '%s' with '%s',returning %d.\n",  buff, "[0-9]+", reti);
		}
	}
		
	regfree(&regex);
	pclose(in);
	return 0;
}
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.