-2

I was reading the Advanced Programming in UNIX and stumbled upon this example. What is the shebang line doing here? Here's the top part of the code.

#!/usr/bin/awk -f
BEGIN   {
    printf("#include \"apue.h\"\n")
    printf("#include <errno.h>\n")
    printf("\n")
    printf("static void pr_sysconf(char *, int);\n")
    printf("static void pr_pathconf(char *, char *, int);\n")
    printf("\n")
    printf("int\n")
    printf("main(int argc, char *argv[])\n")
    printf("{\n")
    printf("\tif (argc != 2)\n")
    printf("\t\terr_quit(\"usage: a.out <dirname>\");\n\n")
    FS="\t+"
    while (getline <"sysopt.sym" > 0) {
        printf("#ifdef %s\n", $1)
        printf("\tprintf(\"%s is defined (val is %%ld)\\n\", (long)%s+0);\n", $1, $1)
        printf("#else\n")
        printf("\tprintf(\"%s is undefined\\n\");\n", $1)
        printf("#endif\n")
        printf("#ifdef %s\n", $2)
Myst
  • 16,507
  • 2
  • 40
  • 61
  • 7
    Why is this tagged [c]? It looks like it emits some c-code, but is otherwise not related. – abelenky May 04 '18 at 13:00
  • It means that this file is intended to be an executable command, to be executed (interpreted) by the program `/usr/bin/awk`. (That's what the `#!` line always means.) – Steve Summit May 04 '18 at 13:00

2 Answers2

3

The shebang line is (on Linux and most Unixes) understood by execve(2). However, POSIX don't specify anything about it. Your script should be run by e.g. GNU awk, assuming that script is an executable file (and you probably want it to be accessible from your PATH variable).

So when something (probably your Unix shell, but could be something else) is executing with execve that script, the /usr/bin/awk program gets executed. You are betting that this awk program is some implementation of AWK

Basile Starynkevitch
  • 1
  • 16
  • 251
  • 479
1

The OS's routines for executing a file look for the two characters #! at the start of a file, and if present, instead of directly loading the file as a binary executable, they call the executable file referenced by the rest of that line, along with any command line argument therein, then the original file as a final argument.

That's quite an involved description; a couple of examples make it clearer:

If myFile contains:

#!/bin/echo My path is

... and we make it executable:

$ chmod +x myFile

... then when we run it, we get:

$ ./myFile
My path is /home/slim/myFile

Or if we change its contents to:

#!/bin/cat
Hello
world

Then when we run it, it prints itself ...

$ ./myFile
#!/bin/cat
Hello
world

This is generally useful when command it invokes is an interpreter which can work with the contents, and itself ignores the shebang. Of course in many languages # denotes a comment, so we get this for free:

#!/bin/bash
#!/usr/bin/perl
#!/bin/awk -f

So essentially it arranges matters such that running myFile directly, is equivalent to running awk -f myFile.

slim
  • 36,139
  • 10
  • 83
  • 117