home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / unix_c / utils / bexec.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-03-21  |  4.1 KB  |  144 lines

  1. 10-Dec-85 13:09:35-MST,4267;000000000001
  2. Return-Path: <unix-sources-request@BRL.ARPA>
  3. Received: from BRL-TGR.ARPA by SIMTEL20.ARPA with TCP; Tue 10 Dec 85 13:09:24-MST
  4. Received: from usenet by TGR.BRL.ARPA id a003897; 10 Dec 85 14:04 EST
  5. From: Brandon Allbery <allbery@ncoast.uucp>
  6. Newsgroups: net.unix-wizards,net.sources
  7. Subject: csh vs. # comments in bourne shell scripts
  8. Message-ID: <918@ncoast.UUCP>
  9. Date: 10 Dec 85 03:08:18 GMT
  10. Followup-To: net.unix-wizards
  11. Xref: seismo net.unix-wizards:16109 net.sources:4009
  12. To:       unix-sources@BRL-TGR.ARPA
  13.  
  14. Expires:
  15.  
  16. Quoted from <392@brl-tgr.ARPA> ["Re: Magic Numbers"], by gwyn@brl-tgr.ARPA (Doug Gwyn <gwyn>)...
  17. +---------------
  18. | > Csh on non-4.2 systems checks for a # as
  19. | > the first character of the file, and forks itself if it sees it; if not, it
  20. | > forks a /bin/sh.
  21. | Yes, some of them do, but if they do that's a bug.
  22. | Virtually all of my Bourne shell scripts (including
  23. | SVR2 system utility scripts) start with "#".
  24. +---------------
  25.  
  26. All of them do.  When csh was written bsh still only spoke :.
  27.  
  28. There *is* a simple (albeit slow) solution.  Write a program to intuit the
  29. program to invoke on the file, with the file's full pathname passed as argv[1]
  30. and its arguments as argv[2] .. argv[argc - 1].  Then say:
  31.  
  32.     alias shell $HOME/bin/bexec
  33.  
  34. or whatever you decide to call it.  IT MUST BE A BINARY FILE AND IT MUST BE A
  35. FULL PATHNAME.  If csh can't exec() a program it will prepend the value of the
  36. ``shell'' alias to it, if any, and try again; if there isn't a shell alias it
  37. uses its own heuristics.
  38.  
  39. The program below uses this (mis-?)feature of bastard (orphaned?) csh'es to
  40. handle #! magic numbers, sans set[ug]id and other fun stuff.  Other than
  41. that it uses the same test as csh itself.  But you can do whatever you like,
  42. say to use * to cause your local Kermit-running MS-DOS machine to receive and
  43. execute the file as an MS-DOS batch file. [ :-) ]  Let me know if you come
  44. up with any interesting new twists.
  45.  
  46. --Brandon
  47. ----------------------------- cut here ---------------------------------------
  48. #include <stdio.h>
  49. #include <fcntl.h>
  50.  
  51. /*
  52.  * bexec: execute a non-binary file for csh, with #! recognition
  53.  * (usage: alias shell /usr/local/bin/bexec)
  54.  */
  55.  
  56. extern int errno;
  57. extern char *sys_errlist[];
  58.  
  59. #define SH        "/bin/sh"
  60. #define CSH        "/usr/plx/csh"
  61.  
  62. #define NARG        512    /* this is the number csh uses */
  63.  
  64. char *sysargv[NARG + 1];
  65. char **newargv();
  66. char *basename();
  67. extern char *strrchr();
  68.  
  69. main(argc, argv, envp)
  70. char **argv, **envp; {
  71.     FILE *cmd;
  72.     char kcmd[512];
  73.     char *cp, *ap;
  74.     
  75.     if ((cmd = fopen(argv[1], "r")) == NULL) {
  76.         fprintf(stderr, "bexec: can't open %s: %s\n", argv[1], sys_errlist[errno]);
  77.         exit(1);
  78.     }
  79.     fgets(kcmd, sizeof kcmd, cmd);
  80.     kcmd[strlen(kcmd) - 1] = '\0';    /* kill trailing \n */
  81.     if (strncmp(kcmd, "#!", 2) != 0) {
  82.         if (kcmd[0] == '#') {
  83.             argv[0] = "csh";
  84.             cp = CSH;
  85.         }
  86.         else {
  87.             argv[0] = "sh";
  88.             cp = SH;
  89.         }
  90.         execve(cp, argv, envp);
  91.         fprintf(stderr, "bexec: can't exec %s: %s\n", cp, sys_errlist[errno]);
  92.         exit(100);
  93.     }
  94.     for (cp = kcmd + 2; *cp == ' '; cp++)
  95.         ;
  96.     for (ap = cp; *ap != ' ' && *ap != '\0'; ap++)
  97.         ;
  98.     if (*ap == ' ')
  99.         *ap++ = '\0';
  100.     argv = newargv(basename(argv[1]), ap, argv);
  101.     fclose(stdin);
  102.     fcntl(fileno(cmd), F_DUPFD, 0);
  103.     lseek(0, ftell(cmd), 0);
  104.     fclose(cmd);
  105.     execve(cp, argv, envp);
  106.     fprintf(stderr, "bexec: can't exec %s: %s\n", cp, sys_errlist[errno]);
  107.     exit(100);
  108. }
  109.  
  110. char **newargv(newar0, newar1, oldargv)
  111. char *newar0, *newar1, **oldargv; {
  112.     int ap, op;
  113.     
  114.     sysargv[0] = newar0;
  115.     ap = 1;
  116.     if (newar1[0] != '\0') {
  117.         sysargv[1] = newar1;
  118.         ap++;
  119.     }
  120.     for (op = 2; ap < NARG && oldargv[op] != NULL; ap++, op++)
  121.         sysargv[ap] = oldargv[op];
  122.     sysargv[ap] = NULL;
  123.     return sysargv;
  124. }
  125.  
  126. char *basename(path)
  127. char *path; {
  128.     char *cp;
  129.  
  130.     if ((cp = strrchr(path, '/')) == NULL)
  131.         return path;
  132.     return cp + 1;
  133. }
  134.  
  135. -- 
  136.  
  137.             Lord Charteris (thurb)
  138.  
  139. ncoast!allbery@Case.CSNet (ncoast!allbery%Case.CSNet@CSNet-Relay.ARPA)
  140. ..decvax!cwruecmp!ncoast!allbery (..ncoast!tdi2!root for business)
  141. 6615 Center St., Mentor, OH 44060 (I moved) --Phone: +01 216 974 9210
  142. CIS 74106,1032 -- MCI MAIL BALLBERY (WARNING: I am only a part-time denizen...)
  143.