How to read all environment variables of a single process using C? - 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);
}

Related

How to create a thread, make it wait for input and then finally have it execute it's function

I have program and I want it to create a thread, thread 'a', I want it to wait for input from a file to be read into a buffer, buffer 1, then execute its function and put the answer to that question in a second buffer, buffer 2. At the moment the thread waits but it never executes and I can't figure out why. Could it be that the parent thread is exiting before thread 'a' has a chance to execute? If this is the case how do I stop the parent thread from exiting? If it is not the case could I have some pointers on what I am doing wrong
The code is below.
EDIT: This is a homework assignment and it has to be done in this manner as opposed to reading in the input first or having the thread read the input.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include "LinkedList.h"
#include "macros.h"
#include "FileReading.h"
pthread_mutex_t lock;
pthread_cond_t cond;
int returnSeekTime(int curData, int nextData)
{
int seekTime;
if (curData > nextData)
{
seekTime = curData - nextData;
}
else
{
seekTime = nextData - curData;
}
return seekTime;
}
void* firstComeFirstServed(void* data)
{
Buffers* buffers = (Buffers*)data;
Buffer1 buffer1 = buffers->buffer1;
Buffer2 buffer2 = buffers->buffer2;
int curData, nextData;
Node* current = current = buffer1.disks->head;
pthread_cond_wait(&cond, &lock);
buffer2.seekTime += returnSeekTime(buffer1.secondDisk, current->data);
while(current != NULL && current != buffer1.disks->tail)
{
curData = current->data;
nextData = current->next->data;
buffer2.seekTime += returnSeekTime(curData, nextData);
current = current->next;
}
return NULL;
}
int main (void)
{
char fileName[11] = "input.txt\0";
pthread_t a;
Buffers* buffers = (Buffers*)malloc(sizeof(Buffers));
buffers->buffer1.disks = createLinkedList();
pthread_create(&a, NULL, firstComeFirstServed, (void*)buffers);
readInputFile(fileName, &buffers->buffer1);
pthread_cond_signal(&cond);
pthread_mutex_unlock(&lock);
return 0;
}

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;
}

fuse parsing custom arguments in C

Using libfuse in my c-project, I 'm trying to add custom command-line arguments and handle them.
Here is an example on which I rely
https://github.com/libfuse/libfuse/wiki/Option-Parsing
First, I tried to do the argument for the mount point configuration -с <pathtoconfig>
I tried many ways to describe an option like -c --config conf= -o conf=, but ineffectually
Please, help me find the right path to solve the problem :(
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <fuse.h>
#include "fuu_walk.h"
#include "jsmnload.h"
#define _JSMN_TOKEN_SIZE_ 256
#define _JSMN_BUFFER_SIZE_ 4096
#define MYFS_OPT(t, p, v) { t, offsetof(struct myfs_config, p), v }
struct myfs_config {
char *mystring;
} conf;
static struct fuse_opt myfs_opts[] = {
MYFS_OPT("-c %s", mystring, 1),
FUSE_OPT_END
};
jsmntok_t t[_JSMN_TOKEN_SIZE_];
char buf[_JSMN_BUFFER_SIZE_];
#if 0
= ""
"{\"root\": ["
"{\"path\":\"/\", \"mode\":\"drw-------\"},"
"{\"path\":\"/12ABC345DE67\", \"mode\":\"drw-------\"},"
"{\"path\":\"/12ABC345DE67/_XQ01\", \"mode\":\"-rw-------\"},"
"{\"path\":\"/12ABC345DE67/_XQ02\", \"mode\":\"-rw-------\"},"
"{\"path\":\"/12ABC345DE78\", \"mode\":\"drw-------\"},"
"{\"path\":\"/12ABC345DE89\", \"mode\":\"drw-------\"}"
"]}";
#endif
static int myfs_opt_proc(void *data, const char *arg, int key, struct fuse_args *outargs)
{
struct myfs_config *ptr = (struct myfs_config *)data;
FILE *conf;
int rc = 0;
//I wanna check the argument on the each iteration of fuse_opt_parse. It's just the debug printf
printf("arg = %s\t string %s\t key = %i\n", arg, ptr->mystring, key);
switch (key) {
case 1:
conf = fopen(ptr->mystring, "r");
rc = read(fileno(conf), buf, _JSMN_BUFFER_SIZE_);
if ( jsmnload(buf, t, _JSMN_TOKEN_SIZE_, fuu_mkfstree) < 0 ) {
printf("Error load configuration\n");
exit(-1);
}
}
return 1;
}
int main(int argc, char *argv[])
{
struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
memset(&conf, 0, sizeof(conf));
fuse_opt_parse(&args, &conf, myfs_opts, myfs_opt_proc);
return fuu_main(args.argc, args.argv);
}
Launch example
./appendix/fuu /mnt/cdrom/ -c /mnt/fs.json
As a result, printf in myfs_opt_proc function works only once and outputs
arg = /mnt/cdrom/ string (null) key = -2
Why myfs_opt_proc does not work for option -c?
I cannot comment so as an answer... looking at the reference you provided it seems to me that there is no option starting with -c. So result seems correct because fuse cannot parse this. Look at this snippet from your link:
fuse_opt_add_arg(&args, "-omodules=subdir,subdir=/foo");
You may try to announce options to fuse using -o.
Edit: Youre example differs from the linked one, try to add to following line to the defined struct:
FUSE_OPT_KEY("-c", "KEY_CONFIG");
and some line before
emum {
KEY_CONFIG
};
and parse it like this in youre myfs_opt_proc function
switch (key) {
case KEY_CONFIG:
/* ... */
. Summed up you missed declaring the -c key.

creating multiple recursive directories in c

I am completing cs50x (the edX (free) version of the Harvard cs50) course and am trying to be a bit tricky/lazy/test myself.
I am trying to use a C program to create all the directories I will need for my psets.
I have looked online and found that <sys/stat.h> includes the mkdir() function and therefore tried creating some nested loops to create all the necessary folders by doing something similar to mkdir {pset1,pset1/{standard,hacker},pset2,pset2{standard... to give me a directory structure like this:
pset1/Standard
pset1/Hacker
pset2/Standard
etc...
I came up with this:
#include <cs50.h>
#include <stdio.h>
#include <sys/stat.h>
int main(int argc, string argv[])
{
for(int i = 1; i <=8; i++)
{
string dir = argv[1];
sprintf(dir,"%s%i", argv[1], i);
mkdir(dir, 0777);
for(int j = 0; j<2; j++)
{
string subDir[] = {"Standard","Hacker"};
sprintf(dir,"%s%i/%s", argv[1], i, subDir[j]);
mkdir(dir, 0777);
}
}
}
However, the program only creates pset1 and completes, there are no subfolders, no pset2 etc.
Yes, you're being lazy since you seem to have very little knowledge of C, yet try to program in it. :)
C is not Python, there is no string interpolation/formatting operator. You have to call a function, specificially snprintf(). Read that manual page.
Also, you can't create a bunch of nested directories with a single call to mkdir(). Read the manual page.
To create nested directories, you're either going to have to build each's absolute path (i.e. each successive time you call mkdir() the path will be longer than the previous time), or actually enter each directory as you create it, and go from there.
To create a full path you can call mkdir() recursivly like this:
#include <limits.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
int mkdirr(const char * path, const mode_t mode, const int fail_on_exist)
{
int result = 0;
char * dir = NULL;
do
{
if (NULL == path)
{
errno = EINVAL;
result = -1;
break;
}
if ((dir = strrchr(path, '/')))
{
*dir = '\0';
result = mkdirr(path, mode, fail_on_exist);
*dir = '/';
if (result)
{
break;
}
}
if (strlen(path))
{
if ((result = mkdir(path, mode)))
{
char s[PATH_MAX];
sprintf(s, "mkdir() failed for '%s'", path);
perror(s);
if ((EEXIST == result) && (0 == fail_on_exist))
{
result = 0;
}
else
{
break;
}
}
}
} while (0);
return result;
}
And then call mkdirr() like this;
int main(void)
{
char p[] = "test/1/2/3";
if (-1 == mkdirr(p, 0777, 0))
{
perror("mkdirr() failed()");
}
return 0;
}

How to reset pointer of getutent()

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.

Resources