C: implicit declaration of function ‘getpwnam_r’ - c

While retrieving the broken-out fields of the record in the password database (e.g., the local password file /etc/passwd, NIS, and LDAP) that matches a provided username name, I am using the getpwnam_r (http://linux.die.net/man/3/getpwnam_r) function.
#define __USE_BSD
#define _BSD_SOURCE
#include <pwd.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
int
main(int argc, char *argv[])
{
struct passwd pwd;
struct passwd *result;
char *buf;
size_t bufsize;
int s;
if (argc != 2) {
fprintf(stderr, "Usage: %s username\n", argv[0]);
exit(EXIT_FAILURE);
}
bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
if (bufsize == -1) /* Value was indeterminate */
bufsize = 16384; /* Should be more than enough */
buf = malloc(bufsize);
if (buf == NULL) {
perror("malloc");
exit(EXIT_FAILURE);
}
s = getpwnam_r(argv[1], &pwd, buf, bufsize, &result);
if (result == NULL) {
if (s == 0)
printf("Not found\n");
else {
errno = s;
perror("getpwnam_r");
}
exit(EXIT_FAILURE);
}
printf("Name: %s; UID: %ld\n", pwd.pw_gecos, (long) pwd.pw_uid);
exit(EXIT_SUCCESS);
}
The code works fine, but Eclipse shows me a warning as follows:
warning: implicit declaration of function ‘getpwnam_r’ [-Wimplicit-function-declaration]
How could I fix it?
Note that I'm currently using Ubuntu 14.04 LTS.

To use this function you need two includes :
#include <sys/types.h>
#include <pwd.h>
Add them and it should not complain anymore.
You can see that by running man getpwnam_r.
You also need to define either __USE_MISC or __USE_SVID since it a POSIX only function.

Related

How to pass argument values in the program implementing the shell

SOURCE::
#include <stdio.h> // printf()
#include <stdlib.h> // exit()
#include <string.h> // string
#include <dirent.h> // microsoft base compiler. _chdir, _getcwd
#include <unistd.h> // unix base complier. getcwd, chdir
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#define FILE_SIZE 1024
#define MAX 255
#define ERROR (-1)
void cmd_mkdir(int argc, char *argv);
void cmd_ls()
{
char * cwd = (char *)malloc(sizeof(char) * 1024);
DIR * dir = NULL;
struct dirent * entry = NULL;
getcwd(cwd, 1024);
if( (dir = opendir(cwd)) == NULL)
{
printf("current directory error\n");
exit(1);
}
while( (entry = readdir(dir)) != NULL)
{
printf("%s\n", entry->d_name);
}
free(cwd);
closedir(dir);
}
void cmd_pwd() {
char buf[MAX];
getcwd(buf, MAX);
printf("%s\n", buf);
}
int main(int argc, char *argv[])
{
char cBuf[MAX];
char *arg;
while(1) {
printf(">> ");
arg = fgets(cBuf, MAX, stdin);
if(argc < 2){
// printf("1111\n"); -- check
if(strncmp(arg, "ls", 2) == 0)
cmd_ls();
else if(strncmp(arg, "pwd", 3) == 0)
cmd_pwd();
else if(strncmp(arg, "exit", 4) == 0)
break;
} // if END
else {
// printf("2222\n"); -- check
if(strcmp(arg, "mkdir") == 0){
if (argc != 2)
fprintf(stderr, "Usage : jmkdir dirname\n");
if(mkdir(argv[1], 0755))
perror("mkdir error");
}
}// else END
} // while END
} // main END
Desired result::
How to get two input values (mkdir, mini_maked) as parameters after executing ./minishell (executable file implementing the shell)
$ ./minishell
>> mkdir mini_maked
Currently implemented ls, pwd, exit can be implemented because it can be used without options, but a command that requires a "command filename" such as mkdir is not implemented.
If the program itself functions as mkdir, it is solved using the values of argc and argv.
However, since the ./myshell program itself implements the shell program, when you run the program and receive mkdir mini_maked as an input, you are having a hard time executing the command.
If we get two inputs (mkdir, mini_maked) after program execution, how do we get these as parameters?

Not sure why I am getting an undefine refence to gss_str_to_oid error

I am using gssapi in C for the first time. I am trying to reconstruct example on Oracle doc http://docs.oracle.com/cd/E19683-01/816-1331/sampleprogs-1/index.html.
In my .c file I call gss_str_to_oid(&min_stat, &tok, oid); and get an undefined reference error. I included #include "gssapi.h" at the top of my .c file. In gssapi.h there is a function call
OM_uint32 KRB5_CALLCONV
gss_str_to_oid(
OM_uint32 *, /* minor_status */
gss_buffer_t, /* oid_str */
gss_OID *);
So what am I doing wrong? I thought that if you included #include "gssapi.h" it would give me access to function in gssapi. Both files are in my src folder. So what am I doing wrong. I am using eclipse and from what in my makefile under targets it says all: GSS-API.
I am including most of my code below.
main
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <error.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "gssapi.h"
#include "gssapi_ext.h"
#include "gss-misc.h"
/* global mech oid needed by display status, and acquire cred */
FILE *display_file;
gss_OID g_mechOid = GSS_C_NULL_OID;
void usage()
{
fprintf(stderr, "Usage: gss-client [-port port] [-d]"
" [-mech mechOid] host service msg\n");
exit(1);
}
static void parse_oid(char *mechanism, gss_OID *oid)
{
char *mechstr = 0, *cp;
gss_buffer_desc tok;
OM_uint32 maj_stat, min_stat;
if (isdigit(mechanism[0])) {
mechstr = malloc(strlen(mechanism)+5);
if (!mechstr) {
printf("Couldn't allocate mechanism scratch!\n");
return;
}
sprintf(mechstr, "{ %s }", mechanism);
for (cp = mechstr; *cp; cp++)
if (*cp == '.')
*cp = ' ';
tok.value = mechstr;
} else
tok.value = mechanism;
tok.length = strlen(tok.value);
maj_stat = gss_str_to_oid(&min_stat, &tok, oid);
if (maj_stat != GSS_S_COMPLETE) {
// display_status("str_to_oid", maj_stat, min_stat);
return;
}
if (mechstr)
free(mechstr);
}
int main(argc, argv)
int argc;
char **argv;
{
/* char *service_name, *hostname, *msg; */
char *msg;
char service_name[128];
char hostname[128];
char *mechanism = 0;
u_short port = 4444;
int use_file = 0;
OM_uint32 deleg_flag = 0, min_stat;
display_file = stdout;
/* Parse arguments. */
argc--; argv++;
while (argc) {
if (strcmp(*argv, "-port") == 0) {
argc--; argv++;
if (!argc) usage();
port = atoi(*argv);
} else if (strcmp(*argv, "-mech") == 0) {
argc--; argv++;
if (!argc) usage();
mechanism = *argv;
} else if (strcmp(*argv, "-d") == 0) {
deleg_flag = GSS_C_DELEG_FLAG;
} else if (strcmp(*argv, "-f") == 0) {
use_file = 1;
} else
break;
argc--; argv++;
}
if (argc != 3)
usage();
if (argc > 1) {
strcpy(hostname, argv[0]);
} else if (gethostname(hostname, sizeof(hostname)) == -1) {
perror("gethostname");
exit(1);
}
if (argc > 2) {
strcpy(service_name, argv[1]);
strcat(service_name, "#");
strcat(service_name, hostname);
}
msg = argv[2];
if (mechanism)
parse_oid(mechanism, &g_mechOid);
/* if (call_server(hostname, port, g_mechOid, service_name,
deleg_flag, msg, use_file) < 0)
exit(1);*/
/*
if (g_mechOid != GSS_C_NULL_OID)
(void) gss_release_oid(&min_stat, &gmechOid);
*/
return 0;
}
gssapi.h
/* New for V2 */
OM_uint32 KRB5_CALLCONV
gss_str_to_oid(
OM_uint32 *, /* minor_status */
gss_buffer_t, /* oid_str */
gss_OID *);
You just can't include the header you have to link the library either dynamically or statically. Is there some dll, lib, so, etc you need to add to your project? Without makefile or your project setup been shown in your question; I think you will not receive a very clear answer. Just including header file isn't enough, the undefined is not a compilation error but a linker error, which means its missing a reference because you are not linking the library to your program.
The documentation for GSSAPI in C and C++ in not the greatest. Turns out you need to download gssapi. Here is the link http://www.gnu.org/software/gss/manual/gss.html.
It is under download and install
So, I faced same problem.
I found out that you need to add some .so files to your project.
Just in case check that your system has libkrb5-dev packet (most likely it is already installed if you have gssapi.h).
Required files are stored in folder "/usr/lib/x86_64-linux-gnu/" (debian in my case):
I added libkdb5.so and libgssapi_krb5.so to QT .pro file and all works fine:
LIBS += -lkdb5
LIBS += -lgssapi_krb5
If you need to find that files .so use folloing commands:
apt-file update
dpkg -L libkrb5-dev

mmap error on linux (using somethingelse)

Exactly, I thought that I finished my project until compiling isn't accepted on ubuntu because of mmap(). I'm trying to access(read) files by using fork(). It's okey. But, When I want to count number of read files, entered folder(directories) and child, I powned! How and What can I use or change mmap() because I get error: ‘MAP_ANON’ undeclared (first use in this function)|
. On mac, It's okey but on ubuntu error. Thank you for helps.
#define _XOPEN_SOURCE 700
#define _POSIX_C_SOURCE 200809L
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <dirent.h>
#include <errno.h>
#include <ftw.h>
#include <ctype.h>
#include <sys/mman.h>
#define MAX_PATH_LEN 2048
static int *wordCount = 0;
static int *childCount = 0;
static int *folderCount = 0;
int relatedWord(const char *arr);
int checkWord(const char arr[], int size);
void err_sys(const char *msg);
int disp(const char *filepath, const struct stat *finfo, int flag, struct FTW *ftw);
int main(int argc, char *argv[])
{
//struct stat finfo;
//int count = 0;
wordCount = mmap(NULL, sizeof *wordCount, PROT_READ | PROT_WRITE,MAP_SHARED | MAP_ANON, -1, 0);
childCount = mmap(NULL, sizeof *childCount, PROT_READ | PROT_WRITE,MAP_SHARED | MAP_ANON, -1, 0);
folderCount = mmap(NULL, sizeof *folderCount, PROT_READ | PROT_WRITE,MAP_SHARED | MAP_ANON, -1, 0);
if (argc != 2) {
fprintf(stderr, "Wrong number of arguments!\nUsage: dirwalk6 <path>\n");
exit(EXIT_FAILURE);
}
if (nftw(argv[1], disp, 20, 0) < 0)
err_sys("ntfw");
printf( "\nTotal words = %d\n\n", *wordCount);
printf( "\nTotal folders = %d\n\n", *folderCount);
printf( "\nTotal childs = %d\n\n", *childCount);
return 0;
}
int disp(const char *filepath, const struct stat *finfo, int flag, struct FTW *ftw)
{
int count = 0; /* number of words */
switch (flag) {
case FTW_F: /* determining file */
printf("%*s%s\n", ftw->level * 4, "", filepath);
pid_t pid;
pid=fork();
if(pid < 0)
{
perror("Error corresponding to fork()");
}
else if (pid == 0)
{
count += relatedWord(filepath);
*wordCount += count;
*childCount += 1;
exit(1);
}
else
{
while( pid != wait(0) ) ;
}
// printf( "word = %d, file = %s \n", count,filepath);
break;
case FTW_D: /* determining folder */
printf("%*s%s\n", ftw->level * 4, "", filepath + ftw->base);
*folderCount += 1;
break;
}
return 0;
}
From the man page for mmap(2) (my bold):
Certain flags constants are defined only if either _BSD_SOURCE or _SVID_SOURCE is defined. (Requiring _GNU_SOURCE also suffices, and requiring that macro specifically would have been more logical, since these flags are all Linux specific.) The relevant flags are: MAP_32BIT, MAP_ANONYMOUS (and the synonym MAP_ANON), MAP_DENYWRITE, MAP_EXECUTABLE, MAP_FILE, MAP_GROWSDOWN, MAP_HUGETLB, MAP_LOCKED, MAP_NONBLOCK, MAP_NORESERVE, MAP_POPULATE, and MAP_STACK.
So you will need to define _BSD_SOURCE, _SVID_SOURCE or (if I read that right) _GNU_SOURCE at the top of the file, but in any event prior to
#include <sys/mman.h>
As per #mafso's comment, best to do this prior to any system header include (not least in case an another header itself includes <sys/mman.h>

Root-SUID C wrapper debugging

I am new to C and this is a simple wrapper I wrote to run execute scripts as different user. I understand I can do visudo in etc/sudoers but, I already did this and I don't want it to go to waste, also it will help me improve writing in C. I seem to ha The problem is I am having errors when I compile it. My operating system is Ubuntu 12.04.03 LTS. Can someone help me fix these errors?
rootsuidwrapper.c: In function ‘trusted’:
rootsuidwrapper.c:60:15: warning: assignment makes pointer from integer without a cast [enabled by default]
rootsuidwrapper.c: In function ‘main’:
rootsuidwrapper.c:116:48: error: too many arguments to function ‘stat’
/usr/include/x86_64-linux-gnu/sys/stat.h:211:12: note: declared here
It would be nice if someone could fix these errors and give me the working code. Also, I would like to know what I did wrong.
* This program must be run as root to work.
*/
#if !defined(lint) && !defined(SABER) || defined(RCS_HDRS)
#endif /* !lint && !SABER || RCS_HDRS */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <netdb.h>
#include <sys/stat.h>
#define TRUSTED_GROUP "trusted"
typedef enum { false = 0, true } bool;
#ifdef __STDC__
bool trusted(char *whoami)
#else
bool trusted(whoami)
char *whoami;
#endif /* __STDC__ */
{
char *user;
char host[BUFSIZ + 1];
char domain[BUFSIZ + 1];
struct hostent *hp;
/*
* Figure out whether this user on this host in this domain is
* trusted.
*/
/*
* Determine our domain name
*/
(void) memset(domain, '\0', sizeof(domain));
getdomainname(domain, sizeof(domain) - 1);
/*
* Figure out our fully canonicalized hostname
*/
(void) memset(host, '\0', sizeof(host));
gethostname(host, sizeof(host) - 1);
if ((hp = gethostbyname(host)) == NULL) {
strcat(host, ".");
strcat(host, domain);
fprintf(stderr,
"%s: WARNING: can't canonlicalize hostname; assuming %s.\n",
whoami, host);
}
else {
strcpy(host, hp->h_name);
}
/*
* Get login name of current user
*/
if ((user = cuserid(NULL)) == NULL) {
fprintf(stderr, " %s: You do not seem to be in the passwd file!\n",
whoami);
return(false);
}
/*
* Look this triple up in the trusted netgroup
*/
return ((innetgr(TRUSTED_GROUP, host, user, domain) == 1) ? true : false);
}
#ifdef __STDC__
main(int argc, char *argv[])
#else
main(argc, argv)
int argc;
char *argv[];
#endif /* __STDC__ */
{
char *whoami;
int ouruid; /* uid we set to run chown and chmod */
int proguid; /* uid we are chowning program to */
char *filename;
struct stat statbuf;
int error = 0;
if (whoami = strrchr(argv[0], '/'))
whoami ++;
else
whoami = argv[0];
if (argc == 3)
proguid = atoi(argv[2]);
else if (argc == 2)
proguid = 0;
else {
fprintf(stderr, "usage: %s filename [proguid]\n", whoami);
exit(1);
}
filename = argv[1];
if (trusted(whoami))
ouruid = 0;
else
ouruid = getuid();
if (setuid(ouruid) == -1) {
fprintf(stderr, "%s: Warning: setuid(%d) failed: ", whoami, ouruid);
perror(NULL);
exit(1);
}
if (stat(filename, &statbuf, sizeof(struct stat)) == -1) {
fprintf(stderr, "%s: failure statting %s: ", whoami, filename);
perror(NULL);
exit(1);
}
if (chown(filename, proguid, -1) == -1) {
error++;
fprintf(stderr, "%s: chown %d %s failed: ", whoami, proguid, filename);
perror(NULL);
fprintf(stderr, "continuing...\n");
}
if (chmod(filename, statbuf.st_mode | S_ISUID)) {
error++;
fprintf(stderr, "%s: chmod u+s %s failed: ", whoami, filename);
perror(NULL);
}
return(error);
}
Help is appreciated,
NAME
stat, fstat, lstat - get file status
SYNOPSIS
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int stat(const char *path, struct stat *buf);
int fstat(int filedes, struct stat *buf);
int lstat(const char *path, struct stat *buf);
Remove your third parameter in the call to stat(). Your code should then be:
if (stat(filename, &statbuf) == -1) {
There is no need to tell stat() the size of the buffer because stat() expects a struct stat * which has a fixed size.
For the compiler warning:
cuserid() returns a pointer to a character (char*). When any function returns a pointer, and you want to place the return value into a buffer, then you have to put the return value into a specific place in the buffer, usually the beginning. Specifically, you should use:
*user = cuserid(NULL);
if(user == NULL)
Remember, cuserid() returns a pointer to a single character. Therefore, the return value of the function should go into a single character - that is, *user or user[0]. When the above code is used, the compiler shouldn't complain. Then you place the result of cuserid(NULL) into user, from the first byte to the rest of the memory allocated.

MAC address from interface on OS X (C)

This might be a stupid question and I apologize if it's already been addressed here, but I've searched quite a bit without much luck. I'm trying to get my interface's hardware address in C and I'm using OS X (x86-64). I know how to get it with ifconfig, but I want my program to get it automatically for any computer, well, at least OS X computers. I found another thread that posted this link which pretty much does what I want (with some modifications), but I can't make the iokit functions link in ld (my compiler is gcc). I tried adding the flags -lIOKit and -framework IOKit to the gcc command line, but I still get the same link errors. Here's a link to my code: header and source.
This little program will work without changes on OSX.
Code : (credits to Alecs King from freebsd list)
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/sysctl.h>
#include <net/if.h>
#include <net/if_dl.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int mib[6], len;
char *buf;
unsigned char *ptr;
struct if_msghdr *ifm;
struct sockaddr_dl *sdl;
if (argc != 2) {
fprintf(stderr, "Usage: getmac <interface>\n");
return 1;
}
mib[0] = CTL_NET;
mib[1] = AF_ROUTE;
mib[2] = 0;
mib[3] = AF_LINK;
mib[4] = NET_RT_IFLIST;
if ((mib[5] = if_nametoindex(argv[1])) == 0) {
perror("if_nametoindex error");
exit(2);
}
if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) {
perror("sysctl 1 error");
exit(3);
}
if ((buf = malloc(len)) == NULL) {
perror("malloc error");
exit(4);
}
if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) {
perror("sysctl 2 error");
exit(5);
}
ifm = (struct if_msghdr *)buf;
sdl = (struct sockaddr_dl *)(ifm + 1);
ptr = (unsigned char *)LLADDR(sdl);
printf("%02x:%02x:%02x:%02x:%02x:%02x\n", *ptr, *(ptr+1), *(ptr+2),
*(ptr+3), *(ptr+4), *(ptr+5));
return 0;
}
You should, however, change int len; to size_t len;

Resources