I want to set a path environment variable in bash by C program.
So I coded using 'setenv' function, But it was not the answer to solve.
Could anybody suggest another way to solve this problem in C programming?
I thought the other solution that the program read the profile file, then modify and save, but actually when I opened this file there's no string I wanted about PATH variable.
You can use setenv() and putenv() to set environment variables. But these will only be set for the given program. You cannot set environment variables for the shell or its parent process.
Here an example to define the Python path.
It is created a string path and append it to the python path.
char *append_path = malloc(sizeof(char) * 1000);
append_path = "/trunk/software/hmac_sha256/:.";
printf("Append to path is:\n%s\n", append_path);
setenv("PYTHONPATH",append_path,1);//Set PYTHONPATH TO working directory https://www.ibm.com/support/knowledgecenter/en/SSLTBW_2.1.0/com.ibm.zos.v2r1.bpxbd00/setenv.htm
char *path = Py_GetPath();
printf("Python search path is:\n%s\n", path);
This should append the string to the PYTHONPATH environment variable. For me it is working as stated before.
In case the variable is replaced and not appended, then you just need to read the environment variable before, append the new string and then do the "setenv".
for example
//include string functions
#include <string.h>
....
char *current_path = malloc(sizeof(char) * 1000);
current_path = Py_GetPath();
printf("Current search path is:\n%s\n", current_path);
char *new_path = malloc(sizeof(char) * 1000);
new_path = "/trunk/software/hmac_sha256/:.";
printf("New to add path is:\n%s\n", new_path);
snprintf(current_path, sizeof(char) * 1000, "%s%s", current_path,new_path);//this concatenate both strings
setenv("PYTHONPATH",current_path,1);//Set PYTHONPATH TO working directory https://www.ibm.com/support/knowledgecenter/en/SSLTBW_2.1.0/com.ibm.zos.v2r1.bpxbd00/setenv.htm
char *path = Py_GetPath();
printf("Python search path is:\n%s\n", path);
Related
When trying to open a file with fopen(path, "2"); i get NULL on an existing path
iv'e tried to enter only the file name and it works but i want the program to write the file in the path...
Yes, i write the path with double backslashes "\\" when it's necesary.
Yes the path without doubt exists.
FILE* log;
char directory_path[PATH_LEN] = { 0 };
char directory_file[PATH_LEN] = { 0 };
//directory_path is the directory, entered by the user
//LOG_NAME is the files name without the path - "log.txt"
//#define PATH_LEN 100
printf("Folder to scan: ");
fgets(directory_path, PATH_LEN, stdin);
directory_path[strlen(directory_path) - 1] = 0;
//this section connects the path with the file name.
strcpy(directory_file, directory_path);
strcat(directory_file, "\\");
strcat(directory_file, LOG_NAME);
if ((log = fopen(directory_file, "w")) == NULL)
{
printf("Error");
}
My program worked until i tried to write into a file in order to create a log file. This means that the path is correct without doubt.
Can anyone tell me the problem here?
You have several issues in your code:
For one, fopen(path, "2"); is not valid.
The mode argument needs to include one of a, r, and w and can optionally include b or +.
As another thing, directory_path[strlen(directory_path) - 1] = 0; may truncate the end of your path (if it's over PATH_LEN characters long).
There also may be a possible issue with buffer overflow due to the fact that you copy a string to a buffer of the same size and then concatenate two other strings to it. Therefore, you should change this line:
char directory_file[PATH_LEN] = { 0 };
to this:
char directory_file[PATH_LEN+sizeof(LOG_NAME)+1] = { 0 };
To debug this issue, you should print the string entered and ask for confirmation before using it (wrap this in #ifdef DEBUG).
can anyone help me. I'm trying to create a folder, but when I use sprintf, it concatenates at the end special characters like OUUUU, how can I fix it?
there is an image (link below) where you can see the directory variable that has "/home/mia" and the buffer has "mkdir/home/miaOUUUU"
Any suggestions?
i'm using codeblocks in debian...
https://drive.google.com/file/d/1q3KKBbyDjA8_dfwKT54_OT_5QeREIz7k/view?usp=sharing
You should post the code in the body of the question, with copy+paste from your IDE and one extra indentation level (select the code and type Alt-K for that), not as a link to a bitmap, it is very rude.
directorio is not null terminated. You must declare it with one extra element as char directorio[i + 1]; and make sure to initialize directorio[i] to '\0'.
The memset is useless since you overwrite the whole buffer in the subsequent for loop. Do this instead:
char directorio[i + 1];
memcpy(directorio, path, i);
directorio[i] = '\0';
DIRP *dirp = opendir(directorio);
if (dirp == NULL) {
...
} else {
// do not forget to close the directory
closedir(dirp);
}
Also note that you should create directories from the root directory to the final path, and you should handle the spurious case of an existing file with the same name as one of the directories along the path.
I want to delete the folder C:\Users\username\AppData\Roaming\appname when the users uninstall the application appname.
First, I use the following code to get the path C:\Users\username\AppData\Roaming:
TCHAR dir[MAX_PATH];
dir[0] = '\0';
BOOL ok = SHGetSpecialFolderPath(NULL, dir, CSIDL_APPDATA, TRUE);
appname is defined as _T("appname")
The first question is: How to append "appname" to "dir"?
Suppose the above is done. Then I need to use SHFileOperation to delete the non-empty folder C:\Users\username\AppData\Roaming\appname. So I need a double null-terminated string in a SHFILEOPSTRUCT structure. So
How to get a double null-terminated string from the result of the first step? Just append _T("\0\0") to it?
Update: I can use TCHAR *dir2 = lstrcat(dir, appname); to get the path. But when I tried to use TCHAR *dir3 = lstrcat(dir2, _T("\0\0"));, the folder is not deleted. Any number of \0 won't work.
p.s:
If I do the following directly, I got it to work. The problem is that I want to it to be user-independent.
TCHAR path[] = _T("C:\\Users\\username\\AppData\\Roaming\\appname");
memcpy(path + sizeof(path) / sizeof(TCHAR) - 1, _T("\0\0\0"), 3);
For appending paths see PathAppend function.
TCHAR dir[MAX_PATH] = {0};
BOOL ok = SHGetSpecialFolderPath(NULL, dir, CSIDL_APPDATA, TRUE);
PathAppend(dir, _T("appname"));
If you want ensure double null terminating of dir variable:
dir[MAX_PATH - 1] = 0;
dir[MAX_PATH - 2] = 0;
I am working on modifying the didactic OS xv6 (written in c) to support symbolic links (AKA shortcuts).
A symbolic link is a file of type T_SYM that contains a path to it's destination.
For doing that, i wrote a recursive function that gets a path and a buffer and fills the buffer with the "real" path (i.e. if the path contains a link, it should be replaced by the real path, and a link can occur at any level in the path).
Basically, if i have a path a/b/c/d, and a link from f to a/b, the following operations should be equivalent:
cd a/b/c/d
cd f/c/d
Now, the code is written, but the problem that i try to solve is the problem of starting the path with "/" (meaning that the path is absolute and not relative).
Right now, if i run it with a path named /dir1 it treats it like dir1 (relative instead of absolute).
This is the main function, it calls the recursive function.
pathname is the given path, buf will contain the real path.
int readlink(char *pathname, char *buf, size_t bufsize){
char name[DIRSIZ];
char realpathname[100];
memset(realpathname,0,100);
realpathname[0] = '/';
if(get_real_path(pathname, name, realpathname, 0, 0)){
memmove(buf, realpathname, strlen(realpathname));
return strlen(realpathname);
}
return -1;
}
This is the recursive part.
the function returns an inode structure (which represents a file or directory in the system). it builds the real path inside realpath.
ilock an iunlock are being used to use the inode safely.
struct inode* get_real_path(char *path, char *name, char* realpath, int position){
struct inode *ip, *next;
char buf[100];
char newpath[100];
if(*path == '/')
ip = iget(ROOTDEV, ROOTINO);// ip gets the root directory
else
ip = idup(proc->cwd); // ip gets the current working directory
while((path = skipelem(path, name)) != 0){name will get the next directory in the path, path will get the rest of the directories
ilock(ip);
if(ip->type != T_DIR){//if ip is a directory
realpath[position-1] = '\0';
iunlockput(ip);
return 0;
}
if((next = dirlookup(ip, name, 0)) == 0){//next will get the inode of the next directory
realpath[position-1] = '\0';
iunlockput(ip);
return 0;
}
iunlock(ip);
ilock(next);
if (next->type == T_SYM){ //if next is a symbolic link
readi(next, buf, 0, next->size); //buf contains the path inside the symbolic link (which is a path)
buf[next->size] = 0;
iunlockput(next);
next = get_real_path(buf, name, newpath, 0);//call it recursively (might still be a symbolic link)
if(next == 0){
realpath[position-1] = '\0';
iput(ip);
return 0;
}
name = newpath;
position = 0;
}
else
iunlock(next);
memmove(realpath + position, name, strlen(name));
position += strlen(name);
realpath[position++]='/';
realpath[position] = '\0';
iput(ip);
ip = next;
}
realpath[position-1] = '\0';
return ip;
}
I have tried many ways to do it right but with no success. If anyone sees the problem, i'd be happy to hear the solution.
Thanks,
Eyal
I think it's clear that after running get_real_path(pathname, name, realpathname, 0, 0) the realpathname cannot possibly start with a slash.
Provided the function executes successfully, the memmove(realpath + position, name, strlen(name)) ensures that realpath starts with name, as the position variable always contains zero at the first invocation of memmove.
I'd suggest something like
if(*path == '/') {
ip = iget(ROOTDEV, ROOTINO); // ip gets the root
realpath[position++] = '/';
} else
ip = idup(proc->cwd); // ip gets the current working directory
P.S. I'm not sure why you put a slash into the realpathname before executing the get_real_path, since at this point you don't really know whether the path provided is an absolute one.
Ok, found the problem...
The problem was deeper than what i thought...
Somehow the realpath was changed sometimes with no visible reason... but the reason was the line:
name = newpath;
the solution was to change that line to
strcpy(name,newpath);
the previous line made a binding between the name and the realpath... which can be ok if we were not dealing with softlinks. When dereferencing a subpath, this binding ruined everything.
Thanks for the attempts
I just started working with C & Xcode and I've run into a little difficulty.
All I want to do is read a file from the command line and see the output in the terminal.
I think my problem lies with the path to the file that I want to read in. I'm using a Mac and the file is on my desktop, so the path should be Users/myName/Desktop/words.txt. Is this correct?
This is my code:
#import <Foundation/Foundation.h>
int main (int argc, const char* argv[]){
if(argc == 1){
NSLog(#" you must pass at least one arguement");
return 1;
}
NSLog(#"russ");
FILE* wordFile = fopen(argv[1] , "r");
char word[100];
while (fgets(word,100,wordFile)) {
NSLog(#" %s is %d chars long", word,strlen(word));
}
fclose(wordFile);
return 0;
}//main
If you need the path to a file in OS X, an easy way to get it is to just drag the file into the Terminal.app window where you are typing the command. Voila!
The path to the desktop is /Users/[username]/Desktop/
~/Desktop/ is a user-agnostic way of denoting this, ~ represents the current users home directory. It must be expanded using a method like stringByExpandingTildeInPath
Not sure about using C# (I've never used it on Mac OS X), but in Objective-C/Cocoa, you would do..
// Get array with first index being path to desktop
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDesktopDirectory, NSUserDomainMask, YES);
// Get the first element
NSString *desktopPath = [paths objectAtIndex:0];
// Append words.txt to path
NSString *theFilePath = [desktopPath stringByAppendingPathComponent:#"words.txt"];
NSLog(#"%#", theFilePath);
This is the most robust way of getting the Desktop path, as a user could technically move their Desktop folder else where (although this is pretty unlikely). Another valid option is to use the NSString method stringByExpandingTildeInPath:
NSString *desktop = [#"~/Desktop" stringByExpandingTildeInPath];
NSString *theFile = [desktop stringByAppendingPathComponent:#"words.txt"]
As I said, both those are in Objective-C, but it shouldn't be hard to translate to C#, assuming you can get at the Cocoa libraries.
The code you posted works correctly:
dbr:.../build/Debug $ ./yourcode ~/Desktop/words.txt
yourcode[2106:903] russ
yourcode[2106:903] this is words.txt is 17 chars long
Your terminal automatically expands the ~/ tilda path
Close... it's
/{Volume}/Users/myName/Desktop/words.txt
... where {Volume} is the name of your hard drive. You can also try using:
~/Desktop/words.txt
... where ~ is understood to mean "your home directory", but this might not resolve correctly.
(Note - this appears to be a C question, not a C# question)
Actually, you can do:
/Users/myName/Desktop/words.txt
You don't have to give the path to the volume.
However, to get the full path in C you'd do something like:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
char *home, *fullPath;
home = getenv("HOME");
fullPath = strcat(home, "/Desktop/words.txt");
The issue you're running into with passing the filename as an argument is that you need to set the current working directory to the place where the file exists.