I wrote an example program about UNIX semaphores, where a process and its child lock/unlock the same semaphore. I would appreciate your feedback about what I could improve in my C style. Generally I feel that the program flow is hard to read because of all those error checks, but I didn't find a better way to write it. It's also breaking the rule of "one vertical screen maximum per function" but I don't see a logical way to split it into functions.

#include &lt;semaphore.h&gt;
#include &lt;stdio.h&gt;
#include &lt;errno.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;unistd.h&gt;
#include &lt;sys/types.h&gt;
#include &lt;sys/stat.h&gt;
#include &lt;fcntl.h&gt;
#include &lt;sys/mman.h&gt;

int main(void)
{ 
  /* place semaphore in shared memory */
  sem_t *sema = mmap(NULL, sizeof(sema), 
          PROT_READ |PROT_WRITE,MAP_SHARED|MAP_ANONYMOUS, -1, 0);
  if (!sema) {
    perror("Out of memory");
    exit(EXIT_FAILURE);
  }

  /* create, initialize semaphore */
  if (sem_init(sema, 1, 0) &lt; 0) {
    perror("semaphore initilization");
    exit(EXIT_FAILURE);
  }

  int i, nloop=10;
  int ret = fork();
  if (ret &lt; 0) {
    perror("fork failed");
    exit(EXIT_FAILURE);
  }

  if (ret == 0) { 
    /* child process*/
    for (i = 0; i &lt; nloop; i++) {
      printf("child unlocks semaphore: %d\n", i);
      sem_post(sema);
      sleep(1);
    }
    if (munmap(sema, sizeof(sema)) &lt; 0) {
      perror("munmap failed");
      exit(EXIT_FAILURE);
    }
    exit(EXIT_SUCCESS);
  }

  if (ret &gt; 0) {
    /* back to parent process */
    for (i = 0; i &lt; nloop; i++) {
      printf("parent starts waiting: %d\n", i);
      sem_wait(sema);
      printf("parent finished waiting: %d\n", i);
    }
    if (sem_destroy(sema) &lt; 0) {
      perror("sem_destroy failed");
      exit(EXIT_FAILURE);
    }
    if (munmap(sema, sizeof(sema)) &lt; 0) {
      perror("munmap failed");
      exit(EXIT_FAILURE);
    }
    exit(EXIT_SUCCESS);
  }
}



Question: Prove $[A,B^n] = nB^{n-1}[A,B]$
Answer: It seems that the question (v1) is caused by the fact that there are two different notions of the commutator: 


One for group theory: 
$$\tag{1} [A,B] ~:=~ ABA^{-1}B^{-1}$$ 
(or sometimes $[A,B] := A^{-1}B^{-1}AB$, depending on convention), which is relatively seldom used in physics.
One for rings/associative algebras: 
$$\tag{2} [A,B]:=AB-BA,$$ 
which is the definition usually used in physics. (This latter definition (2) generalizes to a supercommutator in superalgebras.)


The identity 

$$\tag{*}  [A,B^n] ~=~ nB^{n-1}[A,B]$$ 

holds in the latter sense (2), if $[[A,B],B]=0$. (It is not necessary to demand $[A,[A,B]]=0$.) More generally, for a sufficiently well-behaved function $f$, we have

$$\tag{**} [A,f(B)] ~=~ f^{\prime}(B)[A,B], $$

if $[[A,B],B]=0$. 

The group commutator (1) is dimensionless, which (among other things) makes the identity (*) unnatural to demand for group commutators.