![]() |
|
|||||||
| Programming C, bash, Python, Perl, PHP, Java, you name it. |
![]() |
|
|
Thread Tools | Display Modes |
|
|||
|
I working on a file that invokes <sys/stat>. I've gotten a lot I needed but for the life of me I can't figure where:
Code:
struct stat sb; Here is the file in question: Code:
#include "wifimgr.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <pwd.h>
#include <sys/stat.h>
#ifndef WITHOUT_NLS
#include <libintl.h>
#else
#define gettext(x) (x)
#endif
#define PATH "/bin:/usr/bin:/sbin:/usr/sbin"
main(int argc, char ** argv) {
char line[1024];
char cmd[1024];
int auth = 0;
int copy_stdout;
char * arg;
int xst;
#ifndef WITHOUT_NLS
/* set output character set */
bind_textdomain_codeset("wifimgr", "UTF-8");
/* set language catalog domain */
textdomain("wifimgr");
#endif
if (isatty(0) || isatty(1)) {
fprintf(stderr, gettext("wifimgrsu: for invocation by wifimgr(8) only\n"));
exit(1);
}
/* set line buffering */
setvbuf(stdin, (char *) NULL, _IOLBF, 0);
setvbuf(stdout, (char *) NULL, _IOLBF, 0);
/* set safe PATH (required for shell scripts such as /etc/rc.d/netif) */
setenv("PATH", PATH, 1);
/* loop reading commands */
while (fgets(line, sizeof(line), stdin) != NULL) {
chop(line);
if (strncmp(line, "password ", 9) == 0) {
char * pass;
char * su_pass;
pass = strdup(index(line, ' ') + 1);
su_pass = strdup(getpwnam("root")->pw_passwd);
if (strcmp(crypt(pass, su_pass), su_pass) != 0)
printf("FAIL %s\n", gettext("invalid password"));
else {
auth = 1;
printf("OK\n");
}
continue;
}
/* go no further unless authorization passed */
if (!auth) {
printf("FAIL %s\n", gettext("not authorized"));
continue;
}
/* flag for commands that produce stdout */
copy_stdout = 0;
if (strcmp(line, "cat_netfile") == 0) {
if (stat(file, &sb) >= 0)
sprintf(cmd, "%s %s", PATH_CAT, NETWORKS_FILE);
else
sprintf(cmd, "");
copy_stdout = 1;
}
else if (strncmp(line, "write_netfile ", 14) == 0) {
arg = index(line, ' ') + 1;
sprintf(cmd, "%s %s %s", PATH_CP, arg, NETWORKS_FILE);
}
else if (strcmp(line, "diff_netfile") == 0)
sprintf(cmd, "%s -q %s %s.save >/dev/null", PATH_DIFF, NETWORKS_FILE, NETWORKS_FILE);
else if (strcmp(line, "backup_netfile") == 0)
sprintf(cmd, "%s -p %s %s.save", PATH_CP, NETWORKS_FILE, NETWORKS_FILE);
else if (strncmp(line, "restart_netif ", 14) == 0) {
arg = index(line, ' ') + 1;
sprintf(cmd, "%s restart %s >/dev/null 2>&1", PATH_NETIF, arg);
}
else if (strncmp(line, "start_netif ", 12) == 0) {
arg = index(line, ' ') + 1;
sprintf(cmd, "%s start %s >/dev/null 2>&1", PATH_NETIF, arg);
}
else if (strncmp(line, "stop_netif ", 11) == 0) {
arg = index(line, ' ') + 1;
sprintf(cmd, "%s stop %s >/dev/null 2>&1", PATH_NETIF, arg);
}
else {
printf("FAIL %s\n", gettext("invalid command"));
continue;
}
xst = system(cmd);
if (copy_stdout)
printf("EOF\n");
if (WEXITSTATUS(xst) == 0)
printf("OK\n");
else
printf("FAIL %s %d\n", gettext("exit status"), WEXITSTATUS(xst));
}
}
|
|
|||
|
They can be declared at the start of a block too, though whether that style is acceptable depends on who you're coding with. I like it as a C++ programmer -- the principle being that the smaller the visibility of the variable the simpler the analysis of program when reading it over for errors -- but it doesn't seem like a principle many C programmers agree with. For instance, the OpenBSD style man page has this to say:
" Parts of a for loop may be left empty. Don't put declarations inside blocks unless the routine is unusually complicated." |
|
|||
|
Oh and if you can use C99 the variable definitions can be intermixed with the statements like in C++, so if you wanted to you could wait to define it until the last possible place. But in the program above the last possible place is the same as the beginning of the if block enclosing the stat call, so there's no difference.
|
|
|||
|
One more thing. This code is rife with potential null pointer references and buffer overflows from trusting its input and assuming functions (e.g. index) don't fail and using error prone functions like sprintf.
Say, it wouldn't happen to come from the source code of PHP would it? |
|
||||
|
It might be there but I sincerely hope it isn't. As far as I know, the only variable that should be declared/defined in a header is a constant and, in his case, it's not a constant and it shouldn't be global, not even file static, unless he wants to create some sort of global buffer.
__________________
A daemon in need is a daemon indeed. Last edited by classicmanpro; 30th March 2011 at 07:10 PM. Reason: Made my reply more explicit |
|
|||
|
Yeah, I think it being defined in the header or declared in the header and defined in some other module can be ruled out. The code isn't good, but it's not that out there.
|
|
|||
|
Quote:
Code:
if (some_other_predicate(...)) {
struct stat sb;
if (stat(fname, &sb) == -1)
handle the error.
else
act on file or directory or whatever thing is.
maybe sb has something in it you want to look at, hmm.
}
else ...
|
![]() |
| Thread Tools | |
| Display Modes | |
|
|