I am trying to add as option in the command $ printenv the command date . e.g. if you try to run $ printenv -d it should return the date output.
I have the src code from the link ftp://ftp.ntua.gr/pub/gnu/coreutils/coreutils-8.23.tar.xz that contains all the coreutils in a linux distribution.
I have already change the source code of src/printenv.c (this file is in the coreutils.tar file). But what is my next move ?
I can not compile it with gcc printenv.c
Compile error: fatal error: config.h: No such file or directory
compilation terminated.
Should I make the makefiles/configs etc and install it manually? How?
I post my changed code (printenv.c)
/* printenv -- print all or part of environment
Copyright (C) 1989-2014 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* Usage: printenv [variable...]
If no arguments are given, print the entire environment.
If one or more variable names are given, print the value of
each one that is set, and nothing for ones that are not set.
Exit status:
0 if all variables specified were found
1 if not
2 if some other error occurred
David MacKenzie and Richard Mlynarik */
#include <config.h>
#include <stdio.h>
#include <sys/types.h>
#include <getopt.h>
#include "system.h"
/* Exit status for syntax errors, etc. */
enum { PRINTENV_FAILURE = 2 };
/* The official name of this program (e.g., no 'g' prefix). */
#define PROGRAM_NAME "printenv"
#define AUTHORS \
proper_name ("David MacKenzie"), \
proper_name ("Richard Mlynarik")
static struct option const longopts[] =
{
{"null", no_argument, NULL, '0'},
{"date", required_argument, NULL, 'd'},
{GETOPT_HELP_OPTION_DECL},
{GETOPT_VERSION_OPTION_DECL},
{NULL, 0, NULL, 0}
};
/* Forward declarations. */
static void dateMachine (void);
void
usage (int status)
{
if (status != EXIT_SUCCESS)
emit_try_help ();
else
{
printf (_("\
Usage: %s [OPTION]... [VARIABLE]...\n\
Print the values of the specified environment VARIABLE(s).\n\
If no VARIABLE is specified, print name and value pairs for them all.\n\
\n\
"),
program_name);
fputs (_("\
-0, --null end each output line with NUL, not newline\n\
"), stdout);
fputs (HELP_OPTION_DESCRIPTION, stdout);
fputs (VERSION_OPTION_DESCRIPTION, stdout);
printf (USAGE_BUILTIN_WARNING, PROGRAM_NAME);
emit_ancillary_info ();
}
exit (status);
}
int
main (int argc, char **argv)
{
char **env;
char *ep, *ap;
int i;
bool ok;
int optc;
bool opt_nul_terminate_output = false;
initialize_main (&argc, &argv);
set_program_name (argv[0]);
setlocale (LC_ALL, "");
bindtextdomain (PACKAGE, LOCALEDIR);
textdomain (PACKAGE);
initialize_exit_failure (PRINTENV_FAILURE);
atexit (close_stdout);
while ((optc = getopt_long (argc, argv, "+iu:0d", longopts, NULL)) != -1)
{
switch (optc)
{
case '0':
opt_nul_terminate_output = true;
break;
case 'd':
dateMachine ();
break;
case_GETOPT_HELP_CHAR;
case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
default:
usage (PRINTENV_FAILURE);
}
}
if (optind >= argc)
{
for (env = environ; *env != NULL; ++env)
printf ("%s%c", *env, opt_nul_terminate_output ? '\0' : '\n');
ok = true;
}
else
{
int matches = 0;
for (i = optind; i < argc; ++i)
{
bool matched = false;
/* 'printenv a=b' is silent, even if 'a=b=c' is in environ. */
if (strchr (argv[i], '='))
continue;
for (env = environ; *env; ++env)
{
ep = *env;
ap = argv[i];
while (*ep != '\0' && *ap != '\0' && *ep++ == *ap++)
{
if (*ep == '=' && *ap == '\0')
{
printf ("%s%c", ep + 1,
opt_nul_terminate_output ? '\0' : '\n');
matched = true;
break;
}
}
}
matches += matched;
}
ok = (matches == argc - optind);
}
exit (ok ? EXIT_SUCCESS : EXIT_FAILURE);
}
static void
dateMachine (void)
{
system(date);
}
If you google "printenv.c" You'll find several versions of just that file, that you can compile and run with minimal jiggery-pokery.
Example: "http://www.opensource.apple.com/source/shell_cmds/shell_cmds-170/printenv/printenv.c"
./configure && make (without sudo). It compiles every .c program locally.
It compiles only the .c files that have been changed, due to datestamp.
Related
I have a 3rd party C static library that uses xdr_wrapstring. I am moving to RH 8 where these symbols are not unavailable in the default /lib64/libc.so.6, but are available as versioned symbols (xdr_wrapstring#GLIBC_2.2.5)? Is there a way to tell the linker to resolve xdr_wrapstring to xdr_wrapstring#GLIBC_2.2.5?
I can't link with libtirpc (which provides unversioned symbols) due to it requiring libssl.so & libcrypto.so via libk5crypto.so
Prefaced by the top comments ...
The assembler .symver shows some promise. A web search on it shows:
http://web.mit.edu/rhel-doc/3/rhel-as-en-3/symver.html
https://man7.org/conf/lca2006/shared_libraries/slide19a.html
Linking against older symbol version in a .so file
From this, I've created a symver.s file that has stubs that seems to work on my system [which has the same versioned symbols issue].
However, I'd have a look at those linked pages (e.g.) symver is also an attribute, so it may be possible to do this with inline asm from a .c file.
I've created a crude test program:
// xdrtest.c -- print address of xdr_wrapstring
#include <stdio.h>
void xdr_wrapstring(void);
int
main(void)
{
void *ptr = xdr_wrapstring;
printf("%p\n",ptr);
return 0;
}
Here is an better test program:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stddef.h>
#include <rpc/types.h>
#include <rpc/xdr.h>
#define ALEN 1000
#define sysfault(_fmt...) \
do { \
fprintf(stderr,_fmt); \
exit(1); \
} while (0)
XDR xdrs;
void
sendstring(const char *str)
{
static char buf[ALEN];
char *bp;
strcpy(buf,str);
bp = buf;
if (! xdr_wrapstring(&xdrs,&bp))
sysfault("sendstring: xdr_wrapstring fail -- str='%s' buf='%s'\n",
str,buf);
}
void
recvstring(const char *str)
{
static char buf[ALEN];
char *bp;
bp = buf;
if (! xdr_wrapstring(&xdrs,&bp))
sysfault("recvstring: xdr_wrapstring fail -- str='%s' buf='%s'\n",
str,buf);
fprintf(stderr,"buf=%p bp=%p str='%s' bp='%s'\n",buf,bp,str,bp);
if (strcmp(bp,str) != 0)
sysfault("recvstring: MISMATCH\n");
}
void
writer(void)
{
xdrstdio_create(&xdrs, stdout, XDR_ENCODE);
sendstring("hello");
sendstring("world");
sendstring("goodbye");
sendstring("galaxy");
}
void
reader(void)
{
xdrstdio_create(&xdrs, stdin, XDR_DECODE);
recvstring("hello");
recvstring("world");
recvstring("goodbye");
recvstring("galaxy");
}
int
main(int argc,char **argv)
{
int opt_dir = -1;
--argc;
++argv;
for (; argc > 0; --argc, ++argv) {
char *cp = *argv;
if (*cp != '-')
break;
cp += 2;
switch (cp[-1]) {
case 'r':
opt_dir = 0;
break;
case 'w':
opt_dir = 1;
break;
}
}
switch (opt_dir) {
case 0:
reader();
break;
case 1:
writer();
break;
default:
sysfault("main: -r/-w not specified\n");
break;
}
return 0;
}
Here is the "magic" xdrver.s file:
.globl xdrstdio_create
.symver foo, xdrstdio_create#GLIBC_2.2.5
xdrstdio_create:
jmp foo
.globl xdr_wrapstring
.symver bar, xdr_wrapstring#GLIBC_2.2.5
xdr_wrapstring:
jmp bar
Compile with (e.g.):
cc -o xdrtest xdrtest.c xdrver.s
Or, of course, we can create xdrver.o and link with whatever program we want.
Anyway, to test the program:
./xdrtest -w | ./xdrtest -r
And, the output is:
buf=0x4044a0 bp=0x4044a0 str='hello' bp='hello'
buf=0x4044a0 bp=0x4044a0 str='world' bp='world'
buf=0x4044a0 bp=0x4044a0 str='goodbye' bp='goodbye'
buf=0x4044a0 bp=0x4044a0 str='galaxy' bp='galaxy'
When using the auto completion with the Readline library in C, the prompt is reprinted when typing the tab key twice:
(prompt) view NAME_OF_F (user presses tab twice)
NAME_OF_FILE1 NAME_OF_FILE2 (suggestions by Readline)
(prompt) view NAME_OF_F
I'd like to suppress the reprinting of the prompt on the 3rd line by keeping the first line printed with the suggestions below it like such:
(prompt) view NAME_OF_F (user presses tab twice)
NAME_OF_FILE1 NAME_OF_FILE2 (suggestions by Readline)
I'd like the cursor back at the end of the first line that has the prompt.
Compiled with gcc -Wall -O0 -ggdb -fno-builtin rline.c -o rline -lreadline -ltermcap.
Here's a code sample:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <readline/readline.h>
int execute_line(char *line);
void initialize_readline();
static char **fileman_completion(char *text, int start, int end);
static char *command_generator(char *text, int state);
char *command[] = { "view", "quit", (char *)NULL };
int done; /* When non-zero, this global means the user is done using this program. */
int main(int argc, char **argv)
{
char *line;
initialize_readline(); /* Bind our completer. */
for ( ; done == 0; ) {
line = readline("> ");
if (!line)
break;
if (*line)
execute_line(line);
free(line);
}
return 0;
}
/* String to pass to system(). This is for the VIEW command. */
static char syscom[1024];
int execute_line(char *line)
{
int i = 0;
char *word;
/* Isolate the command word. */
while (line[i] && whitespace(line[i]))
i++;
word = line + i;
while (line[i] && !whitespace(line[i])) i++;
if (line[i]) line[i++] = '\0';
if (strcmp(word, "quit") == 0) {
done = 1;
return 0;
} else if (strcmp(word, "view")) {
fprintf(stderr, "%s: Choose only \"view FILE\" or \"quit\" as your command.\n", word);
return -1;
}
/* Get argument to command, if any. */
while (whitespace(line[i])) i++;
word = line + i;
if(!word || !*word) {
fprintf(stderr, "view: Argument required.\n");
return -1;
}
sprintf(syscom, "more %s", word);
return system(syscom);
}
void initialize_readline()
{
rl_readline_name = "rline";
rl_attempted_completion_function = (rl_completion_func_t *)fileman_completion;
}
static char **fileman_completion(char *text, int start, int end)
{
if (start == 0)
return rl_completion_matches(text, (rl_compentry_func_t *)*command_generator);
return NULL;
}
static char *command_generator(char *text, int state)
{
static int list_index, len;
char *name;
if (!state) {
list_index = 0;
len = strlen(text);
}
while ((name = command[list_index++]))
if (strncmp(name, text, len) == 0)
return strdup(name);
return NULL;
}
The program only accepts the commands view FILE_NAME to view the contents of a file and quit to exit the program.
The example is a shortened version of a sample program found here.
I don't think that readline has anything like that built in, but it does provide a lot of customisation possibilities if you want to try to write the logic yourself.
You could try writing a custom rl_completion_display_matches_hook to display the completion list. But it's not entirely clear to me how you would restore the cursor position afterwards. I don't think readline has a public interface for either finding or resetting the cursor position. (And, of course, it's possible that the completion list was so big that the original command scrolled off the screen.)
As an alternative, I was able use the hook to print the completion list over top of the current line and then redisplay the prompt after the completion list (although I cheated by assuming that the current input is always just one line). That's not quite what you asked for, but it may be useful for demonstration purposes. I used the following custom match printer:
static void display_matches(char** matches, int len, int max) {
putp(carriage_return);
putp(clr_eol);
putp(cursor_up);
rl_display_match_list(matches, len, max);
rl_forced_update_display();
}
I also added the following to the initialisation function:
rl_completion_display_matches_hook = display_matches;
setupterm(NULL, 1, (int*)0);
Thanks #rici for the inspiration. I got it working with his function with some modifications.
In order for this to work properly you need to download the readline library. In the rlprivate.h file from readline, I removed the lines char **lines;, and the line #include "realdine.h" from display.c. Then in your own .c you must have an #include </PATH/TO/display.c>. In that display.c, an #include points to the modified rlprivate.h. All of this so that I can have access to _rl_move_vert(1).
static void display_matches(char** matches, int len, int max)
{
int saved_point = rl_point;
char *saved_line = rl_copy_text(0, rl_end);
rl_save_prompt();
rl_replace_line("", 0); // Clear the previous text
putp(cursor_up);
_rl_move_vert(1);
rl_display_match_list(matches, len, max);
putp(cursor_up);
rl_restore_prompt();
rl_replace_line(saved_line, 0);
rl_point = saved_point;
rl_redisplay();
putp(cursor_down);
free(saved_line);
}
I was working on my game and decided to use eclipse as my compiler. I had to compile it for both platforms: x86 and x64. The trouble started there. There are many dependency files in the system path.
And every time I had to change them in order to change the platform. So, I've created a line to set up my configurations faster and without affect the path itself.
This is the line to add into the path that I've created:
%DRIVE%\mingw\mingw%PLATFORM%\bin;%DRIVE%\Dropbox\Machine\Windows\C\Place\bin\x%PLATFORM%;%DRIVE%\Dropbox\Machine\Windows\C\PLUGIN\x%PLATFORM%\bin;
As you guys can see there are two variables there: %DRIVE% and %PLATFORM%.
I wish to change them with a file that I try to create in c.
Here is the code
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <string.h>
char *strremove(char *str, const char *sub) {
char *p, *q, *r;
if ((q = r = strstr(str, sub)) != NULL) {
size_t len = strlen(sub);
while ((r = strstr(p = r + len, sub)) != NULL) {
while (p < r)
*q++ = *p++;
}
while ((*q++ = *p++) != '\0')
continue;
}
return str;
}
#ifndef HAVE_SETENV
int setenv(const char * variable,const char * value) {
if(!variable || !value)return(0);
int len = strlen(variable)+1+strlen(value)+1;
char * EnvString = calloc(len,sizeof(char));
sprintf(EnvString, "%s=%s", variable, value);
if (!_putenv(EnvString)) {
return (1);
}
if(EnvString)free(EnvString);
return (0);
}
#endif
void change_platform(int argc,char ** argv) {
char * variable = "PLATFORM",* value = "86";
if(argc > 1){
value = argv[1];
}
if (setenv(variable, value)) {
printf("\n environmental variable successfully written");
printf("\n value of the environmental variable written is %s",
getenv(variable));
} else {
printf("\n error in writing the environmental variable");
}
}
int main(int argc, char ** argv) {
change_platform(argc,argv);
getch();
return 0;
}
My code shows the right result inside the program, but when I go and check the system environment itself, nothing changes. Am I doing something wrong.
Detail: I thought it was because of mingw which isn't native from Windows, then I've created I file in Visual c++ too, but it did not work either.
Please remember it affects only the environment of the current process
getenv, _wgetenv
int main( void )
{
char *libvar;
// Get the value of the LIB environment variable.
libvar = getenv( "LIB" ); // C4996
// Note: getenv is deprecated; consider using getenv_s instead
if( libvar != NULL )
printf( "Original LIB variable is: %s\n", libvar );
// Attempt to change path. Note that this only affects the environment
// variable of the current process. The command processor's
// environment is not changed.
_putenv( "LIB=c:\\mylib;c:\\yourlib" ); // C4996
// Note: _putenv is deprecated; consider using putenv_s instead
// Get new value.
libvar = getenv( "LIB" ); // C4996
if( libvar != NULL )
printf( "New LIB variable is: %s\n", libvar );
}
How to delete a non empty directory in C or C++? Is there any function? rmdir only deletes empty directory. Please provide a way without using any external library.
Also tell me how to delete a file in C or C++?
You want to write a function (a recursive function is easiest, but can easily run out of stack space on deep directories) that will enumerate the children of a directory. If you find a child that is a directory, you recurse on that. Otherwise, you delete the files inside. When you are done, the directory is empty and you can remove it via the syscall.
To enumerate directories on Unix, you can use opendir(), readdir(), and closedir(). To remove you use rmdir() on an empty directory (i.e. at the end of your function, after deleting the children) and unlink() on a file. Note that on many systems the d_type member in struct dirent is not supported; on these platforms, you will have to use stat() and S_ISDIR(stat.st_mode) to determine if a given path is a directory.
On Windows, you will use FindFirstFile()/FindNextFile() to enumerate, RemoveDirectory() on empty directories, and DeleteFile() to remove files.
Here's an example that might work on Unix (completely untested):
int remove_directory(const char *path) {
DIR *d = opendir(path);
size_t path_len = strlen(path);
int r = -1;
if (d) {
struct dirent *p;
r = 0;
while (!r && (p=readdir(d))) {
int r2 = -1;
char *buf;
size_t len;
/* Skip the names "." and ".." as we don't want to recurse on them. */
if (!strcmp(p->d_name, ".") || !strcmp(p->d_name, ".."))
continue;
len = path_len + strlen(p->d_name) + 2;
buf = malloc(len);
if (buf) {
struct stat statbuf;
snprintf(buf, len, "%s/%s", path, p->d_name);
if (!stat(buf, &statbuf)) {
if (S_ISDIR(statbuf.st_mode))
r2 = remove_directory(buf);
else
r2 = unlink(buf);
}
free(buf);
}
r = r2;
}
closedir(d);
}
if (!r)
r = rmdir(path);
return r;
}
Many unix-like systems (Linux, the BSDs, and OS X, at the very least) have the fts functions for directory traversal.
To recursively delete a directory, perform a depth-first traversal (without following symlinks) and remove every visited file:
int recursive_delete(const char *dir)
{
int ret = 0;
FTS *ftsp = NULL;
FTSENT *curr;
// Cast needed (in C) because fts_open() takes a "char * const *", instead
// of a "const char * const *", which is only allowed in C++. fts_open()
// does not modify the argument.
char *files[] = { (char *) dir, NULL };
// FTS_NOCHDIR - Avoid changing cwd, which could cause unexpected behavior
// in multithreaded programs
// FTS_PHYSICAL - Don't follow symlinks. Prevents deletion of files outside
// of the specified directory
// FTS_XDEV - Don't cross filesystem boundaries
ftsp = fts_open(files, FTS_NOCHDIR | FTS_PHYSICAL | FTS_XDEV, NULL);
if (!ftsp) {
fprintf(stderr, "%s: fts_open failed: %s\n", dir, strerror(errno));
ret = -1;
goto finish;
}
while ((curr = fts_read(ftsp))) {
switch (curr->fts_info) {
case FTS_NS:
case FTS_DNR:
case FTS_ERR:
fprintf(stderr, "%s: fts_read error: %s\n",
curr->fts_accpath, strerror(curr->fts_errno));
break;
case FTS_DC:
case FTS_DOT:
case FTS_NSOK:
// Not reached unless FTS_LOGICAL, FTS_SEEDOT, or FTS_NOSTAT were
// passed to fts_open()
break;
case FTS_D:
// Do nothing. Need depth-first search, so directories are deleted
// in FTS_DP
break;
case FTS_DP:
case FTS_F:
case FTS_SL:
case FTS_SLNONE:
case FTS_DEFAULT:
if (remove(curr->fts_accpath) < 0) {
fprintf(stderr, "%s: Failed to remove: %s\n",
curr->fts_path, strerror(curr->fts_errno));
ret = -1;
}
break;
}
}
finish:
if (ftsp) {
fts_close(ftsp);
}
return ret;
}
If you are using a POSIX compliant OS, you could use nftw() for file tree traversal and remove (removes files or directories). If you are in C++ and your project uses boost, it is not a bad idea to use the Boost.Filesystem as suggested by Manuel.
In the code example below I decided not to traverse symbolic links and mount points (just to avoid a grand removal:) ):
#include <stdio.h>
#include <stdlib.h>
#include <ftw.h>
static int rmFiles(const char *pathname, const struct stat *sbuf, int type, struct FTW *ftwb)
{
if(remove(pathname) < 0)
{
perror("ERROR: remove");
return -1;
}
return 0;
}
int main(int argc, char *argv[])
{
if (argc != 2)
{
fprintf(stderr,"usage: %s path\n",argv[0]);
exit(1);
}
// Delete the directory and its contents by traversing the tree in reverse order, without crossing mount boundaries and symbolic links
if (nftw(argv[1], rmFiles,10, FTW_DEPTH|FTW_MOUNT|FTW_PHYS) < 0)
{
perror("ERROR: ntfw");
exit(1);
}
return 0;
}
The easiest way to do this is with remove_all function of the Boost.Filesystem library. Besides, the resulting code will be portable.
If you want to write something specific for Unix (rmdir) or for Windows (RemoveDirectory) then you'll have to write a function that deletes are subfiles and subfolders recursively.
EDIT
Looks like this question was already asked, in fact someone already recommended Boost's remove_all. So please don't upvote my answer.
C++17 has <experimental\filesystem> which is based on the boost version.
Use std::experimental::filesystem::remove_all to remove recursively.
If you need more control, try std::experimental::filesystem::recursive_directory_iterator.
You can also write your own recursion with the non-resursive version of the iterator.
namespace fs = std::experimental::filesystem;
void IterateRecursively(fs::path path)
{
if (fs::is_directory(path))
{
for (auto & child : fs::directory_iterator(path))
IterateRecursively(child.path());
}
std::cout << path << std::endl;
}
You can use opendir and readdir to read directory entries and unlink to delete them.
//======================================================
// Recursely Delete files using:
// Gnome-Glib & C++11
//======================================================
#include <iostream>
#include <string>
#include <glib.h>
#include <glib/gstdio.h>
using namespace std;
int DirDelete(const string& path)
{
const gchar* p;
GError* gerr;
GDir* d;
int r;
string ps;
string path_i;
cout << "open:" << path << "\n";
d = g_dir_open(path.c_str(), 0, &gerr);
r = -1;
if (d) {
r = 0;
while (!r && (p=g_dir_read_name(d))) {
ps = string{p};
if (ps == "." || ps == "..") {
continue;
}
path_i = path + string{"/"} + p;
if (g_file_test(path_i.c_str(), G_FILE_TEST_IS_DIR) != 0) {
cout << "recurse:" << path_i << "\n";
r = DirDelete(path_i);
}
else {
cout << "unlink:" << path_i << "\n";
r = g_unlink(path_i.c_str());
}
}
g_dir_close(d);
}
if (r == 0) {
r = g_rmdir(path.c_str());
cout << "rmdir:" << path << "\n";
}
return r;
}
How to delete a non empty folder using unlinkat() in c?
Here is my work on it:
/*
* Program to erase the files/subfolders in a directory given as an input
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
void remove_dir_content(const char *path)
{
struct dirent *de;
char fname[300];
DIR *dr = opendir(path);
if(dr == NULL)
{
printf("No file or directory found\n");
return;
}
while((de = readdir(dr)) != NULL)
{
int ret = -1;
struct stat statbuf;
sprintf(fname,"%s/%s",path,de->d_name);
if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, ".."))
continue;
if(!stat(fname, &statbuf))
{
if(S_ISDIR(statbuf.st_mode))
{
printf("Is dir: %s\n",fname);
printf("Err: %d\n",ret = unlinkat(dirfd(dr),fname,AT_REMOVEDIR));
if(ret != 0)
{
remove_dir_content(fname);
printf("Err: %d\n",ret = unlinkat(dirfd(dr),fname,AT_REMOVEDIR));
}
}
else
{
printf("Is file: %s\n",fname);
printf("Err: %d\n",unlink(fname));
}
}
}
closedir(dr);
}
void main()
{
char str[10],str1[20] = "../",fname[300]; // Use str,str1 as your directory path where it's files & subfolders will be deleted.
printf("Enter the dirctory name: ");
scanf("%s",str);
strcat(str1,str);
printf("str1: %s\n",str1);
remove_dir_content(str1); //str1 indicates the directory path
}
This code will open particular directory and iterate over all files and delete them which are under that directory. After that it will delete empty directory at the end.
/**
* #file RemoveDir.c
* #author Om Patel (ompatel1861#gmail.com)
* #brief This program will remove non empty directory.
* #version 0.1
* #date 2022-05-31
*
* #copyright Copyright (c) 2022
*
*/
#include<stdio.h>
#include<string.h>
#include<dirent.h>
#include <unistd.h>
int main()
{
DIR* dir = opendir("OUTPUT/Aakash");
struct dirent* entity;
entity = readdir(dir);
while(entity != NULL){
char path[30] ="OUTPUT/Aakash/";
printf("%s\n",entity->d_name);
strcat(path,entity->d_name);
printf("PAth: %s\n",path);
remove(path);
entity = readdir(dir);
}
char path1[30] ="OUTPUT/Aakash";
rmdir(path1);
closedir(dir);
char out[20]="OUTPUT/";
char fol_file[30];
sprintf(fol_file,"%s\\",out);
printf("%s",fol_file);
return 0;
}
I've got an library which must read data from sqlite database by calling
extern int read(char** argv, int argc); // from header
it must process:
int read(char** argv, int argc) {
char* lineborder1;
char* lineborder2;
char* spaces1;
char* spaces2;
int maxl2 = 0, maxl1 = 0;
int i, maxi1, maxi2;
if (prelude() == -1) return -1;
// etc...
where prelude is inner procedure for sqlite connection:
int prelude() {
timefile = 0;
f = NULL;
#ifndef WIN32
char* temp = (char*)calloc(200, sizeof(char));
#endif
queries = (char**)malloc(sizeof(char*) * q_cnt);
for (x = 0; x < q_cnt; x++) {
queries[x] = (char*)malloc(sizeof(char) * q_size);
}
#ifdef WIN32
retval = sqlite3_open("todo.db3", &handle);
#else
home = (char*)getenv("HOME");
strcpy(temp, home);
retval = sqlite3_open(strcat(temp, "/.todo.db3"), &handle);
free(temp);
#endif
if (retval) {
printf("Database connection failed\n\r");
return -1;
}
return 0;
}
whole source is here : bitbucket: ctodo.c
I call this read from my application:
else if ((strcmp(argv[1], "read") == 0) || (strcmp(argv[1], "r") == 0)) {
return read(argv, argc);
but getting infinity cycle of this read call:
>>./todo r
Database connection failed
Database connection failed
Database connection failed
.... etc
here is how do I build it:
gcc -I . -c -o todo.a ctodo.c -lsqlite3 -O3
gcc -I . -o todo cctodo.c -lsqlite3 -O3 todo.a
help or version calls wrok fine and read works fine on windows, something specific to my linux build is here but I can't find a bug so far. what could call this read to run in infinity cycle like that?
The read function is defined in libc.so, and used to, you know, read data.
It is exceedingly likely that sqlite3_open() calls it.
By introducing your own function called read(), you've made your program enter infinite loop. If you wait long enough, your program will run out of stack and crash.
Doctor, it hurts when I do that. Well, don't do that :-)