Here's what I normally use. If I were doing it again today, I'd probably do it a bit differently, but it works well enough that I haven't really had any reason to look at it for years (in fact, I'm pretty sure the last time I did anything to it was adding "cmd" to the list of extensions when I ported it from DOS to Win32...
// Which.c:
#include <io.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char *extensions[] = { "com", "exe", "bat", "cmd", NULL };
int is_exe(char *ext) {
    int i;
    for ( i = 0; extensions[i]; i++)
        if ( 0 == stricmp(ext, extensions[i] ) )
            return 1;
    return 0;
}
int main(int argc, char **argv) {
    char path[FILENAME_MAX];
    char buffer[FILENAME_MAX];
    char *path_var;
    char *ext;
    char *dir;
    int i;
    if (argc != 2) { 
        fprintf(stderr, "Usage: which <filename>\n");
        return 1;
    }
/* First try to find file name as-is.
 */
    if ( 0 == access(argv[1], 0)) {
        printf("\n%s", argv[1]);
        return 0;
    }
/* Okay, it wasn't found.  See if it had an extension, and if not, try
 * adding the usual ones...
 */
    ext = strrchr(argv[1], '.' );
    if ( 0 == ext++ || !is_exe(ext) ) {
        for ( i = 0; extensions[i]; i++) {
            sprintf(buffer, "%s.%s", argv[1], extensions[i]);
            if ( 0 == access(buffer, 0)) {
                printf("\n%s", buffer);
                return 0;
            }
        }
        if ( NULL == (path_var=getenv("PATH")))
            return 1;
        dir = strtok(path_var, ";");
        do {
            for ( i = 0; extensions[i]; i++) {
                sprintf(buffer, "%s\\%s.%s", dir, argv[1], extensions[i]);
                if ( 0 == access( buffer, 0)) {
                    printf("\n%s", buffer);
                    return 0;
                }
            }
        } while ( NULL != ( dir = strtok(NULL, ";")));
    }
    else {
        if ( NULL == (path_var=getenv("PATH")))
            return 1;
        dir = strtok(path_var, ";");
        do {
            sprintf(buffer, "%s\\%s", dir, argv[1]);
            if ( 0 == access( buffer, 0)) {
                printf("\n%s", buffer);
                return 0;
            }
        } while ( NULL != ( dir = strtok(NULL, ";")));
    }
    return 1;
}