Using System Calls in C to compare 2 user Inputted Passwords - c

I am learner in C and I need to compile my code using shellforge and hence cannot use any library functions as they provide an error.
Can someone help me with the same.
This is what I have so far, I need help in comparing the 2 passwords and only then writing it to the file. Any help/modifications to my code to achieve this with an explanation will be highly appreciated.
#include <stdio.h>
int main()
{
int fd;
char username;
char kbinput[KBINPUT_SIZE];
char kbinputpassone[KBINPUTPASSONE_SIZE];
char kbinputpasstwo[KBINPUTPASSTWO_SIZE];
char passwordone;
char passwordtwo;
int count = 0;
int ret;
fd = open("test.txt", O_CREAT | O_RDWR,0666);
if(fd == -1)
{
printf("Error!");
exit(1);
}
write(1,"Enter the username",18);
do
{
read(0, &username, 1);
if (username == '\n')
break;
kbinput[count++] = username;
}
while (count < KBINPUT_SIZE - 1);
kbinput[count] = 0;
write(fd,username,10);
write(1,"Enter the password",18);
count =0;
do
{
read(0, &passwordone, 1);
if (passwordone == '\n')
break;
kbinputpassone[count++] = passwordone;
}
while (count < KBINPUTPASSONE_SIZE - 1);
kbinputpassone[count] = 0;
write(1,"Enter the password again",25);
count=0;
do
{
read(0, &passwordtwo, 1);
if (passwordtwo == '\n')
break;
kbinputpasstwo[count++] = passwordtwo;
}
while (count < KBINPUTPASSTWO_SIZE - 1);
kbinputpasstwo[count] = 0;
write(1,"The Passwords match",20);
write(fd, passwordone, 15);
return 0;
}

Related

testing the program for various memory allocation errors and memory leaks

The tee utility copies its standard input to both stdout and to a file. This allows the user to view the output of a command on the console while writing a log to a file at the same time.
My program implements the tee command from linux POSIX system calls, with the -a option.
How can I modify the program to test for possible memory allocation errors? Positive memory leaks.
Also, the memory allocation doesn't seem right to me. When creating a new buffer each time I call getline(), should I declare and initialize line outside the loop and reallocate it only after the loop has ended?
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <fcntl.h>
#include <sys/stat.h>
#include "apue.h"
int writeAll(int fd, char *buf, int buflen);
int main(int argc, char *argv[]) {
struct stat status;
int option;
bool append = false;
int errCode = 0;
while ((option = getopt(argc, argv, "a")) != -1) {
switch (option) {
case 'a':
append = true;
break;
}
}
// We need to write in all the files given as parameter AND stdout.
int numFileDescriptors = argc - optind + 1;
int *fileDescriptors = malloc((numFileDescriptors + 1) * sizeof(*fileDescriptors));
char **fileNames = malloc((numFileDescriptors + 1) * sizeof(*fileNames));
int lastFileDescriptor = 0;
fileDescriptors[0] = STDOUT_FILENO;
fileNames[0] = "stdout";
int flags = O_CREAT | O_WRONLY;
if (append) {
flags = flags | O_APPEND;
} else {
flags = flags | O_TRUNC;
}
for (int i = optind; i < argc; i++) {
if (access(argv[i], F_OK) == 0) {
if (access(argv[i], W_OK) < 0) {
err_msg("%s: Permission denied", argv[i]);
errCode = 1;
continue;
}
}
if (lstat(argv[i], &status) < 0) {
status.st_mode = 0;
}
if (S_ISDIR(status.st_mode)) {
err_msg("%s: Is a directory", argv[i]);
errCode = 1;
continue;
}
int fd = open(argv[i], flags, 0644);
if (fd < 0) {
err_msg("%s: Failed to open", argv[i]);
errCode = 1;
continue;
}
lastFileDescriptor = lastFileDescriptor + 1;
fileDescriptors[lastFileDescriptor] = fd;
fileNames[lastFileDescriptor] = argv[i];
}
while (true) {
size_t len = 0;
ssize_t read = 0;
char *line = NULL;
read = getline(&line, &len, stdin);
if (read == -1) {
break;
}
for (int i = 0; i <= lastFileDescriptor; i++) {
int written = writeAll(fileDescriptors[i], line, strlen(line));
if (written < 0) {
err_msg("%s: Failed to write", fileNames[i]);
errCode = 1;
}
}
}
for (int i = 0; i <= lastFileDescriptor; i++) {
close(fileDescriptors[i]);
}
free(fileDescriptors);
free(fileNames);
return errCode;
}
int writeAll(int fd, char *buf, int buflen) {
ssize_t written = 0;
while (written < buflen) {
int writtenThisTime = write(fd, buf + written, buflen - written);
if (writtenThisTime < 0) {
return writtenThisTime;
}
written = written + writtenThisTime;
}
return written;
}
Testing for memory allocation failure is simple: just add tests, report the failure and exit with a non zero exit status.
To avoid memory leaks, you must free the line that was allocated by getline inside the while (true) loop:
while (true) {
size_t len = 0;
char *line = NULL;
ssize_t nread = getline(&line, &len, stdin);
if (nread == -1) {
if (errno == ENOMEM) {
fprintf(stderr, "out of memory\n");
exit(1);
}
free(line);
break;
}
for (int i = 0; i <= lastFileDescriptor; i++) {
int written = writeAll(fileDescriptors[i], line, nread);
if (written < 0) {
err_msg("%s: Failed to write", fileNames[i]);
errCode = 1;
}
}
free(line);
}
Alternately, you can reuse the same line for the next iteration and only free the buffer after the while loop:
size_t len = 0;
char *line = NULL;
while (true) {
ssize_t nread = getline(&line, &len, stdin);
if (nread == -1) {
if (errno == ENOMEM) {
fprintf(stderr, "out of memory\n");
exit(1);
}
break;
}
for (int i = 0; i <= lastFileDescriptor; i++) {
int written = writeAll(fileDescriptors[i], line, nread);
if (written < 0) {
err_msg("%s: Failed to write", fileNames[i]);
errCode = 1;
}
}
}
free(line);
Note that reading a full line at a time is risky as the input might contain very long, possibly unlimited lines (eg: /dev/zero). You might want to use fgets() to read a line with a limited length and dispatch the contents as you read, possibly splitting long lines:
char line[4096];
while (fgets(line, sizeof line, stdin)) {
size_t len = strlen(line);
for (int i = 0; i <= lastFileDescriptor; i++) {
int written = writeAll(fileDescriptors[i], line, len);
if (written < 0) {
err_msg("%s: Failed to write", fileNames[i]);
errCode = 1;
}
}
}
The above code has a limitation: if the input streams contains null bytes, they will cause some data to be lost in translation. A solution is to not use fgets(), but getchar() directly:
for (;;) {
char line[4096];
size_t len = 0;
int c;
while (len < sizeof(line) && (c = getchar()) != EOF)) {
if ((line[len++] = c) == '\n')
break;
}
if (len > 0) {
for (int i = 0; i <= lastFileDescriptor; i++) {
int written = writeAll(fileDescriptors[i], line, len);
if (written < 0) {
err_msg("%s: Failed to write", fileNames[i]);
errCode = 1;
}
}
}
if (c == EOF)
break;
}

Why am I getting extra character when trying to write to file?

This is supposed to flips upper and lower case letters but its not flipping just adding random characters.
int in = open(argv[1], O_RDONLY);
int out = open(argv[2], O_CREAT | O_WRONLY, 0624);
char buff[65];
buff[64] = '\0';
if(argc < 2){
printf("Not enough arguments");
return 1;
}
else if(argv[1] == 0 || argv[2] == 0){
printf("No file");
return 1;
}
int i = read(in,buff,64);
for (i = 0; buff[i]!='\0'; i++) {
if(buff[i] >= 'a' && buff[i] <= 'z') {
printf("%d", buff[i]-32);
} else if (buff[i] >= 'A' && buff[i] <= 'Z') {
printf("%d", buff[i]+32);
} else {
printf("%d", buff[i]);
}
}
write(out, buff, 64);
close(in);
close(out);
return 0;
}
How do I get it to read the character and flip without extras?
If your input file does not contain a '\0' as last character, your condition buff[i]!='\0' depends on random contents.
Change these lines:
char buff[65];
buff[64] = '\0';
to this line:
char buff[65] = { 0 };
However, read() tells you the number of bytes it read. You can use that value to mark the end:
int n = read(in,buff,64);
for (i = 0; i < n; i++) {
/* ... */
}
write(out, buff, n);
Write a function that reads a line, up to some maximum size; separate the logic of reading the file from other processing,
int readline(int fh, char* buff, int maxsize) {
int rc = read(fh,buff,maxsize);
if( rc < 0 ) {
printf("read error, %d\n",rc);
return rc;
}
return rc;
}
Write a function that writes the converted buffer, separate the logic of writing the file and other processing,
int writeline(int fh, char* buff, int len) {
int wc = write(fh, buff, len);
return wc;
}
Write a function that flips the case; separate the logic from reading and writing the file,
char* flipcase(char* buff, int len) {
if(!buff || len<1) return buff;
char* cp = buff;
for (int ix = 0; ix<len; ix++, cp++ ) {
if( isupper(*cp) { // in [A-Z]
// printf("%d", *cp-32); // not portable
*cp = tolower(*cp); // modify buff[ix]
}
else if( islower(*cp) ) { // in [a-z]
// printf("%d", *cp+32); // not portable
*cp = toupper(*cp); // modify buff[ix]
}
// else {
// unchanged
// }
// printf("%d", *cp);
}
return buff;
}
Build a function that handles each line separately,
# define MAXLINE (256) // named 'constant'
int doline(int fin, int fout) {
char buff[MAXLINE+1] = { 0 };
int rc = readline(fin, buff, MAXLINE);
// check results of readline here
flipcase(buff, rc);
int wc = writeline(fout, buff, rc);
// check results of writeline here
return rc;
}
Here you would handle your (argc, argv) and open your files,
if(argc < 3) {
printf("Not enough arguments");
return 1;
}
if(argv[1] == 0 || argv[2] == 0) {
printf("No file");
return 1;
}
int fin = open(argv[1], O_RDONLY);
if( !fin ) {
printf("open %s failed\n",argv[1]);
return 2;
}
int fout = open(argv[2], O_CREAT | O_WRONLY, 0624);
if( !fout ) {
printf("open %s failed\n",argv[2]);
close(fout);
return 2;
}
int rc = 0;
// process one line
rc = doline(fin,fout);
// or, process every line in file
for( ; rc = doline(fin,fout) >= 0; ) {
}
close(fin);
close(fh);

Set files.txt into program's arguments in code blocks

My question is simple, I am a beginner in c language, I am currently developing the hangman game on code blocks. To do this a restriction was imposed on me, the file in which my word dictionary is located, I must pass it as an argument in my program. I saw in my research that in the project -> Set program's arguments .. tab, we can add arguments, but I cannot pass my text file as a parameter. Anyone have a solution please? thank you so much
I pass it like this :
But when I build my program it does not detect my file.
this is the code that tries to read the file
char *read_file(int ac, char **av, int *lifes, char **word)
{
int fd = -1;
int nb_caractere = 0;
char *buffer = calloc(1,sizeof(char));
if((fd = open(av[1], O_RDONLY)) == -1)
{
printf("Aucun fichier ou dossier. \n");
return (NULL);
}
lseek(fd, 0, SEEK_SET);
while(read(fd, buffer, 1) > 0)
{
nb_caractere++;
}
lseek(fd, 0, SEEK_SET);
buffer = calloc(nb_caractere+1, sizeof(char));
memset(buffer, 0, nb_caractere+1);
read(fd, buffer, nb_caractere);
close(fd);
return (buffer);
}
and the main how call this funtion is this :
int main(int ac, char **av)
{
int lifes = 10;
char *word = NULL;
char *hide_word = NULL;
srand(time(NULL));
if(ac < 2 || ac > 3)
{
printf("Nombres d'arguments incorrect !\n");
return (84);
}
if(ac == 3)
{
lifes = atoi(av[2]);
}
if(init_game(lifes, &word, &hide_word, read_file(ac, av, &lifes,
&word)) == 84 )
{
free(word);
return (84);
}
game_loop(lifes, word, hide_word);
free(word);
free(hide_word);
return 0;
}
the output of this code is "aucun fichier ou dossier"

How to get a line from csv file with a custom fgets

I'm currently writing a program in C that reads in from a CSV file, I have a defined buffer size but am having trouble separating each line from the buffer. I can see where the line ends by checking for a '\n' char. I cannot extract that line from the buffer for parsing however. Anybody have some ideas?
#ifndef BUFFSIZE
#define BUFFSIZE 4096
#endif
int main() {
int fd;
int fdBin;
char * buf = malloc(BUFFSIZE);
int count = 0;
bool EOFFlag = false;
fd = open("SongCSV.csv", O_RDONLY);
fdBin = open("BinarySongData.bin", O_CREAT | O_WRONLY, "0600");
if (fd == -1) {
printf("failed to open a file\n");
exit(1);
}
off_t offset = 0;
off_t offsetOld = 0;
int readBytes;
while (!EOFFlag) {
offsetOld = offset;
offset = lseek(fd, offset - offsetOld, SEEK_CUR);
readBytes = read(fd, buf, BUFFSIZE);
printf("\n\n%lld\n\n", (offset));
int i = 0;
int commaCounter = 0;
while (i < readBytes) {
if (buf[i] != '\n') {
}
if (buf[i] == '\n') {
printf("\t\t THIS IS END OF LINE \t%d", i);
commaCounter = 0;
}
if (buf[i] == ',') {
commaCounter++;
if (commaCounter == 4) {
printf("****Album Name****");
}
}
write(fdBin, buf, BUFFSIZE);
printf("%c", buf[i]);
i++;
}
if (readBytes < BUFFSIZE) {
EOFFlag = true;
printf("\nREACHED END OF FILE");
}
printf("\n");
printf("AA: END OF LINE ****%d*****", count);
count++;
}
close(fd);
close(fdBin);
return 0;
}
I do it this way, easy and simple. I just did it quickly, any doubts just ask me, Cheers.
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
int len = sending();
char *firstline;
int i = 0;
char buf[0];
int rd ;
int fd = open("hey.csv", O_RDONLY);
rd = read(fd, buf, 1);
firstline = malloc(sizeof(char) * len);
while (i != len)
{
firstline[i] = buf[0];
i++;
rd = read(fd, buf, 1);
}
firstline[i] = '\0';
printf("%s\n", firstline);
return (0);
}
int sending()
{
int fd = open("hey.csv", O_RDONLY);
char buf[1];
int r = 0;
r = read(fd, buf, 1);
int len = 0;
while (buf[0] != '\n')//getting exact size to malloc
{
len++;
r = read(fd, buf, 1);
}
return len;
}

Segmentation fault when running simple shell program

I am trying to make a simple shell program with the C language which have the options of redirecting stdin and stdout and making a pipe but it's giving me a segmentation fault error. Maybe the problem is in the getline but I'm not sure. Here is the code:
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/stat.h>
#define R 0
#define W 1
#define LINE_LEN 25
struct Job {
char* command;
char** argv;
int stdin;
int stdout;
} typedef Job;
int tokens_number = 0;
int sign_place = 0;
int contain_left = 0;
int contain_right = 0;
int contain_line = 0;
char** parse_cmdline (char * cmdline ){
char** arg = calloc(15, sizeof(char*));
char temp_cmd[LINE_LEN*10];
strcpy(temp_cmd, cmdline);
char * tmp;
tmp = strtok(temp_cmd, " ");
while(tmp != NULL) {
arg[tokens_number] = (char*) malloc(LINE_LEN * sizeof(char*));
strcpy(arg[tokens_number],tmp);
tmp = strtok(NULL, " ");
tokens_number++;
}
//LAST ELEMENT IS NULL
arg[tokens_number+1] = NULL;
return arg;
}
void check_for_special_signs(char** argv){
int i;
for(i=0; i<tokens_number; i++){
if(strcmp(argv[i], "<") == 0){
contain_left = 1;
sign_place = i;
return;
}else if(strcmp(argv[i], ">") == 0){
contain_right = 1;
sign_place = i;
return;
}else if(strcmp(argv[i], "|") == 0){
contain_line = 1;
sign_place = i;
return;
}
}
}
void fork_child(Job* my_job) {
pid_t pid = fork();
if (pid == 0) {
execv(my_job -> command, my_job -> argv);
perror(my_job -> command);
} else if (pid > 0) {
int status;
wait(&status);
} else
perror("fork");
}
char** create_argv(char** argv){
int i;
int j = 0;
char** argvs = calloc(sign_place,sizeof(char*));
if(sign_place!=0){
for(i=0; i < sign_place ; i++){
argvs[i] = (char*) malloc(sizeof(char*));
strcpy(argvs[i],argv[i]);
}
return argvs;
}else{
return argv;
}
}
void close_job(Job* my_job) {
if (my_job -> stdin != STDIN_FILENO)
close(my_job -> stdin);
if (my_job -> stdout != STDOUT_FILENO)
close(my_job -> stdout);
free(my_job);
}
int main() {
size_t s = 512;
char* buffer = malloc(s * sizeof(char));
char** sep_cmd = malloc(s * sizeof(char));
while (getline(&buffer, &s, stdin) != EOF) {
Job* my_job;
int my_pipe[2];
int in = 0;
int out = 1;
sep_cmd = parse_cmdline(buffer);
my_job->command = sep_cmd[0];
my_job->argv = sep_cmd;
my_job->stdin = in;
my_job->stdout = out;
check_for_special_signs(my_job->argv);
pid_t pid = fork();
if (pid == 0) {
if(contain_left == 1){
in = open(my_job->argv[sign_place + 1], O_RDONLY);
if(in < 0){
perror("open()");
}
my_job->argv = create_argv(my_job->argv);
my_job->stdin = in;
}else if(contain_right == 1){
out = open(my_job->argv[sign_place + 1], O_WRONLY | O_CREAT,
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
if (out < 0)
perror("open()");
my_job->argv = create_argv(my_job->argv);
my_job->stdout = out;
}else if(contain_line == 1){
pipe(my_pipe);
if (my_job -> stdin == my_pipe[R])
close(my_pipe[W]);
else
close(my_pipe[R]);
}
execv(my_job -> command, my_job -> argv);
perror(my_job -> command);
} else if (pid > 0) {
int status;
wait(&status);
} else{
perror("fork");
}
close_job(my_job);
free(buffer);
buffer = (char*) malloc(s * sizeof(char));
}
free(buffer);
return 0;
}
That way I can't see if there are more mistakes in the code. Please if you see more mistakes list them too.
Thank you.
You forgot to allocate memory for my_job in main function

Resources