mirror of the now-defunct rocklinux.org
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

492 lines
12 KiB

  1. /*
  2. * --- ROCK-COPYRIGHT-NOTE-BEGIN ---
  3. *
  4. * This copyright note is auto-generated by ./scripts/Create-CopyPatch.
  5. * Please add additional copyright information _after_ the line containing
  6. * the ROCK-COPYRIGHT-NOTE-END tag. Otherwise it might get removed by
  7. * the ./scripts/Create-CopyPatch script. Do not edit this copyright text!
  8. *
  9. * ROCK Linux: rock-src/misc/tools-source/cmd_wrapper.c
  10. * ROCK Linux is Copyright (C) 1998 - 2004 Clifford Wolf
  11. *
  12. * This program is free software; you can redistribute it and/or modify
  13. * it under the terms of the GNU General Public License as published by
  14. * the Free Software Foundation; either version 2 of the License, or
  15. * (at your option) any later version. A copy of the GNU General Public
  16. * License can be found at Documentation/COPYING.
  17. *
  18. * Many people helped and are helping developing ROCK Linux. Please
  19. * have a look at http://www.rocklinux.org/ and the Documentation/TEAM
  20. * file for details.
  21. *
  22. * --- ROCK-COPYRIGHT-NOTE-END ---
  23. *
  24. * Generic command wrapper.
  25. *
  26. * Recognised Variables:
  27. *
  28. * prefix_WRAPPER_MYPATH "/path/to/binary"
  29. * prefix_WRAPPER_LOGFILE ".cmd_wrapper_log"
  30. *
  31. * prefix_WRAPPER_DEBUG 0
  32. * prefix_WRAPPER_BYPASS 0
  33. *
  34. * prefix_WRAPPER_APPEND_PO "-1st-opt -2nd-opt"
  35. *
  36. * prefix_WRAPPER_OTHERS "wrapper1:wrapper2:..."
  37. *
  38. * prefix_WRAPPER_INSERT "-1st-opt -2nd-opt"
  39. * prefix_WRAPPER_REMOVE "-del-this-opt -this-also [!-]*"
  40. * prefix_WRAPPER_APPEND "-last-opt"
  41. *
  42. * prefix_WRAPPER_FILTER "sed '...' | awk '...' | foobar"
  43. *
  44. * prefix_WRAPPER_NOLOOP Internal use only.
  45. *
  46. */
  47. #include <stdlib.h>
  48. #include <string.h>
  49. #include <stdio.h>
  50. #include <unistd.h>
  51. #include <ctype.h>
  52. #include <sys/wait.h>
  53. #include <libgen.h>
  54. #include <fnmatch.h>
  55. #ifndef ENVPREFIX
  56. # error You must use -DENVPREFIX=".." when compiling this tool.
  57. #endif
  58. #ifndef MYNAME
  59. # error You must use -DMYNAME=".." when compiling this tool.
  60. #endif
  61. #define VERBOSE_DEBUG 1
  62. int debug=1;
  63. /*
  64. * Clean config vars before using them (ugh!)
  65. */
  66. void cleanenv(const char * name, const char ch) {
  67. int pos1=0, pos2=0, delim=1;
  68. char *tmp1, *tmp2;
  69. setenv(name, "", 0);
  70. tmp1 = getenv(name);
  71. tmp2 = malloc(strlen(tmp1)+1);
  72. while ( tmp1[pos1] ) {
  73. if ( tmp1[pos1] == ch ) {
  74. if ( ! delim ) {
  75. tmp2[pos2++] = ch;
  76. delim = 1;
  77. }
  78. } else {
  79. tmp2[pos2++] = tmp1[pos1];
  80. delim = 0;
  81. }
  82. pos1++;
  83. }
  84. if (pos2 > 0 && tmp2[pos2-1] == ch) pos2--;
  85. tmp2[pos2] = 0; setenv(name, tmp2, 1);
  86. }
  87. /*
  88. * Main function.
  89. */
  90. int main(int argc, char ** argv) {
  91. char **newargv;
  92. int c1,c2,c3;
  93. char *delim, *delim1, *optbuf, *wrdir;
  94. FILE *logfile = NULL;
  95. /* Calling the wrapper with an absolute path results in an
  96. endless-loop. Use basename only to force a $PATH lookup. */
  97. argv[0] = basename(argv[0]);
  98. if ( !strcmp(argv[0], MYNAME) ) {
  99. if ( argc > 1 ) {
  100. argv++; argc--;
  101. argv[0] = basename(argv[0]);
  102. } else {
  103. fprintf(stderr, "Usage: %s command\n", argv[0]);
  104. exit(250);
  105. }
  106. }
  107. /* Open logfile (if any) */
  108. delim = getenv(ENVPREFIX "_WRAPPER_LOGFILE");
  109. if (delim && delim[0]) {
  110. logfile = fopen(delim, "a");
  111. }
  112. if (logfile) {
  113. delim = malloc(FILENAME_MAX);
  114. if ( getcwd(delim, FILENAME_MAX) == NULL ) delim[0]=0;
  115. fprintf(logfile, "\n%s:\n-", delim);
  116. for (c3=0; c3<argc; c3++) fprintf(logfile, " %s", argv[c3]);
  117. fprintf(logfile, "\n");
  118. free(delim);
  119. }
  120. /* Others loop */
  121. if ( (delim = getenv(ENVPREFIX "_WRAPPER_OTHERS_TMP")) != NULL )
  122. setenv(ENVPREFIX "_WRAPPER_OTHERS", delim, 1);
  123. /* Has to be solved that way ... do not ask my why >_< */
  124. if ( (delim = getenv(ENVPREFIX "_WRAPPER_APPEND_PO_CLEAR")) != NULL )
  125. setenv(ENVPREFIX "_WRAPPER_APPEND_PO", "", 1);
  126. /*
  127. * Read prefix_WRAPPER_DEBUG and prefix_WRAPPER_BYPASS
  128. */
  129. if ( (delim=getenv(ENVPREFIX "_WRAPPER_DEBUG")) != NULL &&
  130. delim[0] ) debug = atoi(delim);
  131. if ( (delim=getenv(ENVPREFIX "_WRAPPER_BYPASS")) != NULL &&
  132. delim[0] && atoi(delim)) {
  133. #if VERBOSE_DEBUG
  134. if (debug) fprintf(stderr, "Bypassing cmd_wrapper by "
  135. "clearing all config variables.\n");
  136. #endif
  137. setenv(ENVPREFIX "_WRAPPER_APPEND_PO", "", 1);
  138. setenv(ENVPREFIX "_WRAPPER_OTHERS", "", 1);
  139. setenv(ENVPREFIX "_WRAPPER_INSERT", "", 1);
  140. setenv(ENVPREFIX "_WRAPPER_REMOVE", "", 1);
  141. setenv(ENVPREFIX "_WRAPPER_APPEND", "", 1);
  142. setenv(ENVPREFIX "_WRAPPER_FILTER", "", 1);
  143. }
  144. cleanenv(ENVPREFIX "_WRAPPER_APPEND_PO", ' ');
  145. cleanenv(ENVPREFIX "_WRAPPER_OTHERS", ':');
  146. cleanenv(ENVPREFIX "_WRAPPER_INSERT", ' ');
  147. cleanenv(ENVPREFIX "_WRAPPER_REMOVE", ' ');
  148. cleanenv(ENVPREFIX "_WRAPPER_APPEND", ' ');
  149. cleanenv(ENVPREFIX "_WRAPPER_FILTER", '|');
  150. #if VERBOSE_DEBUG
  151. if (debug) {
  152. fprintf(stderr, "Old Command:");
  153. for (c3=0; c3<argc; c3++) fprintf(stderr, " %s", argv[c3]);
  154. fprintf(stderr, "\n");
  155. fprintf(stderr, "ENVPREFIX = '%s'\n", ENVPREFIX);
  156. fprintf(stderr, "APPEND_PO = '%s'\n",
  157. getenv(ENVPREFIX "_WRAPPER_APPEND_PO"));
  158. fprintf(stderr, "OTHERS = '%s'\n",
  159. getenv(ENVPREFIX "_WRAPPER_OTHERS"));
  160. fprintf(stderr, "INSERT = '%s'\n",
  161. getenv(ENVPREFIX "_WRAPPER_INSERT"));
  162. fprintf(stderr, "REMOVE = '%s'\n",
  163. getenv(ENVPREFIX "_WRAPPER_REMOVE"));
  164. fprintf(stderr, "APPEND = '%s'\n",
  165. getenv(ENVPREFIX "_WRAPPER_APPEND"));
  166. fprintf(stderr, "FILTER = '%s'\n",
  167. getenv(ENVPREFIX "_WRAPPER_FILTER"));
  168. }
  169. #endif
  170. /*
  171. * Run other wrappers first. They will re-start us.
  172. */
  173. if ( (delim=getenv(ENVPREFIX "_WRAPPER_OTHERS")) != NULL &&
  174. delim[0] ) {
  175. c1=argc;
  176. /*
  177. * If prefix__WRAPPER_APPEND_PO we need to add the count of
  178. * spaces in that variable
  179. */
  180. if ( (delim1=getenv(ENVPREFIX "_WRAPPER_APPEND_PO")) != NULL &&
  181. delim1[0] ) {
  182. while (*delim1) { if (*delim1==' ') c1++; delim1++; }
  183. }
  184. newargv=malloc( sizeof(char*) * (c1+10) );
  185. newargv[0] = malloc(strlen(delim) + 1);
  186. strcpy(newargv[0], delim);
  187. delim = strchr(newargv[0], ':');
  188. if ( delim == NULL ) delim = "";
  189. else { *delim = 0; delim++; }
  190. setenv(ENVPREFIX "_WRAPPER_OTHERS_TMP", delim, 1);
  191. for (c1=0; c1 < argc; c1++)
  192. newargv[c1+1] = argv[c1];
  193. /*
  194. * Append prefix_WRAPPER_APPEND_PO contents
  195. */
  196. if ( (delim1=getenv(ENVPREFIX "_WRAPPER_APPEND_PO")) != NULL &&
  197. delim1[0] ) {
  198. optbuf = malloc( strlen(delim1) + 1 );
  199. strcpy(optbuf, delim1);
  200. delim1 = strtok(optbuf, " ");
  201. c1=argc+1;
  202. while (delim1 != NULL) {
  203. if (delim1[0]) {
  204. #if VERBOSE_DEBUG
  205. if (debug) fprintf(stderr,
  206. "Append PreOthers: %s\n",
  207. delim1);
  208. #endif
  209. newargv[c1++] = delim1;
  210. }
  211. delim1 = strtok(NULL, " ");
  212. }
  213. /* Telling next instance of the wrapper to clean
  214. * prefix_WRAPPER_APPEND_PO_RUN (argh!)
  215. */
  216. setenv(ENVPREFIX "_WRAPPER_APPEND_PO_CLEAR", "1", 1);
  217. }
  218. #if VERBOSE_DEBUG
  219. if (debug) fprintf(stderr,
  220. "Running external wrapper: %s\n", newargv[0]);
  221. #endif
  222. if (logfile) {
  223. fprintf(logfile, "+");
  224. for (c3=0; c3<=c1; c3++)
  225. fprintf(logfile, " %s", newargv[c3]);
  226. fprintf(logfile, "\n");
  227. fclose(logfile);
  228. }
  229. execvp(newargv[0], newargv);
  230. fprintf(stderr, ENVPREFIX "_WRAPPER: Can't execute "
  231. "'%s' -> abort.\n", newargv[0]);
  232. return 250;
  233. }
  234. /*
  235. * Detect loops
  236. */
  237. if ( (delim=getenv(ENVPREFIX "_WRAPPER_NOLOOP")) != NULL &&
  238. delim[0] && delim[0] != '0') {
  239. fprintf(stderr, ENVPREFIX
  240. "_WRAPPER: Detected loop! -> abort.\n");
  241. return 250;
  242. }
  243. setenv(ENVPREFIX "_WRAPPER_NOLOOP", "1", 1);
  244. /*
  245. * Remove the wrapper dir from PATH
  246. */
  247. if ( (delim=getenv("PATH")) != NULL && delim[0] &&
  248. (wrdir=getenv(ENVPREFIX "_WRAPPER_MYPATH")) != NULL &&
  249. wrdir[0] ) {
  250. optbuf = malloc( strlen(delim) + 1 );
  251. optbuf[0] = 0;
  252. #if VERBOSE_DEBUG
  253. if (debug)
  254. fprintf(stderr, "Old PATH: %s\n", delim);
  255. #endif
  256. delim = strtok(delim, ":");
  257. while ( delim != NULL ) {
  258. if (strcmp(delim, wrdir)) {
  259. if (optbuf[0]) strcat(optbuf, ":");
  260. strcat(optbuf, delim);
  261. }
  262. delim = strtok(NULL, ":");
  263. }
  264. setenv("PATH", optbuf, 1);
  265. #if VERBOSE_DEBUG
  266. if (debug) fprintf(stderr, "New PATH: %s\n", optbuf);
  267. #endif
  268. } else {
  269. fprintf(stderr, ENVPREFIX "_WRAPPER: $PATH or $" ENVPREFIX
  270. "_WRAPPER_MYPATH is not set! -> abort.\n");
  271. return 250;
  272. }
  273. /*
  274. * Make sure that newargv[] is big enough
  275. */
  276. /* start with argc */
  277. c1 = argc;
  278. /* add numbers of blanks in prefix_WRAPPER_INSERT */
  279. if ( (delim=getenv(ENVPREFIX "_WRAPPER_INSERT")) != NULL )
  280. while (*delim) { if (*delim==' ') c1++; delim++; }
  281. /* add numbers of blanks in prefix_WRAPPER_APPEND */
  282. if ( (delim=getenv(ENVPREFIX "_WRAPPER_APPEND")) != NULL )
  283. while (*delim) { if (*delim==' ') c1++; delim++; }
  284. /* add 10 to be sure (3 should be enough) */
  285. newargv=malloc( sizeof(char*) * (c1+10) );
  286. /* init newargv[], c1 and c2 */
  287. newargv[0]=argv[0]; c1=1; c2=1;
  288. /*
  289. * Copy options from prefix_WRAPPER_INSERT to newargv[]
  290. */
  291. if ( (delim=getenv(ENVPREFIX "_WRAPPER_INSERT")) != NULL ) {
  292. optbuf = malloc( strlen(delim) + 1 );
  293. strcpy(optbuf, delim);
  294. delim = strtok(optbuf, " ");
  295. while (delim != NULL) {
  296. if (delim[0]) {
  297. #if VERBOSE_DEBUG
  298. if (debug) fprintf(stderr, "Insert: %s\n", delim);
  299. #endif
  300. newargv[c1++] = delim;
  301. }
  302. delim = strtok(NULL, " ");
  303. }
  304. }
  305. /*
  306. * Copy options from argv[] to newargv[] if they are not listed
  307. * in prefix_WRAPPER_REMOVE
  308. */
  309. for (; c2<argc; c2++) {
  310. if ( (delim=getenv(ENVPREFIX "_WRAPPER_REMOVE")) != NULL ) {
  311. optbuf = malloc( strlen(delim) + 1 );
  312. strcpy(optbuf, delim);
  313. delim = strtok(optbuf, " ");
  314. while (delim != NULL) {
  315. if ( delim[0] &&
  316. !fnmatch(delim, argv[c2], 0) ) break;
  317. delim = strtok(NULL, " ");
  318. }
  319. free(optbuf);
  320. }
  321. if (delim == NULL) {
  322. #if VERBOSE_DEBUG
  323. if (debug) fprintf(stderr, "Copy: %s\n", argv[c2]);
  324. #endif
  325. newargv[c1++] = argv[c2];
  326. #if VERBOSE_DEBUG
  327. } else {
  328. if (debug) fprintf(stderr, "Remove: %s\n", argv[c2]);
  329. #endif
  330. }
  331. }
  332. /*
  333. * Copy options from prefix_WRAPPER_APPEND to newargv[]
  334. */
  335. if ( (delim=getenv(ENVPREFIX "_WRAPPER_APPEND")) != NULL ) {
  336. optbuf = malloc( strlen(delim) + 1 );
  337. strcpy(optbuf, delim);
  338. delim = strtok(optbuf, " ");
  339. while (delim != NULL) {
  340. if (delim[0]) {
  341. #if VERBOSE_DEBUG
  342. if (debug) fprintf(stderr, "Append: %s\n", delim);
  343. #endif
  344. newargv[c1++] = delim;
  345. }
  346. delim = strtok(NULL, " ");
  347. }
  348. }
  349. /*
  350. * Use prefix_WRAPPER_FILTER if set and not ""
  351. *
  352. * (Maybe we make a nice re-write of this code-block later.)
  353. */
  354. if ( (delim=getenv(ENVPREFIX "_WRAPPER_FILTER")) != NULL && delim[0] ) {
  355. /* Open temp files. */
  356. char outfn[] = "/tmp/gccfilter_out.XXXXXX";
  357. char infn[] = "/tmp/gccfilter_in.XXXXXX";
  358. int outfd = mkstemp(outfn);
  359. int infd = mkstemp(infn);
  360. /* Create content of input file */
  361. for (c3=0; c3<c1; c3++) {
  362. write(infd, newargv[c3], strlen(newargv[c3]));
  363. write(infd, "\n", 1);
  364. }
  365. lseek(infd, 0, SEEK_SET);
  366. /* Run filter command with shell (sh -c xxx) */
  367. #if VERBOSE_DEBUG
  368. if (debug) fprintf(stderr, "Run Filter: %s\n", delim);
  369. #endif
  370. if (!fork()) {
  371. dup2(infd, 0); close(infd);
  372. dup2(outfd, 1); close(outfd);
  373. execlp("sh", "sh", "-c", delim, NULL);
  374. fprintf(stderr, ENVPREFIX "_WRAPPER: Can't execute "
  375. "'%s' with shell!\n", delim);
  376. return 1;
  377. }
  378. wait(NULL); /* We don't expect any signals and have no */
  379. /* other child processes. */
  380. /* Re-read parameter list. Don't free old stuff, we do an
  381. exec() anyway ... */
  382. lseek(outfd, 0, SEEK_SET);
  383. /* Maximum on 1023 parameters, 1023 chars each. */
  384. newargv = malloc( sizeof(char*) * 1024 );
  385. for (c1=0; c1<1023; c1++) {
  386. newargv[c1] = malloc(1024);
  387. for (c2=0; c2<1023; c2++) {
  388. if (read(outfd, newargv[c1]+c2, 1) != 1)
  389. goto reread_file_finished;
  390. if (newargv[c1][c2] == '\n')
  391. { newargv[c1][c2] = 0; break; }
  392. }
  393. newargv[c1] = realloc(newargv[c1],
  394. strlen(newargv[c1])+1);
  395. }
  396. reread_file_finished:
  397. /* Close and remove temp files */
  398. close(outfd); unlink(outfn);
  399. close(infd); unlink(infn);
  400. }
  401. /*
  402. * Run the new command
  403. */
  404. if (debug) {
  405. fprintf(stderr, "New Command:");
  406. for (c3=0; c3<c1; c3++) fprintf(stderr, " %s", newargv[c3]);
  407. fprintf(stderr, "\n");
  408. }
  409. if (logfile) {
  410. fprintf(logfile, "+");
  411. for (c3=0; c3<c1; c3++) fprintf(logfile, " %s", newargv[c3]);
  412. fprintf(logfile, "\n");
  413. fclose(logfile);
  414. }
  415. newargv[c1]=NULL;
  416. execvp(newargv[0], newargv);
  417. fprintf(stderr, ENVPREFIX "_WRAPPER: Can't execute "
  418. "'%s' -> abort.\n", newargv[0]);
  419. return 250;
  420. }