lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite for Android: free password hash cracker in your pocket
[<prev] [next>] [day] [month] [year] [list]
Message-ID: <CAFf+5ziNV4KUT93awVTgipgdQESsi5wJ9tyY9yqiUAXkoWauCw@mail.gmail.com>
Date: Thu, 11 Dec 2025 13:54:19 +0530
From: Amit <amitchoudhary0523@...il.com>
To: linux-kernel@...r.kernel.org
Subject: stdin functions library (Three files: stdin_functions_library.c,
 stdin_functions_library.h, and compile_stdin_functions_library.sh).

stdin functions library (Three files: stdin_functions_library.c,
stdin_functions_library.h, and compile_stdin_functions_library.sh).

--------------------------
stdin_functions_library.c
--------------------------

/*
 * License:
 *
 * This file has been released under "unlicense" license
 * (https://unlicense.org).
 *
 * This is free and unencumbered software released into the public domain.
 *
 * Anyone is free to copy, modify, publish, use, compile, sell, or distribute
 * this software, either in source code form or as a compiled binary, for any
 * purpose, commercial or non-commercial, and by any means.
 *
 * For more information about this license, please visit - https://unlicense.org
 */

/*
 * Author: Amit Choudhary
 * Email: amitchoudhary0523 AT gmail DOT com
 */

#include "stdin_functions_library.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>

const char *sful_convert_err_num_to_err_str(int error_num)
{

    switch (error_num) {

        case SFUL_SUCCESS:
            return ("Everything happened successfully");

        case SFUL_FAILURE:
            return ("Some error happened");

        case SFUL_ARG_STR_IS_NULL:
            return ("Argument 'str' is NULL");

        case SFUL_ARG_SIZE_IS_OUT_OF_BOUNDS:
            return ("Argument 'size' is either less than 1 or greater than"
                    " SFUL_MAX_INPUT_SIZE_ALLOWED_FROM_STDIN");

        case SFUL_USER_GAVE_MORE_INPUT_THAN_ASKED_FOR:
            return ("The user gave more input than asked for");

        case SFUL_ARG_STR_IS_EMPTY_STRING:
            return ("Argument 'str' is an empty string");

        case SFUL_LENGTH_OF_ARG_STR_IS_OUT_OF_BOUNDS:
            return ("The length of argument 'str' is greater than"
                    " 'SFUL_INTEGER_STR_SIZE - 1'");

        case SFUL_ARG_MSG_FOR_USER_IS_NULL:
            return ("Argument 'msg_for_user' is NULL");

        case SFUL_ARG_MIN_IS_OUT_OF_BOUNDS:
            return ("Argument 'min' is less than SFUL_INT_MIN or greater than"
                    " SFUL_INT_MAX");

        case SFUL_ARG_MAX_IS_OUT_OF_BOUNDS:
            return ("Argument 'max' is less than SFUL_INT_MIN or greater than"
                    " SFUL_INT_MAX");

        case SFUL_ARG_MAX_IS_LESS_THAN_ARG_MIN:
            return ("Argument 'max' is less than argument 'min'");

    } // end of switch (error_num)

    return ("Wrong error number given");

} // end of function sful_convert_err_num_to_err_str()

int sful_get_input_from_stdin_and_clear_stdin(char *str, int size,
                                              int clear_stdin)
{

    int c = 0;
    int num_chars_read = 0;

    if (!str) {
        if (clear_stdin > 0) {
            sful_clear_stdin();
        }
        return SFUL_ARG_STR_IS_NULL;
    }

    if ((size < 1) || (size > SFUL_MAX_INPUT_SIZE_ALLOWED_FROM_STDIN)) {
        if (clear_stdin > 0) {
            sful_clear_stdin();
        }
        return SFUL_ARG_SIZE_IS_OUT_OF_BOUNDS;
    }

    while (1) {

        c = getchar();

        if ((c == '\n') || (c == EOF)) {
            str[num_chars_read] = 0;
            if (clear_stdin > 0) {
                sful_clear_stdin();
            }
            return SFUL_SUCCESS;
        }

        str[num_chars_read] = (char)(c);

        num_chars_read++;

        // The user has given more input than asked for, so we should return
        // a negative error number and memset all characters read till now to 0.
        if (num_chars_read > (size - 1)) {
            memset(str, 0, (size_t)(num_chars_read));
            if (clear_stdin > 0) {
                sful_clear_stdin();
            }
            return SFUL_USER_GAVE_MORE_INPUT_THAN_ASKED_FOR;
        }

    } // end of while (1) loop

} // end of function sful_get_input_from_stdin_and_clear_stdin()

void sful_clear_stdin(void)
{

    int c = 0;

    fcntl(fileno(stdin), F_SETFL, fcntl(0, F_GETFL) | O_NONBLOCK);
    c = getchar();
    fcntl(fileno(stdin), F_SETFL, fcntl(0, F_GETFL) ^ O_NONBLOCK);

    if ((c == '\n') || (c == EOF)) {
        return;
    }

    while ((c = getchar()) && (c != '\n') && (c != EOF));

    return;

} // end of function sful_clear_stdin()

void sful_wait_for_user_to_press_enter(void)
{

    printf("Please press the \"ENTER\" key to continue..");

    getchar();

    sful_clear_stdin();

    return;

} // end of function sful_wait_for_user_to_press_enter()

int sful_get_integer_from_user_within_range_inclusive(const char *msg_for_user,
                                          int min, int max, int *error_num_ptr)
{

    char str[SFUL_INTEGER_STR_SIZE];
    int int_from_user = SFUL_INT_MIN - 1;
    int retval = SFUL_FAILURE;

    *error_num_ptr = SFUL_SUCCESS;

    if (!msg_for_user) {
        *error_num_ptr = SFUL_ARG_MSG_FOR_USER_IS_NULL;
        return (SFUL_INT_MIN - 1);
    }

    if ((min < SFUL_INT_MIN) || (min > SFUL_INT_MAX)) {
        *error_num_ptr = SFUL_ARG_MIN_IS_OUT_OF_BOUNDS;
        return (SFUL_INT_MIN - 1);
    }

    if ((max < SFUL_INT_MIN) || (max > SFUL_INT_MAX)) {
        *error_num_ptr = SFUL_ARG_MAX_IS_OUT_OF_BOUNDS;
        return (SFUL_INT_MIN - 1);
    }

    if (max < min) {
        *error_num_ptr = SFUL_ARG_MAX_IS_LESS_THAN_ARG_MIN;
        return (SFUL_INT_MIN - 1);
    }

    // Keep looping until a valid integer is received or some error happens.
    while ((int_from_user < min) || (int_from_user > max)) {

        printf("\n");

        printf("%s", msg_for_user);

        memset(str, 0, SFUL_INTEGER_STR_SIZE);

        retval = sful_get_input_from_stdin_and_clear_stdin(str,
                                    SFUL_INTEGER_STR_SIZE, SFUL_CLEAR_STDIN);

        if (retval == SFUL_USER_GAVE_MORE_INPUT_THAN_ASKED_FOR) {
            continue;
        }

        if (retval != SFUL_SUCCESS) {
            *error_num_ptr = retval;
            return (SFUL_INT_MIN - 1);
        }

        retval = sful_is_str_allowed_integer(str);

        if (retval != SFUL_SUCCESS) {
            continue;
        }

        int_from_user = atoi(str);

    } // end of while loop

    return int_from_user;

} // end of function sful_get_integer_from_user_within_range_inclusive()

char sful_get_y_or_n_from_user(const char *msg_for_user, int *error_num_ptr)
{

    char str[SFUL_Y_OR_N_STR_SIZE];
    int retval = SFUL_FAILURE;

    *error_num_ptr = SFUL_SUCCESS;

    if (!msg_for_user) {
        *error_num_ptr = SFUL_ARG_MSG_FOR_USER_IS_NULL;
        return -1;
    }

    // Keep looping until 'y' or 'n' is received or some error happens.
    while (1) {

        printf("\n");

        printf("%s", msg_for_user);

        memset(str, 0, SFUL_Y_OR_N_STR_SIZE);

        retval = sful_get_input_from_stdin_and_clear_stdin(str,
                                    SFUL_Y_OR_N_STR_SIZE, SFUL_CLEAR_STDIN);

        if (retval == SFUL_USER_GAVE_MORE_INPUT_THAN_ASKED_FOR) {
            continue;
        }

        if (retval != SFUL_SUCCESS) {
            *error_num_ptr = retval;
            return -1;
        }

        if (strncmp(str, "y", SFUL_Y_OR_N_STR_SIZE) == 0) {
            return 'y';
        }

        if (strncmp(str, "n", SFUL_Y_OR_N_STR_SIZE) == 0) {
            return 'n';
        }

    } // end of while (1) loop

} // end of function sful_get_y_or_n_from_user()

int sful_is_str_allowed_integer(const char *str)
{

    char c = -1;

    if (!str) {
        return SFUL_ARG_STR_IS_NULL;
    }

    if (!(str[0])) { // empty string
        return SFUL_ARG_STR_IS_EMPTY_STRING;
    }

    // If length of 'str' is not less than SFUL_INTEGER_STR_SIZE, then it is
    // an error, and in this case, return SFUL_FAILURE.
    if (strnlen(str, SFUL_INTEGER_STR_SIZE) == SFUL_INTEGER_STR_SIZE) {
        return SFUL_LENGTH_OF_ARG_STR_IS_OUT_OF_BOUNDS;
    }

    if ((*str == '+') || (*str == '-')) {
        str++;
    }

    while ((c = *str)) {
        if ((c < '0') || (c > '9')) {
            return SFUL_FAILURE;
        }
        str++;
    }

    return SFUL_SUCCESS;

} // end of function sful_is_str_allowed_integer()

--------------------------
stdin_functions_library.h
--------------------------

/*
 * License:
 *
 * This file has been released under "unlicense" license
 * (https://unlicense.org).
 *
 * This is free and unencumbered software released into the public domain.
 *
 * Anyone is free to copy, modify, publish, use, compile, sell, or distribute
 * this software, either in source code form or as a compiled binary, for any
 * purpose, commercial or non-commercial, and by any means.
 *
 * For more information about this license, please visit - https://unlicense.org
 */

/*
 * Author: Amit Choudhary
 * Email: amitchoudhary0523 AT gmail DOT com
 */

#ifndef _STDIN_FUNCTIONS_H_
#define _STDIN_FUNCTIONS_H_


// SFUL/sful means stdin functions library.


#define SFUL_CLEAR_STDIN 10001 // Arbitrary positive integer which doesn't
                               // conflict with other constant values.

#define SFUL_DO_NOT_CLEAR_STDIN -99992 // Arbitrary negative integer which
                                       // doesn't conflict with other constant
                                       // values.


/* START OF SUCCESS AND ERROR CODES */

// Everything happened successfully.
#define SFUL_SUCCESS 0

// Some error happened.
#define SFUL_FAILURE -1

// Argument 'str' is NULL.
#define SFUL_ARG_STR_IS_NULL -2

// Argument 'size' is either less than 1 or greater than
// 'SFUL_MAX_INPUT_SIZE_ALLOWED_FROM_STDIN'.
#define SFUL_ARG_SIZE_IS_OUT_OF_BOUNDS -3

// The user gave more input than asked for.
#define SFUL_USER_GAVE_MORE_INPUT_THAN_ASKED_FOR -4

// Argument 'str' is an empty string.
#define SFUL_ARG_STR_IS_EMPTY_STRING -5

// The length of argument 'str' is greater than 'SFUL_INTEGER_STR_SIZE - 1'.
#define SFUL_LENGTH_OF_ARG_STR_IS_OUT_OF_BOUNDS -6

// Argument 'msg_for_user' is NULL.
#define SFUL_ARG_MSG_FOR_USER_IS_NULL -7

// Argument 'min' is less than 'SFUL_INT_MIN' or greater than 'SFUL_INT_MAX'.
#define SFUL_ARG_MIN_IS_OUT_OF_BOUNDS -8

// Argument 'max' is less than 'SFUL_INT_MIN' or greater than 'SFUL_INT_MAX'.
#define SFUL_ARG_MAX_IS_OUT_OF_BOUNDS -9

// Argument 'max' is less than argument 'min'.
#define SFUL_ARG_MAX_IS_LESS_THAN_ARG_MIN -10

/* END OF SUCCESS AND ERROR CODES */


// AFAIK, all unix/linux terminals return only a maximum of 4096 characters of
// user input (including the newline character). If the user input is greater
// than 4096 characters (including the newline character), then the character at
// the position 4096 (here, position starts from 1) is replaced by the newline
// character, and the rest of the input is discarded. So, the terminal returns
// a maximum of 4096 characters (including the newline character).
//
// You can reduce the following constant according to your requirements, but
// increasing it beyond 4096 will not serve any purpose because of the reason
// given above.
#define SFUL_MAX_INPUT_SIZE_ALLOWED_FROM_STDIN 4096 // including null
                                                    // terminating character

// The size of the integer string is 10 (including null terminating character)
// so this means that the max number of digits in this string can be 9. If we
// keep the max number of digits as 10, then in some cases, all these digits can
// be 9, and in these cases when we convert the string to integer, then there
// will be integer overflow because 9999999999 (9 is 10 times) is greater than
// INT_MAX. So, to prevent the integer overflow we have limited the max number
// of integer digits in the string to 9. Since the string will be null
// terminated, so accounting for the null terminating character, the size of the
// integer string becomes 10.
#define SFUL_INTEGER_STR_SIZE 10 // including null terminating character

// To understand the following constants, please read the documentation of
// 'SFUL_INTEGER_STR_SIZE' above.
#define SFUL_INT_MIN -99999999
#define SFUL_INT_MAX 999999999

// 'SFUL_Y_OR_N_STR_SIZE' is defined to be 2 characters including the null
// terminating character. This is because we are expecting only one character
// from the user (either 'y' or 'n', 'y' means yes and 'n' means no). If the
// user inputs more than one character, then we will reject the input, and ask
// for new input from the user (this will go on indefinitely until the user
// inputs only 'y' or 'n', or the user terminates this program. So, the size of
// 2 characters (including the null terminating character) is enough to catch
// whether the user has inputted only one character or more than one character.
#define SFUL_Y_OR_N_STR_SIZE 2 // including null terminating character


/*
 * IMPORTANT NOTES:
 *
 *      1. Please make sure that the argument 'error_num_ptr' (that is required
 *         by some functions) is a pointer to an 'int' data type else the
 *         program may crash. If 'error_num_ptr' is NULL, then the program will
 *         surely crash.
 *
 *      2. If you call a function that has 'error_num_ptr' as an argument, then
 *         after the function returns, you should first check whether the value
 *         of '*error_num_ptr' is 'SFUL_SUCCESS' or not. If it is not
 *         'SFUL_SUCCESS', then this means that some error has happened in the
 *         called function, and so in this case, there is no point in
 *         checking/using the return value of the called function (in case there
 *         is some return value). The return value of the called function (in
 *         case there is some return value) will make sense only when the value
 *         of '*error_num_ptr' is 'SFUL_SUCCESS'.
 *
 *      3. If the value of '*error_num_ptr' is not 'SFUL_SUCCESS', then the
 *         value of '*error_num_ptr' will be a negative error number that will
 *         signify which particular error has happened.
 */

/*
 * sful_convert_err_num_to_err_str():
 *
 * Description:
 *
 *      Function sful_convert_err_num_to_err_str() returns an error string
 *      corresponding to the given error number.
 */
const char *sful_convert_err_num_to_err_str(int error_num);

/*
 * sful_get_input_from_stdin_and_clear_stdin():
 *
 * Description:
 *
 *      Function sful_get_input_from_stdin_and_clear_stdin() reads at most
 *      'size - 1' characters from stdin, and stores them in 'str'. Then, 'str'
 *      is null terminated by appending the null terminating character ('\0') to
 *      'str'.
 *
 *      If argument 'clear_stdin' is greater than 0, then stdin is cleared by
 *      this function before returning in all cases (both successful and error
 *      cases). Clearing stdin means that all the remaining characters in stdin
 *      are read and discarded, and there are no characters left in stdin (stdin
 *      becomes empty).
 *
 *      You should always set 'clear_stdin' to a value greater than 0 so that
 *      stdin is cleared of remaining characters, and you don't get old input
 *      when stdin is read the next time.
 *
 * Return values:
 *
 *      On success, 'SFUL_SUCCESS' is returned, and 'str' contains the read
 *      characters.
 *
 *      On error, the appropriate negative error number is returned, and in this
 *      case, the characters in 'str' shouldn't be used. The error conditions
 *      are described below.
 *
 * Error conditions:
 *
 *      If 'str' is NULL, then it is an error, and nothing is read from stdin,
 *      and a negative error number is returned.
 *
 *      If 'size' is less than 1 or greater than
 *      'SFUL_MAX_INPUT_SIZE_ALLOWED_FROM_STDIN', then it is an error, and
 *      nothing is read from stdin, and a negative error number is returned.
 *
 *      If the user inputs more than 'size - 1' characters, then this function
 *      treats this as an error, and then it memsets all the characters it
 *      stored in 'str' to 0, and then it returns the negative error number
 *      'SFUL_USER_GAVE_MORE_INPUT_THAN_ASKED_FOR'.
 */
int sful_get_input_from_stdin_and_clear_stdin(char *str, int size,
                                              int clear_stdin);

/*
 * sful_clear_stdin():
 *
 * Description:
 *
 *      Function sful_clear_stdin() reads and discards all characters from
 *      stdin. When this function returns then stdin is empty, it doesn't
 *      contain any characters.
 *
 *      This function is not thread-safe because it makes stdin non-blocking
 *      for some time.
 *
 * Return value:
 *
 *      This function doesn't return anything.
 */
void sful_clear_stdin(void);

/*
 * sful_wait_for_user_to_press_enter():
 *
 * Description:
 *
 *      Function sful_wait_for_user_to_press_enter() blocks until the user
 *      presses the "ENTER" key. After the user has pressed the "ENTER" key,
 *      this function clears stdin (by calling sful_clear_stdin()), and then
 *      this function returns.
 *
 * Return value:
 *
 *      This function doesn't return anything.
 */
void sful_wait_for_user_to_press_enter(void);

/*
 * sful_get_integer_from_user_within_range_inclusive():
 *
 * Description:
 *
 *      Function sful_get_integer_from_user_within_range_inclusive() prints the
 *      message given in the argument 'msg_for_user' and waits for an input from
 *      the user. If the input is an integer within the range 'min' - 'max'
 *      (both 'min' and 'max' inclusive) then this function returns the inputted
 *      integer else it prints the message again and waits for the user input
 *      again and this goes on in an endless cycle until the user inputs an
 *      integer within 'min' - 'max' range (both 'min' and 'max' inclusive) or
 *      if an error happens.
 *
 * Return values:
 *
 *      On success, '*error_num_ptr' is set to 'SFUL_SUCCESS' and an integer is
 *      returned which is in the range 'min' - 'max' (both 'min' and 'max'
 *      inclusive).
 *
 *      On error, '*error_num_ptr' is set to the appropriate negative error
 *      number and, in this case, the value returned by this function shouldn't
 *      be used.
 */
int sful_get_integer_from_user_within_range_inclusive(const char *msg_for_user,
                                         int min, int max, int *error_num_ptr);

/*
 * sful_get_y_or_n_from_user():
 *
 * Description:
 *
 *      Function sful_get_y_or_n_from_user() prints the message given in the
 *      argument 'msg_for_user' and waits for an input from the user. If the
 *      input is either 'y' or 'n' (without quotes) ('y' means yes and 'n' means
 *      no), then this function returns the inputted value else it prints the
 *      message again and waits for the user input again and this goes on in an
 *      endless cycle until the user inputs either 'y' or 'n' (without quotes)
 *      or an error happens.
 *
 * Return values:
 *
 *      On success, '*error_num_ptr' is set to 'SFUL_SUCCESS' and the user input
 *      ('y' or 'n' (without quotes)) is returned.
 *
 *      On error, '*error_num_ptr' is set to the appropriate negative error
 *      number and, in this case, the value returned by this function shouldn't
 *      be used.
 */
char sful_get_y_or_n_from_user(const char *msg_for_user, int *error_num_ptr);

/*
 * sful_is_str_allowed_integer():
 *
 *      For this function (sful_is_str_allowed_integer()), the allowed integer
 *      is from 'SFUL_INT_MIN' to 'SFUL_INT_MAX'. To understand more about these
 *      limits, please see the documentation of 'SFUL_INTEGER_STR_SIZE' above.
 *
 *      This function expects only numeric characters in 'str' and optionally a
 *      leading '+' or '-' character.
 *
 *      This function returns 'SFUL_SUCCESS' only when all of the following
 *      conditions are met:
 *
 *              ** 'str' is not null.
 *              ** The first character of 'str' is not the null terminating
 *                 character (means 'str' is not an empty string).
 *              ** Length of 'str' is less than 'SFUL_INTEGER_STR_SIZE'.
 *              ** 'str' contains only numeric characters and optionally a
 *                 leading '+' or '-' character.
 *
 *      If all of the above conditions are not met, then this function returns
 *      an appropriate negative error number.
 */
int sful_is_str_allowed_integer(const char *str);

#endif

-----------------------------------
compile_stdin_functions_library.sh
-----------------------------------

#!/bin/bash

set -x

rm -f stdin_functions_library.o

gcc -c -Wall -Werror -Wextra -Wundef -Wunreachable-code -Winit-self
-Wparentheses -Wconversion -Wsign-conversion -Wsign-compare
-Werror-implicit-function-declaration -Wmissing-prototypes
-Wmissing-declarations -Wno-unused-parameter -Wformat-security
stdin_functions_library.c

----

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ