(long *)(host->h_addr) means to interpret host->h_addr as a pointer to a long. This is not very portable, but presumably a long is 32 bits long on the system this was written for.
The additional star in *(...) dereferences what is now a long for assignment. This effectively copies all four bytes of the original char array into the single long value addr.sin_addr.s_addr. Compare to (long)(*host->h_addr), which would only copy the first char element.
This technique is extremely unportable. It assumes both the size and endianness of the long type. You might be tempted to take a hint from the fact that s_addr is a uint32 and do:
addr.sin_addr.s_addr = *(uint32_t *)(host->h_addr);
This is not really any better because the endianness is still undermined. Also,uint32_t is guaranteed to hold at least 32 bits. It can be any larger number of bits, which would invoke undefined behavior when you tried to read unallocated memory with the copy (imagine copying your 32 bits of char data as a 64-bit integer).
There are two options going forward:
If your char array is already in the correct byte order (i.e., you don't care if h_addr[0] represents the highest or lowest byte of a local uint32_t), use memcpy:
memcpy(&(addr.sin_addr.s_addr), host->h_addr, 4);
This is likely to be the approach you need. If, on the other hand you want h_addr[0] to always end up in the highest byte, you need to respect the endianness of your system:
addr.sin_addr.s_addr = (host->h_addr[0] << 24) + (host->h_addr[1] << 16) + (host->h_addr[2] << 8) + (host->h_addr[3]);
There probably need to be some casts to uint32_t along the way there.