First, fgets() is not a system call, so you're not going to catch it with ptrace. What you are going to catch is sys_read() or similar system call. Even more so, the actual sys_read() may actually be invoked with different buffer and length arguments than those passed to original fgets() because of I/O caching in stdio.
Second, to establish reliably, which registers to check you need to know the exact ABI you're using. For example, on ARM/EABI the sys_read() call will expect the buffer pointer in register "r1" (with register "r0" holding the first argument, e.g. file descriptor and register "r2" holding the length). On x86 it will be ebx/ecx/edx combo; on amd64 - rdi/rsi/rdx.
If you actually want to trace the effects of higher level functions (as opposed to system calls), you will need to dig deep into the debugging information produced by the compiler, because it's more or less the only way to do such things (you can try using the libelf library from elfutils, just like ltrace
utility does). You will actually have to programmatically set breakpoints in proper places and then rely on debugging info to deduce the variable layout on stack (to get to the stack allocated buffer).
Consider using the source of an ltrace
utility for a working example:
By the way, if you're using a sufficiently new kernel, you may benefit from using the 2 new system calls: process_vm_readv
and process_vm_writev
which can manipulate remote process memory "in bulk", given only the target PID and address (this is much more convenient approach than ptrace PEEK and POKE).
http://man7.org/linux/man-pages/man2/process_vm_readv.2.html