[email from 2000-08-17 01:33:37 CDT (Aug Thu) 966494017] Hi, For the web, you can write a certain amount of CGI code in /bin/sh (or any of the other interpreters that can at least handle CGI's somewhat strange input methods), but the workhorse is typically PERL, and most examples will be in that language. C will work just as well as PERL, however, if you don't know the other yet. Note that the HTML output you see in a CGI-generated webpage is -not- the PERL or C or sh code, just the script's HTML output. If you want to do C-based CGI, then just write a program that coughs up the correct initial two lines giving the document type, and use puts() or the like to output HTML. Play with that for a while (it lets you do a whole lot, right there), then find out how the GET and POST actions send their data. I seem to remember that one uses environment variables mostly, so getenv() would be a key function, and the other provides and input stream on stdin of the data from the form, which can be read into a dynamically-allocated buffer with even just getchar(). After that, parsing the input string is a little weird, since you usually want to put the results into a dynamically-allocated vector (remember malloc?) of structs, each with two strings for a name/value pair. Write a function to scan these vector for a named string, and the rest is easy again. So there. :-) ---------------------------------------------------------------------------- C. Alexander North-Keys http://www.talisman.org/~erlkonig/ ------------------------------------------ ^*^ ----------------------------- [when questioned about the following....] | After that, parsing the input string is a little weird, since you usually | want to put the results (got that part) into a"dynamically-allocated vector | (remember malloc?) of structs, each with two strings for a name/value | pair." | | Write a function to scan these vector for a named string, and the rest is | easy again. i.e. typedef struct _NameValuePair { char *name; char *value; } NameValuePair; NameValuePair *pairs; - followed by various functions to fiddle with these, eventually allowing you to do stuff like: char *login = 0, *passwd = 0; if( (login = NvpLookup(pairs, "login")) && (passwd = NvpLookup(pairs, "password"))) { puts("

Login and Password read

"); printf("
\n
login:
%s
password
%s\n", login, password); } else { puts("

Login and/or Password missing

"); } - you could also build functions around a linked list: typedef struct _NameValuePair { struct _NameValuePair *next; /* yes, the _Thing is finally non-optional */ char *name; char *value; } NameValuePair; with functions like NameValuePair *NvpNew(char *name, char *value); /* returns address of new Nvp, with strdup()ed copies of name and value */ NameValuePair *NvpPush(NameValuePair *list, NameValuePair *addme); /* returns longer list, new element first */ const char *NvpSearchByName(NameValuePair *list, const char *name); /* returns pointer to value, or null */ sample implementations: /* free full or partially-complete obj */ NameValuePair *NvpDelete(NameValuePair *doomed) { if(doomed) { if(doomed->name) free(doomed->name); if(doomed->value) free(doomed->value); free(doomed); } return 0; } NameValuePair *NvpNew(char *name, char *value) { NameValuePair *created = (NameValuePair*)malloc(sizeof(NameValuePair)); if(created && (created->name = strdup(name)) && (created->value = strdup(value))) { /* yay, it worked */ } else { perror("NvpNew - malloc/strdup"); created = NvpDelete(created); } return created; } ---------------------------------------------------------------------------- C. Alexander North-Keys http://www.talisman.org/~erlkonig/ Talisman Research / Unix Analyst erlkonig@talisman.org ------------------------------------------ ^*^ -----------------------------