Alcuni commenti in ordine sparso:
1)Questa riga di codice, come altre sparse nel tuo programma:
codice:
if(((word[0]=='I' && n!=word[2]-'0' && word[1]!='\0') || (word[0]=='A' && word[1]!='\0') || (word[0]!='I') || (word[0]!='A')))
merita qualche parentesi in più per evitare che le precedenze tra gli operatori prendano il sopravvento sulla tua volontà.

2)Non capisco cosa volevi fare in questa funzione:
codice:
void insert_nodo(list_pointer *testa, list_pointer temp, int *linea)
{
    list_pointer aux;

    if(*testa)
    {
        (*testa)->link=temp;
        temp->link=NULL;
    }
    else
    {
        temp->link=NULL;
        (*testa)=temp;
        return;
    }

    aux=*testa;

    while(aux)
    {
        *linea++;
        aux=aux->link;
    } /* O(n^2) */
}
soprattutto qui:
codice:
    aux=*testa;

    while(aux)
    {
        *linea++;
        aux=aux->link;
    }
3)Infine mi riguarderei tutti gli if. Ad esempio:

codice:
            case 'I':
                if(word[1]=='\0')
                {
                    inserisci(&testa,n,word);
                    linea++;
                }

                if(word[1]==' ' && word[3]=='\0')
                {
                    n=word[2]-'0';
                    inserisci(&testa,n,word);
                    linea++;
                }
                else
                {
                    inserisci(&testa,n,word);
                    linea++;
                }
                salva_file(testa);
Poiché se word[1] è uguale a '\0' il blocco
codice:
                {
                    inserisci(&testa,n,word);
                    linea++;
                }
può, facilmente, essere eseguito due volte: una volta quando è vero il primo if e un'altra volta quando fallisce il secondo if. Questo tipo di insufficiente valutazione dei possibili casi di input rende il tuo programma non corretto e/o poco robusto. Essendo la robustezza, nel caso del software, la capacità di avere un comportamento predicibile anche in presenza di valori di ingresso diversi da quelli attesi.

Prova ad adottare la tecnica degli antichi romani: "Divide et impera". Ovvero scomponi il problema in sotto problemi e risolvili uno per uno e poi rimonta tutto insieme. Parti la gestione delle liste. Creati delle funzioni di inserimento e cancellazione che funzionino a "prova di bomba". Poi, sviluppa la leggifile e poi vai avanti. Vedrai che verrà un bel programmino