home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk1.iso / altsrc / articles / 7000-7999 / 7507 < prev    next >
Text File  |  1993-03-11  |  11KB  |  512 lines

  1. Newsgroups: alt.sources
  2. Path: wupost!howland.reston.ans.net!agate!dog.ee.lbl.gov!network.ucsd.edu!gulfaero.com!ux1.cso.uiuc.edu!news.cso.uiuc.edu!peltz
  3. From: peltz@cerl.uiuc.edu (Steve Peltz)
  4. Subject: self replicating program
  5. Date: Thu, 11 Mar 1993 23:03:59 GMT
  6. Message-ID: <C3qyqn.H2p@news.cso.uiuc.edu>
  7. Sender: usenet@news.cso.uiuc.edu (Net Noise owner)
  8. Organization: Computer Based Education Research Lab - University of Illinois
  9. Lines: 501
  10.  
  11. A recent posting of a generator for self-extracting compressed program
  12. reminded me of the self-replicating program I posted a year or two back
  13. (after one of the inevitable rounds of discussion about same). Since
  14. I'd played around a bit more with it, I decided to dust it off and fix
  15. it up a bit.
  16.  
  17. There are actually three separate versions of programs here. The
  18. interesting part is that it is a fairly general shell for building
  19. self-replicating programs. Obviously, the job can be done much more
  20. easily if the only goal is to write a program that can re-create it's
  21. source.
  22.  
  23. Instructions for use: snip and copy to a file, compile it, create a new
  24. directory and cd to it, then run the program.
  25.  
  26. e.g.
  27. cc -o replicate replicate.c
  28. mkdir self
  29. cd self
  30. ../replicate
  31.  
  32. This will create a makefile and several source files. The file "selfcopy.c"
  33. in the new directory should be the same as what I'm posting. "make test" will
  34. build and test all three versions.
  35.  
  36. The three programs are:
  37. self        just reproduces its source on stdout
  38. selfshar    reproduces on stdout a shar file that contains the sources
  39.         for re-creating a new version of itself (requires "shar")
  40. replicate    creates the source tree for building itself and the other
  41.         two programs (in the current directory); also creates a
  42.         file selfcopy.c, which should be identical to replicate.c
  43.  
  44. Sorry for the lack of comments.
  45.  
  46. Here is replicate.c:
  47. -------------------------------------------------------------------------------
  48. char    *selfish[] = {
  49. "#include <stdio.h>\n",
  50. "\n",
  51. "void\tdup(p, out)\n",
  52. "\tchar\t*p[];\n",
  53. "\tFILE\t*out;\n",
  54. "{\n",
  55. "\tchar\t*c;\n",
  56. "\n",
  57. "\twhile (c = *p++)\n",
  58. "\t\tfputs(c, out);\n",
  59. "}\n",
  60. "\n",
  61. "void\tmakehead(aname, out)\n",
  62. "\tchar\t*aname;\n",
  63. "\tFILE\t*out;\n",
  64. "{\n",
  65. "\tfprintf(out, \"char\\t*%s[] = {\\n\", aname);\n",
  66. "}\n",
  67. "\n",
  68. "void\tmakeline(c, out)\n",
  69. "\tchar\t*c;\n",
  70. "\tFILE\t*out;\n",
  71. "{\n",
  72. "\tchar\tch;\n",
  73. "\n",
  74. "\tputc('\"', out);\n",
  75. "\twhile (ch = *c++) {\n",
  76. "\t\tif ((ch == '\"') || (ch == '\\\\') || (ch == '\\n') ||\n",
  77. "\t\t\t(ch == '\\t'))\n",
  78. "\t\t\tputc('\\\\', out);\n",
  79. "\t\tif (ch == '\\n')\n",
  80. "\t\t\tputc('n', out);\n",
  81. "\t\telse if (ch == '\\t')\n",
  82. "\t\t\tputc('t', out);\n",
  83. "\t\telse\n",
  84. "\t\t\tputc(ch, out);\n",
  85. "\t}\n",
  86. "\tfputs(\"\\\",\\n\", out);\n",
  87. "}\n",
  88. "\n",
  89. "void\tmaketail(out)\n",
  90. "\tFILE\t*out;\n",
  91. "{\n",
  92. "\tfputs(\"0};\\n\\n\", out);\n",
  93. "}\n",
  94. "\n",
  95. "void\tclone(aname, p, out)\n",
  96. "\tchar\t*aname;\n",
  97. "\tchar\t*p[];\n",
  98. "\tFILE\t*out;\n",
  99. "{\n",
  100. "\tmakehead(aname, out);\n",
  101. "\twhile (*p)\n",
  102. "\t\tmakeline(*p++, out);\n",
  103. "\tmaketail(out);\n",
  104. "}\n",
  105. "\n",
  106. "void\tclonehead(aname, out)\n",
  107. "\tchar\t*aname;\n",
  108. "\tFILE\t*out;\n",
  109. "{\n",
  110. "\tfprintf(out, \"\\nstruct self {\\n\");\n",
  111. "\tfprintf(out, \"\\tchar\\t**txt;\\n\");\n",
  112. "\tfprintf(out, \"\\tchar\\t*name;\\n\");\n",
  113. "\tfprintf(out, \"\\tchar\\t*file;\\n\");\n",
  114. "\tfprintf(out, \"} %s[] = {\\n\", aname);\n",
  115. "}\n",
  116. "\n",
  117. "void\tcloneline(aname, afile, out)\n",
  118. "\tchar\t*aname;\n",
  119. "\tchar\t*afile;\n",
  120. "\tFILE\t*out;\n",
  121. "{\n",
  122. "\tfprintf(out, \"\\t%s, \\\"%s\\\", \\\"%s\\\",\\n\", aname, aname, afil",
  123. "e);\n",
  124. "}\n",
  125. "\n",
  126. "void\tclonetail(aname, afile, out)\n",
  127. "\tchar\t*aname;\n",
  128. "\tchar\t*afile;\n",
  129. "\tFILE\t*out;\n",
  130. "{\n",
  131. "\tfprintf(out, \"\\t0, \\\"%s\\\", \\\"%s\\\"\\n\", aname, afile);\n",
  132. "\tfprintf(out, \"};\\n\\n\");\n",
  133. "}\n",
  134. 0};
  135.  
  136. char    *replicate[] = {
  137. "void\tcloneself(last, out)\n",
  138. "\tstruct self\t*last;\n",
  139. "\tFILE\t*out;\n",
  140. "{\n",
  141. "\tstruct self\t*p;\n",
  142. "\n",
  143. "\tclonehead(last->name, out);\n",
  144. "\tfor (p = self; p->txt; p++)\n",
  145. "\t\tcloneline(p->name, p->file, out);\n",
  146. "\tclonetail(last->name, last->file, out);\n",
  147. "}\n",
  148. "\n",
  149. "void\tdupself(out)\n",
  150. "{\n",
  151. "\tstruct self\t*p;\n",
  152. "\n",
  153. "\tfor (p = self; p->txt; p++)\n",
  154. "\t\tclone(p->name, p->txt, out);\n",
  155. "\tcloneself(p, out);\n",
  156. "\tdup(self[0].txt, out);\n",
  157. "\tdup(self[1].txt, out);\n",
  158. "}\n",
  159. "\n",
  160. "void\tdupfile(p)\n",
  161. "\tstruct self\t*p;\n",
  162. "{\n",
  163. "\tFILE\t*out;\n",
  164. "\n",
  165. "\tif (!(out = fopen(p->file, \"w\"))) {\n",
  166. "\t\tfprintf(stderr, \"dupfile: create \");\n",
  167. "\t\tperror(p->file);\n",
  168. "\t\texit(1);\n",
  169. "\t}\n",
  170. "\tif (p->txt)\n",
  171. "\t\tdup(p->txt, out);\n",
  172. "\telse\n",
  173. "\t\tdupself(out);\n",
  174. "\tfclose(out);\n",
  175. "}\n",
  176. "\n",
  177. "void\tdupfiles()\n",
  178. "{\n",
  179. "\tstruct self\t*p;\n",
  180. "\n",
  181. "\tfor (p = self; p->txt; p++)\n",
  182. "\t\tdupfile(p);\n",
  183. "\tdupfile(p);\n",
  184. "}\n",
  185. "\n",
  186. "int\tmain(argc, argv)\n",
  187. "\tint\targc;\n",
  188. "\tchar\t*argv[];\n",
  189. "{\n",
  190. "\tdupfiles();\n",
  191. "\treturn 0;\n",
  192. "}\n",
  193. 0};
  194.  
  195. char    *replicant[] = {
  196. "\n",
  197. "int\tmain()\n",
  198. "{\n",
  199. "\tclone(\"self\", self, stdout);\n",
  200. "\tclone(\"replicant\", replicant, stdout);\n",
  201. "\tdup(self, stdout);\n",
  202. "\tdup(replicant, stdout);\n",
  203. "}\n",
  204. 0};
  205.  
  206. char    *shar[] = {
  207. "#include <stdio.h>\n",
  208. "\n",
  209. "int\tmain()\n",
  210. "{\n",
  211. "\tchar\t**p;\n",
  212. "\tchar\t*s;\n",
  213. "\n",
  214. "\tp = shar;\n",
  215. "\twhile (s = *p++)\n",
  216. "\t\tfputs(s, stdout);\n",
  217. "\treturn 0;\n",
  218. "}\n",
  219. 0};
  220.  
  221. char    *make[] = {
  222. "all:\tself selfshar replicate\n",
  223. "\n",
  224. "test:\tall\n",
  225. "\trm -rf cmp\n",
  226. "\tmkdir cmp\n",
  227. "\t./self > cmp/self.c\n",
  228. "\tcmp self.c cmp/self.c\n",
  229. "\trm -f cmp/*\n",
  230. "\t./selfshar > cmp/shar\n",
  231. "\tcd cmp; unshar shar; make selfshar; ./selfshar > shar\n",
  232. "\tcmp cmp/shar cmp/self.shar\n",
  233. "\trm -f cmp/*\n",
  234. "\tcd cmp; ../replicate\n",
  235. "\tcmp replicate.c cmp/selfcopy.c\n",
  236. "\tcd cmp; make replicate.c\n",
  237. "\tcmp replicate.c cmp/replicate.c\n",
  238. "\trm -rf cmp\n",
  239. "\n",
  240. "self:\tself.c\n",
  241. "\tcc -o self self.c\n",
  242. "\n",
  243. "self.c:\tmakeself replicant.self\n",
  244. "\t./makeself self selfish.c replicant replicant.self - selfi",
  245. "sh.c replicant.self > self.c\n",
  246. "\n",
  247. "selfshar:\tselfshar.c\n",
  248. "\tcc -o selfshar selfshar.c\n",
  249. "\n",
  250. "selfshar.c:\tmakeself self.shar\n",
  251. "\t./makeself shar self.shar - selfshar.self > selfshar.c\n",
  252. "\n",
  253. "self.shar:\tselfish.c clone.c makeself.c selfshar.self Makef",
  254. "ile\n",
  255. "\tshar selfish.c clone.c makeself.c selfshar.self Makefile >",
  256. " self.shar\n",
  257. "\n",
  258. "replicate:\treplicate.c\n",
  259. "\tcc -o replicate replicate.c\n",
  260. "\n",
  261. "replicate.c:\tmakeself replicate.self replicant.self selfsha",
  262. "r.self Makefile\n",
  263. "\t./makeself selfish selfish.c replicate replicate.self repl",
  264. "icant replicant.self shar selfshar.self make Makefile build",
  265. " makeself.c cloner clone.c -self selfcopy.c selfish.c repli",
  266. "cate.self > replicate.c\n",
  267. "\n",
  268. "makeself:\tmakeself.o selfish.o clone.o\n",
  269. "\tcc -o makeself makeself.o selfish.o clone.o\n",
  270. "\n",
  271. "clean:\n",
  272. "\trm -f replicate.c self.c selfshar.c replicate self selfsha",
  273. "r self.shar copy.c\n",
  274. "\n",
  275. "realclean:\tclean\n",
  276. "\trm -f *.o makeself\n",
  277. "\trm -rf cmp\n",
  278. 0};
  279.  
  280. char    *build[] = {
  281. "#include <stdio.h>\n",
  282. "\n",
  283. "int\tmain(argc, argv)\n",
  284. "\tint\targc;\n",
  285. "\tchar\t*argv[];\n",
  286. "{\n",
  287. "\tint\tindex;\n",
  288. "\tint\tclonal;\n",
  289. "\n",
  290. "\tclonal = 0;\n",
  291. "\tfor (index = 1; index < argc; index += 2) {\n",
  292. "\t\tif (*argv[index] == '-') {\n",
  293. "\t\t\tclonal = index;\n",
  294. "\t\t\tbreak;\n",
  295. "\t\t}\n",
  296. "\t\tmakeself(argv[index], argv[index+1], stdout);\n",
  297. "\t}\n",
  298. "\tif (clonal) {\n",
  299. "\t\tif (argv[clonal][1]) {\n",
  300. "\t\t\tclonehead(argv[clonal]+1, stdout);\n",
  301. "\t\t\tfor (index = 1; index < clonal; index += 2)\n",
  302. "\t\t\t\tcloneline(argv[index], argv[index+1], stdout);\n",
  303. "\t\t\tclonetail(argv[clonal]+1, argv[clonal+1], stdout);\n",
  304. "\t\t\tclonal += 1;\n",
  305. "\t\t}\n",
  306. "\t\tfor (index = clonal + 1; index < argc; index += 1)\n",
  307. "\t\t\tcopyfile(argv[index], stdout);\n",
  308. "\t}\n",
  309. "\treturn 0;\n",
  310. "}\n",
  311. 0};
  312.  
  313. char    *cloner[] = {
  314. "#include <stdio.h>\n",
  315. "\n",
  316. "#define\tMAXLINE\t60\n",
  317. "\n",
  318. "void\tmakeself(aname, fname, out)\n",
  319. "\tchar\t*aname;\n",
  320. "\tchar\t*fname;\n",
  321. "\tFILE\t*out;\n",
  322. "{\n",
  323. "\tFILE\t*in;\n",
  324. "\tchar\tp[MAXLINE];\n",
  325. "\n",
  326. "\tif (!(in = fopen(fname, \"r\"))) {\n",
  327. "\t\tfprintf(stderr, \"makeself: create \");\n",
  328. "\t\tperror(fname);\n",
  329. "\t\texit(1);\n",
  330. "\t}\n",
  331. "\tmakehead(aname, out);\n",
  332. "\twhile (fgets(p, MAXLINE, in))\n",
  333. "\t\tmakeline(p, out);\n",
  334. "\tmaketail(out);\n",
  335. "\tfclose(in);\n",
  336. "}\n",
  337. "\n",
  338. "void\tcopyfile(fname, out)\n",
  339. "\tchar\t*fname;\n",
  340. "\tFILE\t*out;\n",
  341. "{\n",
  342. "\tFILE\t*in;\n",
  343. "\tchar\ts[MAXLINE];\n",
  344. "\n",
  345. "\tif (!(in = fopen(fname, \"r\"))) {\n",
  346. "\t\tfprintf(stderr, \"copyfile: open \");\n",
  347. "\t\tperror(fname);\n",
  348. "\t\texit(1);\n",
  349. "\t}\n",
  350. "\twhile (fgets(s, MAXLINE, in))\n",
  351. "\t\tfputs(s, out);\n",
  352. "\tfclose(in);\n",
  353. "}\n",
  354. 0};
  355.  
  356.  
  357. struct self {
  358.     char    **txt;
  359.     char    *name;
  360.     char    *file;
  361. } self[] = {
  362.     selfish, "selfish", "selfish.c",
  363.     replicate, "replicate", "replicate.self",
  364.     replicant, "replicant", "replicant.self",
  365.     shar, "shar", "selfshar.self",
  366.     make, "make", "Makefile",
  367.     build, "build", "makeself.c",
  368.     cloner, "cloner", "clone.c",
  369.     0, "self", "selfcopy.c"
  370. };
  371.  
  372. #include <stdio.h>
  373.  
  374. void    dup(p, out)
  375.     char    *p[];
  376.     FILE    *out;
  377. {
  378.     char    *c;
  379.  
  380.     while (c = *p++)
  381.         fputs(c, out);
  382. }
  383.  
  384. void    makehead(aname, out)
  385.     char    *aname;
  386.     FILE    *out;
  387. {
  388.     fprintf(out, "char\t*%s[] = {\n", aname);
  389. }
  390.  
  391. void    makeline(c, out)
  392.     char    *c;
  393.     FILE    *out;
  394. {
  395.     char    ch;
  396.  
  397.     putc('"', out);
  398.     while (ch = *c++) {
  399.         if ((ch == '"') || (ch == '\\') || (ch == '\n') ||
  400.             (ch == '\t'))
  401.             putc('\\', out);
  402.         if (ch == '\n')
  403.             putc('n', out);
  404.         else if (ch == '\t')
  405.             putc('t', out);
  406.         else
  407.             putc(ch, out);
  408.     }
  409.     fputs("\",\n", out);
  410. }
  411.  
  412. void    maketail(out)
  413.     FILE    *out;
  414. {
  415.     fputs("0};\n\n", out);
  416. }
  417.  
  418. void    clone(aname, p, out)
  419.     char    *aname;
  420.     char    *p[];
  421.     FILE    *out;
  422. {
  423.     makehead(aname, out);
  424.     while (*p)
  425.         makeline(*p++, out);
  426.     maketail(out);
  427. }
  428.  
  429. void    clonehead(aname, out)
  430.     char    *aname;
  431.     FILE    *out;
  432. {
  433.     fprintf(out, "\nstruct self {\n");
  434.     fprintf(out, "\tchar\t**txt;\n");
  435.     fprintf(out, "\tchar\t*name;\n");
  436.     fprintf(out, "\tchar\t*file;\n");
  437.     fprintf(out, "} %s[] = {\n", aname);
  438. }
  439.  
  440. void    cloneline(aname, afile, out)
  441.     char    *aname;
  442.     char    *afile;
  443.     FILE    *out;
  444. {
  445.     fprintf(out, "\t%s, \"%s\", \"%s\",\n", aname, aname, afile);
  446. }
  447.  
  448. void    clonetail(aname, afile, out)
  449.     char    *aname;
  450.     char    *afile;
  451.     FILE    *out;
  452. {
  453.     fprintf(out, "\t0, \"%s\", \"%s\"\n", aname, afile);
  454.     fprintf(out, "};\n\n");
  455. }
  456. void    cloneself(last, out)
  457.     struct self    *last;
  458.     FILE    *out;
  459. {
  460.     struct self    *p;
  461.  
  462.     clonehead(last->name, out);
  463.     for (p = self; p->txt; p++)
  464.         cloneline(p->name, p->file, out);
  465.     clonetail(last->name, last->file, out);
  466. }
  467.  
  468. void    dupself(out)
  469. {
  470.     struct self    *p;
  471.  
  472.     for (p = self; p->txt; p++)
  473.         clone(p->name, p->txt, out);
  474.     cloneself(p, out);
  475.     dup(self[0].txt, out);
  476.     dup(self[1].txt, out);
  477. }
  478.  
  479. void    dupfile(p)
  480.     struct self    *p;
  481. {
  482.     FILE    *out;
  483.  
  484.     if (!(out = fopen(p->file, "w"))) {
  485.         fprintf(stderr, "dupfile: create ");
  486.         perror(p->file);
  487.         exit(1);
  488.     }
  489.     if (p->txt)
  490.         dup(p->txt, out);
  491.     else
  492.         dupself(out);
  493.     fclose(out);
  494. }
  495.  
  496. void    dupfiles()
  497. {
  498.     struct self    *p;
  499.  
  500.     for (p = self; p->txt; p++)
  501.         dupfile(p);
  502.     dupfile(p);
  503. }
  504.  
  505. int    main(argc, argv)
  506.     int    argc;
  507.     char    *argv[];
  508. {
  509.     dupfiles();
  510.     return 0;
  511. }
  512.