5746889 [rkeene@sledge /home/rkeene/projects/rivet-cgi/bin]$ cat -n rivet.c
  1 #include <tcl.h>
  2 #include <unistd.h>
  3 #include <stdlib.h>
  4 #include <stdio.h>
  5 #include <string.h>
  6 
  7 int main(int argc, char **argv) {
  8     Tcl_Interp *interp;
  9     char newpath_str[8192], parse_str[8192], execdir_str[8192], putenv_buf[8192];
 10     char linkinfo[8192], *tmp = NULL;
 11     char *scpfile = NULL, *pt_env = NULL, *pathinfo = NULL;
 12     char *path = NULL;
 13     size_t chklen;
 14     int chkval;
 15     long bytes_to_copy;
 16     CONST char *chkstr;
 17     CONST char *orig_errmsg, *err_errmsg;
 18 
 19     /*
 20      * Verify we were called correctly.
 21      */
 22     if (argc == 0) {
 23         fprintf(stderr, "Wrong number of arguments, aborting.\n");
 24         return(EXIT_FAILURE);
 25     }
 26 
 27     pt_env = getenv("PATH_TRANSLATED");
 28     if (pt_env) {
 29         scpfile = strdup(pt_env);
 30     }
 31 
 32     /*
 33      * Create an interpreter or bail out.
 34      */
 35     interp = Tcl_CreateInterp();
 36     if (!interp) {
 37         fprintf(stderr, "Could not create interpreter, aborting.\n");
 38         return(EXIT_FAILURE);
 39     }
 40 
 41     /*
 42      * Perform standard Tcl initialization.
 43      */
 44     chkval = Tcl_Init(interp);
 45 
 46     /*
 47      * Update the "auto_path" variable
 48      *   -- Determine the path to the package
 49      *      -- Determine the path to ourselves
 50      */
 51     execdir_str[0] = '\0';
 52 
 53     /*
 54      * If no argv[0] is specified, give up trying to find ourselves.
 55      */
 56     if (argv[0] == NULL) {
 57         fprintf(stderr, "Could not locate myself, aborting. (argv[0] = null)\n");
 58         return(EXIT_FAILURE);
 59     }
 60 
 61     /*
 62      * Ensure we have enough buffer room to hold the value
 63      */
 64     if (strlen(argv[0]) >= sizeof(execdir_str)) {
 65         fprintf(stderr, "Could not locate myself, aborting. (argv[0] too big)\n");
 66         return(EXIT_FAILURE);
 67     }
 68 
 69     /*
 70      * Copy the value into our buffer
 71      */
 72     strcpy(execdir_str, argv[0]);
 73 
 74 #ifdef __WIN32__
 75     {
 76         char *p;
 77         p = execdir_str;
 78 
 79         while (*p) {
 80             if (*p == '\\') {
 81                 *p = '/';
 82             }
 83 
 84             p++;
 85         }
 86     }
 87 #endif
 88 
 89 #ifdef LINUX
 90     /*
 91      * Under Linux we can find ourselves via "/proc/PID/exe"
 92      */
 93     snprintf(execdir_str, sizeof(execdir_str), "/proc/%i/exe", getpid());
 94     execdir_str[sizeof(execdir_str) - 1] = '\0';
 95 #else
 96     /*
 97      * If there was no path delimiters in the passed argv[0] assume
 98      * the executable can be found in the path.
 99      */
100     tmp = strrchr(execdir_str, '/');
101     if (!tmp) {
102         path = getenv("PATH");
103         if (path) {
104             path = strdup(path);
105         }
106 
107         if (path) {
108             for (tmp = strtok(path, ":"); tmp; tmp = strtok(NULL, ":")) {
109                 chklen = snprintf(execdir_str, sizeof(execdir_str), "%s/%s", tmp, argv[0]);
110                 if (chklen >= sizeof(execdir_str)) {
111                     execdir_str[0] = '\0';
112                     continue;
113                 }
114 
115                 if (access(execdir_str, X_OK) == 0) {
116                     break;
117                 }
118 
119                 execdir_str[0] = '\0';
120             }
121         }
122     }
123 #endif
124 
125     if (execdir_str[0] == '\0') {
126         fprintf(stderr, "Could not locate myself, aborting. (failed to perform)\n");
127         return(EXIT_FAILURE);
128     }
129 
130     if (access(execdir_str, X_OK) != 0) {
131         fprintf(stderr, "Could not locate myself, aborting. (not executable)\n");
132         return(EXIT_FAILURE);
133     }
134 
135     /*
136      * Resolve all symlinks whose target is the executable itself.
137      */
138     while (1) {
139 #ifndef __WIN32__
140         chkval = readlink(execdir_str, linkinfo, sizeof(linkinfo));
141 #else
142         chkval = -1;
143 #endif
144 
145         if (chkval == -1) {
146             break;
147         }
148 
149         if ((size_t) chkval >= sizeof(linkinfo)) {
150             fprintf(stderr, "Could not locate myself, aborting. (linkname too big)\n");
151             return(EXIT_FAILURE);
152         }
153 
154         linkinfo[chkval] = '\0';
155 
156         tmp = strrchr(execdir_str, '/');
157         if (tmp && linkinfo[0] != '/') {
158             tmp++;
159             *tmp = '\0';
160             bytes_to_copy = sizeof(execdir_str) - strlen(execdir_str) - 1;
161 
162             if (bytes_to_copy <= 0) {
163                 fprintf(stderr, "Could not locate myself, aborting. (no bytes to copy)\n");
164                 return(EXIT_FAILURE);
165             }
166 
167             strncat(execdir_str, linkinfo, bytes_to_copy);
168         } else {
169             strcpy(execdir_str, linkinfo);
170         }
171     }
172 
173     /*
174      * Ensure that this target is real, and executable.
175      */
176     if (access(execdir_str, X_OK) != 0) {
177         fprintf(stderr, "Could not locate myself, aborting. (no access to execdir=\"%s\")\n", execdir_str);
178         return(EXIT_FAILURE);
179     }
180 
181     /*
182      * Now that we have resolved the symbolic links, remove the filename.
183      */
184     tmp = strrchr(execdir_str, '/');
185     if (tmp) {
186         *tmp = '\0';
187     }
188 
189     /*
190      *   -- Construct the path to the package
191      */
192     chklen = snprintf(newpath_str, sizeof(newpath_str), "%s/../packages/tclrivet/", execdir_str);
193     if (chklen >= sizeof(newpath_str)) {
194         fprintf(stderr, "Could not construct pathname, aborting.\n");
195         return(EXIT_FAILURE);
196     }
197 
198     /*
199      *   -- Update the "auto_path" variable
200      */
201     chkstr = Tcl_SetVar(interp, "auto_path", newpath_str, TCL_APPEND_VALUE | TCL_LIST_ELEMENT);
202     if (chkstr == NULL) {
203         fprintf(stderr, "Could update auto_path, aborting.\n");
204         return(EXIT_FAILURE);
205     }
206 
207     /*
208      * Free allocated memory.
209      */
210     if (path) {
211         free(path);
212     }
213 
214     /*
215      * Load the "tclrivet" package
216      */
217     chkval = Tcl_Eval(interp, "package require tclrivet");
218     if (chkval != TCL_OK) {
219         fprintf(stderr, "Could not evaluate package command, aborting.\n");
220         return(EXIT_FAILURE);
221     }
222 
223     /*
224      * Ensure that the script file is properly defined and accessible.
225      */
226     /*
227      *   -- Verify that the scpfile has even been defined
228      */
229     if (scpfile == NULL) {
230         fprintf(stderr, "Could not determine executable script, aborting.\n");
231         return(EXIT_FAILURE);
232     }
233 
234     /*
235      *   -- If the "scpfile" doesn't exist, see if it's being MultiView'd/PATH_INFO processed
236      */
237     pathinfo = strdup(scpfile);
238     tmp = NULL;
239     while (access(scpfile, F_OK) != 0) {
240         tmp = strrchr(scpfile, '/');
241         if (!tmp) {
242             break;
243         }
244         *tmp = '\0';
245     }
246     if (tmp) {
247         if (tmp > scpfile) {
248             pathinfo += tmp - scpfile;
249             snprintf(putenv_buf, sizeof(putenv_buf), "PATH_INFO=%s", pathinfo);
250             putenv_buf[sizeof(putenv_buf) - 1] = '\0';
251             putenv(putenv_buf);
252         }
253     }
254 
255     if (access(scpfile, F_OK) != 0 || strlen(scpfile) < 2) {
256         fprintf(stderr, "Could not access executable script, aborting. (scp=\"%s\")\n", scpfile);
257         return(EXIT_FAILURE);
258     }
259 
260     /*
261      * Change directories to the script root
262      */
263     path = strdup(scpfile);
264     if (path) {
265         tmp = strrchr(path, '/');
266         if (tmp) {
267             *tmp = '\0';
268 
269             chdir(path);
270         }
271 
272         free(path);
273     }
274 
275     /*
276      * Hand off execution to the script passed in scpfile
277      *    -- Construct the command string
278      */
279     chklen = snprintf(parse_str, sizeof(parse_str), "parse \"%s\"", scpfile);
280     if (chklen >= sizeof(parse_str)) {
281         fprintf(stderr, "Could not construct parse command, aborting.\n");
282         return(EXIT_FAILURE);
283     }
284 
285     /*
286      *    -- Evaluate the command string
287      */
288     chkval = Tcl_Eval(interp, parse_str);
289     if (chkval != TCL_OK) {
290         orig_errmsg = Tcl_GetVar(interp, "errorInfo", TCL_GLOBAL_ONLY);
291         if (orig_errmsg) {
292             orig_errmsg = strdup(orig_errmsg);
293         }
294 
295         /*
296          * Attempt to generate an error page.
297          */
298         chkval = Tcl_Eval(interp, "rivet_error");
299         if (chkval != TCL_OK) {
300             fprintf(stderr, "Error evaluating parse command: %s\n", orig_errmsg);
301             err_errmsg = Tcl_GetVar(interp, "errorInfo", TCL_GLOBAL_ONLY);
302             fprintf(stderr, "Additionally, an error occured while generating the error page: %s\n", err_errmsg);
303         }
304 
305         return(EXIT_FAILURE);
306     }
307 
308     /*
309      * Call "rivet_flush" and ignore any errors.
310      */
311     Tcl_Eval(interp, "rivet_flush");
312 
313     /*
314      * Done
315      */
316     return(EXIT_SUCCESS);
317 }
5746890 [rkeene@sledge /home/rkeene/projects/rivet-cgi/bin]$

Click here to go back to the directory listing.
Click here to download this file.
last modified: 2008-10-05 17:36:46