Una robetta scolastica di poco conto potrebbe essere questa:
io.h
/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
/* 
 * File:   io.h
 * Author: debian
 *
 * Created on 29 luglio 2017, 11.21
 */
#ifndef IO_H
#define IO_H
#define IO_DEBUG
/* Tipo booleano definito per il C89*/
typedef enum {FALSE, TRUE} boolean;
/* Struttura per la memorizzazione dell'input*/
typedef struct
{
    char *mem;
    int size;
}
io_buff;
/*Legge una linea da stdin*/
boolean readline(io_buff *line);
#endif /* IO_H */
readline.c
/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
#include <stdio.h>
#include <stdlib.h>
#include "io.h"
#define READLINE_DEBUG
/*
** Legge una riga da stdin come da manuale di fgets (man fgets).
** Accetta come parametro *line, dove line->size e' la dimensione del vettore,
** mem è un puntatore al vettore stesso.
** readline (nome infelice poiche' gia' esistente in unix) restituisce TRUE in
** caso di successo, FALSE diversamente. (Attenzione a *size* ;) )
*/
boolean readline(io_buff *line)
{
    if(NULL == line || NULL == line->mem)
    {
#if defined(IO_DEBUG) || defined(READLINE_DEBUG)
        (void) fputs("**********DEBUG**********\n",stderr);
        (void) fputs("Errore in readline.c: NULL pointer non previsto!\n", stderr);
        (void) fputs("boolean readline(io_buff *line)\n", stderr);
        (void) fputs("                 ~~~~~~~~^^^^^\n", stderr);
        if(NULL == line)
        {
            (void) fputs("(iobuff) *line = NULL\n", stderr);
        }
        else
        {
            (void) fputs("(iobuff) line->mem = NULL\n", stderr);
        }
        (void) fputs("**********FINE DEBUG**********\n",stderr);
#endif
        return (FALSE);
    }
    /*Legge finalmente la stringa*/
    if(NULL == fgets(line->mem, line->size, stdin))
    {
#if defined(IO_DEBUG) || defined(READLINE_DEBUG)
        (void) fputs("**********DEBUG**********\n",stderr);
        (void) fputs("Errore in readline.c: fgets ha restituito NULL!\n", stderr);
        (void) fputs("**********FINE DEBUG**********\n",stderr);
#endif
        return (FALSE);
    }
    return (TRUE);
}
main.c
/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
/* 
 * File:   main.c
 * Author: debian
 *
 * Created on 29 luglio 2017, 11.21
 */
#include <stdio.h>
#include <stdlib.h>
#include "io.h"
#define SIZE_MAX (128)
/*
 * Driver per la lettura di stringhe da stdin.
 * Questo non è un test!
 */
int main(void)
{
    char buff[SIZE_MAX];
    io_buff line;
    boolean success;
    
    line.mem = buff;
    line.size = SIZE_MAX;
    
    (void) fputs("Inserisci una stinga: ", stdout);
    success = readline(&line);
    if(FALSE == success)
    {
        (void) fputs("Errore: impossibile leggere la stringa!\n", stderr);
        /* Error recovering qui, ma per semplificare usciamo*/
        return (EXIT_FAILURE);
    }
    (void) fputs("Hai inserito: ", stdout);
    (void) fputs(buff, stdout);
    return (EXIT_SUCCESS);
}
Rifletti su 
size comunque. Il codice proposto, mi ripeto, va bene per un compito in classe ma non oltre, anche se passa il controllo con SPLint. Sicuramente non è conforme al MISRA/C.