Advanced Programming in UNIX Environment Episode 32
Interpreter FilesAll contemporary UNIX systems support interpreter files. These files are text files that begin with a line of the form #! pathname [ optional-argument ]
The space between the exclamation point and the pathname is optional. The most common of these interpreter files begin with the line #!/bin/sh
The pathname is normally an absolute pathname,since no special operations are performed on it (i.e.,PATH is not used). Be aware that systems place a size limit on the first line of an interpreter file. This limit includes the #!,the pathname,the optional argument,the terminating newline,and any spaces.
#include "apue.h"
#include <sys/wait.h>
int main(int argc,char *argv[])
{
pid_t pid;
if((pid=fork())<0)
err_sys("fork error");
else if(pid==0)
{
if(execl("/home/sar/bin/testinterp","testinterp","myarg1","MY ARG2",(char *)0)<0)
err_sys("execl error");
}
if(waitpid(pid,NULL,0)<0)
err_sys("waitpid error");
return 0;
}
A program that execs an interpreter file A common use for the optional argument following the interpreter pathname is to specify the -f option for programs that support this option. For example,an awk(1) program can be executed as awk -f myfile
which tells awk to read the awk program from the file myfile.
Using the -f option with an interpreter file lets us write #!/bin/awk -f
(awk program follows in the interpreter file)
#!/usr/bin/awk -f
# Note: on Solaris,use nawk instead
BEGIN {
for (i = 0; i < ARGC; i++)
printf "ARGV[%d] = %sn",i,ARGV[i]
exit
}
An awk program as an interpreter file When /bin/awk is executed,its command-line arguments are /bin/awk -f /usr/local/bin/awkexample file1 FILENAME2 f3
The pathname of the interpreter file (/usr/local/bin/awkexample) is passed to the interpreter. Interpreter files are useful for the following reasons. 1.They hide that certain programs are scripts in some other language. For example,to execute the program in Figure 8.21,we just say awkexample optional-arguments
instead of needing to know that the program is really an awk script that we would otherwise have to execute as awk -f awkexample optional-arguments
2.Interpreter scripts provide an efficiency gain. Consider the previous example again. We could still hide that the program is an awk script,by wrapping it in a shell script: awk ’BEGIN {
for (i = 0; i < ARGC; i++)
printf "ARGV[%d] = %sn",ARGV[i]
exit
}’ $*
3.Interpreter scripts let us write shell scripts using shells other than /bin/sh. When it finds an executable file that isn’t a machine executable,execlp has to choose a shell to invoke,and it always uses /bin/sh. Using an interpreter script,however,we can simply write #!/bin/csh
(C shell script follows in the interpreter file) Again,we could wrap all of this in a /bin/sh script (that invokes the C shell),as we described earlier,but more overhead is required. system FunctionIt is much easier,to say system("date > file");
ISO C defines the system function,but its operation is strongly system dependent. POSIX.1 includes the system interface,expanding on the ISO C definition to dscribe its behavior in a POSIX environment. #include <stdlib.h>
int system(const char *cmdstring);
Because system is implemented by calling fork,exec,and waitpid,there are three types of return values. 1.If either the fork fails or waitpid returns an error other than EINTR,system returns ?1 with errno set to indicate the error.
#include <errnor.h>
#include <unistd.h>
#include <sys/wait.h>
int system(const char *cmdstring)
{
pid_t pid;
int status;
if(cmdstring==NULL)
{
return 1;
}
if((pid=fork())<0)
{
status=-1;
}
else if(pid==0)
{
execl("/bin/sh","sh","-c",cmdstring,(char *)0);
_exit(127);
}
else
{
while(waitpid(pid,&status,0))
{
if(errno!=EINTR)
{
status=-1;
break;
}
}
}
return status;
}
The system function,without signal handling The advantage in using system,instead of using fork and exec directly,is that system does all the required error handling and all the required signal handling. #include "apue.h"
#include <sys/wait.h>
int main(void)
{
int status;
if((status=system("date"))<0)
err_sys("system() error");
pr_exit(status);
if((status=system("nosuchcommand"))<0)
err_sys("system() error");
pr_exit(status);
if((status=system("who; exit 44"))<0)
err_sys("system() error");
pr_exit(status);
return 0;
}
Calling the system function #include "apue.h"
int main(int argc,char*argv[])
{
int status;
if(argc<2)
err_quit("command-line argument required");
if((status=system(argv[1]))<0)
err_sys("system() error");
pr_exit(status);
return 0;
}
Execute the command-line argument using system #include "apue.h"
int main(void)
{
printf("real uid=%d,effective uid=%dn",getuid(),geteuid());
return 0;
}
The superuser permissions that we gave the tsys program are retained across the fork and exec that are done by system.
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |