How to reset pointer of getutent() - c

Following is the final code I was working on. I can sleep and show again other messages with sleep() but I can't print what I originally wanted which is inside 2nd while loop. As far as I tested, while((ptr=getutent()) != NULL) would be the problem but I don't know how to solve. I would really appreciate if anyone can help me. Thanks
Note: The program is showing current login user for every 5 seconds until user stop with Ctrl+c.
#include <utmp.h>
#include <pwd.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main(void)
{
struct utmp *ptr;
struct passwd *pwd;
while(1)
{
while((ptr=getutent()) != NULL)
{
if(ptr->ut_type==USER_PROCESS)
{
pwd=getpwnam(ptr->ut_user);
printf("USERNAME = %s | ID = %d | GID = %d | ",p
tr->ut_user,pwd->pw_uid,pwd->pw_gid);
printf("HomeDir = %s | HOST = %s\n",pwd->pw_dir,
ptr->ut_host);
}
}
sleep(3);
fflush(stdout);
}
}

You want to use setutent() to set the file pointer back to the beginning of the utmp file.

Related

How to read all environment variables of a single process using C?

openproc provides API for retrieving data from /proc. But all examples I found read data about all processes. With PROC_FILLENV it should allocate environment variables:
allocate environ part of proc_t and read information from /proc/#pid/environ
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <proc/readproc.h>
int main(){
PROCTAB* proc = openproc(PROC_FILLENV);
proc_t proc_info;
memset(&proc_info, 0, sizeof(proc_info));
while (readproc(proc, &proc_info) != NULL) {
printf("%s\n", *proc_info.environ);
}
closeproc(proc);
}
But it still reads information about all processes. How can I filter processes by PID?
PROC_PID flag and list of PIDs are needed as 2nd argument:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <proc/readproc.h>
// compile with:
// gcc environ.c -lprocps -o bin/environ
int main(){
pid_t* pidList= NULL;
pidList = (pid_t*) malloc(sizeof(pid_t)*2 );
// lookup only processes whose pid is contained in pidlist
pidList[0] = 1234;
pidList[1] = 0; // the list is terminated with 0
PROCTAB* proc = openproc(PROC_PID | PROC_FILLENV, pidList);
proc_t proc_info;
memset(&proc_info, 0, sizeof(proc_info));
while (readproc(proc, &proc_info) != NULL) {
int i = 0;
//environ is an array of *char
while(proc_info.environ[i] != NULL) {
printf("%s\n", proc_info.environ[i++]);
}
}
closeproc(proc);
free(pidList);
}

Print the name of the most recently modified file/directory whose name starts with 0-9 in the current directory

I need to write a simple program that prints the name of the most recently modified file whose name starts with 0-9 in the current directory. So far I can get it to print the name of a file that starts with 0-9, but it fails to consistently print the one that was modified most recently. I have been stuck at this part and I am in very desperate need to figure this out. Any help or hints would be of much help! Thank you!
Below is my code:
#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>
#include <unistd.h>
int main(void){
// Open the current directory
DIR* currDir = opendir("./");
struct dirent *aDir;
time_t lastModifTime;
struct stat dirStat;
int first_file_checked = 0;
char directoryName[256];
// Go through all the entries
while((aDir = readdir(currDir)) != NULL){
// only check on directories with a name that starts with 0-9
if (48 <= (int)aDir->d_name[0] && (int)aDir->d_name[0] <= 57) {
// Get meta-data for the current entry
stat(aDir->d_name, &dirStat);
// Use the difftime function to get the time difference between the current value of lastModifTime and the st_mtime value of the directory entry
if(first_file_checked == 0 || difftime(dirStat.st_mtime, lastModifTime) > 0){
lastModifTime = dirStat.st_mtime;
memset(directoryName, '\0', sizeof(directoryName));
strcpy(directoryName, aDir->d_name);
}
first_file_checked = 1;
}
}
// Close the directory
closedir(currDir);
printf("The last file/directory modified in the current directory is %s\n", directoryName);
return 0;
}
Works here:
BTW: you dont check for directories, you need to add a check for d_type to accomplish that.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>
int main(void){
// Open the current directory
DIR* currDir ;
struct dirent *aDir;
time_t lastModifTime;
struct stat dirStat;
int count ;
char thename[256] = "";
// Go through all the entries
currDir = opendir("./");
for(count=0; (aDir = readdir(currDir)) ; ){
int rc;
// only check on directories with a name that starts with 0-9
if (aDir->d_name[0] < '0' || aDir->d_name[0] > '9' ) continue;
// Get meta-data for the current entry
rc = stat(aDir->d_name, &dirStat);
if (rc < 0) continue; // check the return value!
if(!count++ || dirStat.st_mtime < lastModifTime ){
lastModifTime = dirStat.st_mtime;
strcpy(thename, aDir->d_name);
}
}
// Close the directory
closedir(currDir);
if (count) {
printf("%d files checked. The last file/directory modified in the current directory is %s(time=%u)\n"
, count, thename, (unsigned) lastModifTime);
}
else {
printf("No files/directories were found\n");
}
return 0;
}

c does not follow the program operation procedure

summary : system("clear"); isn't working well.
I'm using gcc, ubuntu 18.04 LTS version for c programming.
what I intended was "read each words and print from two text files. After finish read file, delay 3 seconds and erase terminal"
so I was make two text files, and using system("clear"); to erase terminal.
here is whole code.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
void printFiles(char *file1,char *file2,char *change1, char *change2){
FILE *f;
char *text = malloc(sizeof(char)*100);
f=fopen(file1,"r");
system("clear");
//while(!feof(f)){
while(EOF!=fscanf(f,"%s",text)){
//fscanf(f,"%s", text);
printf("%s ",text);
//usleep(20000);
}
//sleep(3);
fclose(f);
printf("\n");
//all comment problems are appear here. and if I give delay, such as usleep() or sleep, delay also appear here. Not appear each wrote part.
f=fopen(file2,"r");
//while(!feof(f)){
while(EOF!=fscanf(f,"%s",text)){
if(strcmp(text,"**,")==0){
strcpy(text,change1);
strcat(text,",");
}
else if(strcmp(text,"**")==0){
strcpy(text,change1);
}
else if(strcmp(text,"##.")==0){
strcpy(text,change2);
strcat(text,".");
}
else if(strcmp(text,"##,")==0){
strcpy(text,change2);
strcat(text,",");
}
printf("%s ",text);
//usleep(200000);
}
fclose(f);
free(text);
sleep(3); //here is problem. This part works in the above commented part "//all comment problems are appear here."
system("clear"); //here is problem. This part works in the above commented part "//all comment problems are appear here."
}
int main(){
char file1[100] = "./file1.txt";
char file2[100] = "./file2.txt";
char change1[100]="text1";
char change2[100]="text2";
printFiles(file1,file2,change1,change2);
return 0;
}
I'm very sorry, files and variables names are changed because of policy. Also, file contents also can not upload.
I can't find which part makes break Procedure-oriented programming. I think that was compiler error, because using one file read and system(clear); works well.
I also make two point variables, such as 'FILE *f1; FILE *f2; f1=fopen(file1); f2=fopen(file2)...`, but same result occur.
Is it compiler error? If it is, what should I do for fix these problem? Thanks.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
void printFiles(char *file1,char *file2,char *change1, char *change2){
FILE *f;
char *text = malloc(sizeof(char)*100);
f=fopen(file1,"r");
system("clear");
//while(!feof(f)){
while(EOF!=fscanf(f,"%s",text)){
//fscanf(f,"%s", text);
printf("%s ",text);
fflush(stdout);
//usleep(20000);
}
//sleep(3);
fclose(f);
printf("\n");
//all comment problems are appear here. and if I give delay, such as usleep() or sleep, delay also appear here. Not appear each wrote part.
f=fopen(file2,"r");
//while(!feof(f)){
while(EOF!=fscanf(f,"%s",text)){
if(strcmp(text,"**,")==0){
strcpy(text,change1);
strcat(text,",");
}
else if(strcmp(text,"**")==0){
strcpy(text,change1);
}
else if(strcmp(text,"##.")==0){
strcpy(text,change2);
strcat(text,".");
}
else if(strcmp(text,"##,")==0){
strcpy(text,change2);
strcat(text,",");
}
printf("%s ",text);
fflush(stdout);// The answer.
//usleep(200000);
}
fclose(f);
free(text);
sleep(3); //here is problem. This part works in the above commented part "//all comment problems are appear here."
system("clear"); //here is problem. This part works in the above commented part "//all comment problems are appear here."
}
int main(){
char file1[100] = "./file1.txt";
char file2[100] = "./file2.txt";
char change1[100]="text1";
char change2[100]="text2";
printFiles(file1,file2,change1,change2);
return 0;
}
Hint for
That's probably just buffering. Do fflush(stdout); before you sleep. – melpomene
Thanks.
You can try this solution for delay.
#include <time.h>
#include <stdio.h>
void delay(double seconds)
{
const time_t start = time(NULL);
time_t current;
do
{
time(&current);
} while(difftime(current, start) < seconds);
}
int main(void)
{
printf("Just waiting...\n");
delay(3);
printf("...oh man, waiting for so long...\n");
return 0;
}
Following solution is pretty quite the same of previous one but with a clear terminal solution.
#include <time.h>
#include <stdio.h>
#ifdef _WIN32
#define CLEAR_SCREEN system ("cls");
#else
#define CLEAR_SCREEN puts("\x1b[H\x1b[2J");
#endif
void delay(double seconds)
{
const time_t start = time(NULL);
time_t current;
do
{
time(&current);
} while(difftime(current, start) < seconds);
}
int main(void)
{
printf("Just waiting...\n");
delay(2); //seconds
printf("...oh man, waiting for so long...\n");
delay(1);
CLEAR_SCREEN
return 0;
}

Auto-completion visual not good (readline.h)

I would like to add the auto completion on the shell I created. I could not put the entire code but I can tell you my shell is working!
So I tried to implement auto-completion by using the readline function but the result is not that great (see the code in commentary I tried): the auto-completion works but the problems are:
1. I need to press twice enter to get the command executed now. 2. I need to type twice the command (like "ls") to get it executed! Can you help me to fix this? thank you :)
#include <readline/readline.h>
#include <readline/history.h>
#include <stdlib.h>
#include <stdio.h>
#include "includes/ft_sh1.h"
int main(int ac, char **av, char **envp)
{
char *line;
t_env *e = NULL;
char *add;
if (!(e = (t_env *)malloc(sizeof(t_env))))
return (0);
e->envp = env_cpy(envp, 0, 0);
init_env(e);
while (1)
{
--> My question is only about this part below <--
ft_printf("shell$> ");
// add = readline( "shell ");
// add_history(add);
// printf("%s", add);
--> My question is only about this part above <--
get_next_line(0, &line);
get_pwd_env(e);
e->cmd = get_cmd(e, line);
if (ft_strcmp(line, "exit") == 0)
exit(0);
else if (ft_strncmp(e->cmd[0], "cd", 2) == 0)
cd_cmd(e);
else
ft_execute(av, line, e);
}
}
When you just uncomment the part of code in question, you still have the call
get_next_line(0, &line);
in your program, so no wonder that you need to type two command lines.

Getting the error "undefined reference to". Can you explain what it means and where I have made the mistake?

#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <stdio_ext.h>
#include <string.h>
#include <signal.h>
#include <pwd.h>
#include <sys/types.h>
#include <crypt.h>
#include "pwent.h"
#define TRUE 1
#define FALSE 0
#define LENGTH 16
void sighandler() {
signal(SIGINT,SIG_IGN);
}
int main(int argc, char *argv[]) {
mypwent *passwddata;
/* see pwent.h */
char important[LENGTH] = "***IMPORTANT***";
char user[LENGTH];
char prompt[] = "password: ";
char swap_prompt[]="New password: ";
char again_prompt[]="Again: ";
char *user_pass;
char *new_pass;
char *again_pass;
int f_login;
char *en_pass;
char *envp[] = { NULL };
char *argvv[] = { "/bin/sh",NULL};
sighandler();
while (TRUE) {
/* check what important variable contains - do not remove, part of buffer overflow test */
printf("Value of variable 'important' before input of login name: %s\n",
important);
printf("login: ");
fflush(NULL); /* Flush all output buffers */
__fpurge(stdin); /* Purge any data in stdin buffer */
if (fgets(user,16,stdin) == NULL) /* gets() is vulnerable to buffer */
{
exit(0); /* overflow attacks. */
}
*/* check to see if important variable is intact after input of login name - do not remove */*
printf("Value of variable 'important' after input of login name: %*.*s\n",
LENGTH - 1, LENGTH - 1, important);
user_pass = getpass(prompt);
passwddata = mygetpwnam(user);
if (passwddata != NULL) {
en_pass=crypt(user_pass,passwddata->passwd_salt);
if (!strcmp(en_pass, passwddata->passwd)) {
if(passwddata->pwage==10){
printf("You need to swap your password!!! \n");
do{
new_pass=getpass(swap_prompt);
again_pass=getpass(again_prompt);
}while(strcmp(new_pass,again_pass));
printf("Password changed!!! \n");
passwddata->passwd=new_pass;
passwddata->pwage=0;
}else{
printf(" You're in !\n");
printf("Number of failed login is %d\n", passwddata->pwfailed);
passwddata->pwfailed=0;
passwddata->pwage++;
}
mysetpwent(user,passwddata);
setuid(passwddata->uid);
execve("/bin/sh",argvv,envp);
}else{
if(passwddata->pwfailed==3){
printf("You attempted too many times \n");
passwddata->pwfailed=0;
mysetpwent(user,passwddata);
return 0;
}
printf("Wrong password, please try again!!! \n");
f_login++;
passwddata->pwfailed=f_login;
mysetpwent(user,passwddata);
}
}else{
printf("Login Incorrect \n");
}
}
return 0;
}
So I get the error "undefined reference to mygetpwnam" and "undefined reference to mysetpwent". I am not sure what this exactly means and how to go about correcting it. This is a part of an assignment I am working on with regards to unix and their password systems.
You attempt to call the function mygetpwnam once in your code, and mysetpwent three times, yet those functions are not defined anywhere. Hence, you reference something undefined, an error.
"mygetpwnam" and "mysetpwent" are defined in pwd.h. Open and check if pwd.h has definition for "mygetpwnam" and "mysetpwent".
Check pwent.h to see if your functions are declared there (definition should be in pwent.c). Also make sure you haven't misspelled the function names. You should show us how you compile the program.

Resources