Shuffle a deck of cards and draw 2
rand_ranged_inclusive(a, b) is a surprisingly long function name, for how little information it communicates to the reader. I have frequently seen versions of this function named randint(a, b) or randint0(b) — but where the possible outputs are between 0 inclusive and b exclusive!
Using &quot;half-open ranges&quot; like this has huge advantages in C, because C uses half-open ranges for everything else. To pick a random element from an array, you want randint0(NELEM(a)). To pick a random character from a string, you want randint0(strlen(s)). And so on.
if (min &gt; max)
    SWAP_INT(min, max);

Here and throughout, I strongly recommend curly-bracing all your control flow, including if and for bodies which are currently only one line long. These braces may one day save you from a goto fail bug.
Also, I think it's un-idiomatic that you are going out of your way to produce well-defined behavior for rand_ranged_inclusive(6, 1). I claim that that kind of input clearly indicates a bug in the caller, and you should be using assert(min &lt;= max) here. (Or, if you switch to half-open ranges, assert(min &lt; max).)
Your choice to handle rand_ranged_inclusive(6, 1) becomes even weirder when you consider that you do not handle seemingly valid parameters such as rand_ranged_inclusive(-10, INT_MAX). (The caller who tries that gets integer overflow and undefined behavior.)
int range = max-min+1;
int biased_interval = RAND_MAX%(range-1);

The use of RAND_MAX % ... instead of (RAND_MAX+1) % ... is an immediate red flag for me, after our discussion of half-open ranges. (RAND_MAX is an endpoint-which-is-included, similar to INT_MAX.) All these +1 and -1 would go away if you switched to half-open ranges. I bet they're hiding some off-by-one errors. Let's trace through a sample input.
Suppose min=1, max=6, RAND_MAX=10. (This is legitimately the first input I traced.) Then range=6, biased_interval=0... so the do-while loop runs only once before dropping out... but you end up choosing 1-4 twice as often as 5-6.
Did you test this code at all?  How did you test it?
I think the algorithm you want here is more like
int range = max - min + 1;
int discard_top_k = ((RAND_MAX % range) + 1) % range;
int real_max = RAND_MAX - discard_top_k;
do {
    x = rand();
} while (x &gt; real_max);


int j = rand_ranged_inclusive(i, len-1);

Your Fisher-Yates shuffle looks correct; but notice again that you're having to add a -1 to fix up the lack of half-open ranges in your random-number code.

if (c &lt; 0 || c &gt; 52)
    printf(&quot;Joker\n&quot;);

Is this situation possible? If it's supposed to be impossible, you should assert(0 &lt;= c &amp;&amp; c &lt; 52) (hey look! half-open ranges!)
Also notice the off-by-one error in your code because of (say it with me) the lack of half-open ranges.

char const *argv[]

I agree with Linus on this one. Prefer
const char **argv