et, rset; /* */
struct timeval timeout, rtimeout;
FD_ZERO(&set); nopen = 0; /* */
FD_SET (PP.pfd, &set); nopen++; /* */
FD_SET (STDIN, &set); nopen++;
maxfd = max(PP.pfd, STDIN);
timeout.tv_sec = 3600; /* */
timeout.tv_usec = 0; /* */
. , 1992-95 - 270 - UNIX
nfds = maxfd + 1;
while( nopen ){
rset = set;
rtimeout = timeout;
/* */
if((nready = select( nfds, &rset, NULL, NULL, &rtimeout )) <= 0)
continue;
for(f=0; f < nfds; f++ )
if( FD_ISSET(f, &rset)){ /* f */
int n;
if((n = read(f, buf, sizeof buf)) <= 0 ){
FD_CLR(f, &set); nopen--; /* */
close(f);
} else {
int fdout;
/* */
if( f == PP.pfd ){
fdout = STDOUT;
PP.out_bytes += n;
if( fpscript )
fwrite(buf, 1, n, fpscript);
} else if( f == STDIN ) {
fdout = PP.pfd;
PP.in_bytes += n;
if( halfflag && fpscript )
fwrite(buf, 1, n, fpscript);
if( autoecho )
write(STDOUT, buf, n);
}
write(fdout, buf, n);
}
}
}
}
. , 1992-95 - 271 - UNIX
int main(ac, av) char **av;
{
while( ac > 1 && *av[1] == '-' ){
switch(av[1][1]){
case 's':
scriptflg++;
break;
case 'f':
av++; ac--;
protocol = av[1];
scriptflg++;
break;
case 'h':
halfflag++;
break;
case 'a':
autoecho++;
break;
default:
fprintf(stderr, "Bad key %s\n", av[1]);
break;
}
ac--; av++;
}
if( scriptflg ){
fpscript = fopen( protocol, "w" );
}
ac--; av++;
wm_init();
PP = wm_ptypair();
if( PP.pfd < 0 ){
fprintf(stderr, "Cannot get pty. Please wait and try again.\n");
return 1;
}
wm_fixtty();
wm_startshell(ac, av);
go++;
wm_select();
wm_done(0);
/* NOTREACHED */
return 0;
}
6.12. .
.
match " ".
. , 1992-95 - 272 - UNIX
/* .
* : CMD ARG1 ... ARGn <FILE >FILE >>FILE >&FILE >>&FILE
* : cc -U42 -DCWDONLY sh.c match.c pwd.c -o sh
*/
#include <sys/types.h>/* , */
#include <stdio.h> /* / */
#include <signal.h> /* */
#include <fcntl.h> /* O_RDONLY */
#include <errno.h> /* */
#include <ctype.h> /* */
#include <dirent.h> /* BSD 4.2 */
#include <pwd.h> /* /etc/passwd */
#include <sys/wait.h> /* wait() */
char cmd[256]; /* */
#define MAXARGS 256 /* . */
char *arg[MAXARGS]; /* */
char *fin, *fout; /* / */
int rout; /* */
char *firstfound; /* , */
#define LIM ':' /* path */
extern char *malloc(), *getenv(), *strcpy(), *getwd();
extern char *strchr(), *execat();
extern void callshell(), printenv(), setenv(), dowait(), setcwd();
extern struct passwd *getpwuid();
/* */
extern char **environ; /* :
* , ev main() */
extern int errno; /* */
char *strdup(s)char *s;
{ char *p; return(p=malloc(strlen(s)+1), strcpy(p,s)); }
/* strcpy() */
char *str3spl(s, p, q) char *s, *p, *q;
{ char *n = malloc(strlen(s)+strlen(p)+strlen(q)+1);
strcpy(n, s); strcat(n, p); strcat(n, q); return n;
}
int cmps(s1, s2) char **s1, **s2;
{ return strcmp(*s1, *s2); }
. , 1992-95 - 273 - UNIX
/* */
#define APPEND 0x01
#define ERRTOO 0x02
int output (name, append, err_too, created) char *name; int *created;
{
int fd;
*created = 0; /* ? */
if( append ){ /* >>file */
/* name ? */
if((fd = open (name, O_WRONLY)) < 0) {
if (errno == ENOENT) /* */
goto CREATE;
else
return 0; /* */
}
/* fd == , *created == 0 */
}else{
CREATE: /* ( ) "name" */
if((fd = creat (name, 0666)) < 0 )
return 0; /* */
else *created = 1; /* */
}
if (append)
lseek (fd, 0l, 2); /* */
/* */
dup2(fd, 1);
if( err_too ) dup2(fd, 2); /* err_too=1 >& */
close(fd); return 1;
}
/* */
int input (name) char *name;
{
int fd;
if((fd = open (name, O_RDONLY)) < 0 ) return 0;/* */
/* */
dup2(fd, 0); close(fd); return 1;
}
. , 1992-95 - 274 - UNIX
/* */
int cmdExec(progr, av, envp, inp, outp, outflg)
char *progr; /* */
char **av; /* */
char **envp; /* */
char *inp, *outp; /* - () */
int outflg; /* */
{
void (*del)(), (*quit)();
int pid;
int cr = 0;
del = signal(SIGINT, SIG_IGN); quit = signal(SIGQUIT, SIG_IGN);
if( ! (pid = fork())){ /* */
/* () */
signal(SIGINT, SIG_DFL); /* */
signal(SIGQUIT,SIG_DFL); /* */
/* getpid() () */
printf( " pid=%d \n", pid = getpid());
/* - */
if( inp ) if(!input( inp )){
fprintf(stderr, " <%s\n", inp ); goto Err;
}
if( outp )
if(!output (outp, outflg & APPEND, outflg & ERRTOO, &cr)){
fprintf(stderr, " >%s\n", outp ); goto Err;
}
/* :
* ,
* main(ac, av, envp) , progr.
* ac .
*/
execvpe(progr, av, envp);
Err:
/* */
perror(firstfound ? firstfound: progr);
/* free(firstfound),firstfound = NULL
* (
* ) :
*/
if( cr && outp ) /* */
unlink(outp); /* */
exit(errno);
}
/* - */
/* , wait
* */
dowait(); /* */
/* */
signal(SIGINT, del); signal(SIGQUIT, quit);
return pid; /* */
}
. , 1992-95 - 275 - UNIX
/* PATH */
int execvpe(progr, av, envp) char *progr, **av, **envp;
{
char *path, *cp;
int try = 1;
register eacces = 0;
char fullpath[256]; /* */
firstfound = NULL;
if((path = getenv("PATH")) == NULL )
path = ".:/bin:/usr/bin:/etc";
/* : ? */
cp = strchr(progr, '/') ? "" : path;
do{ /* */
cp = execat(cp, progr, fullpath);
retry:
fprintf(stderr, " \"%s\"\n", fullpath );
execve(fullpath, av, envp);
/* ,
* . - . */
switch( errno ){ /* ? */
case ENOEXEC: /* */
callshell(fullpath, av, envp);
return (-1);
case ETXTBSY: /* */
if( ++try > 5 ) return (-1);
sleep(try); goto retry;
case EACCES: /* */
if(firstfound == NULL)
firstfound = strdup(fullpath);
eacces++; break;
case ENOMEM: /* */
case E2BIG:
return (-1);
}
}while( cp );
if( eacces ) errno = EACCES;
return (-1);
}
/* path name */
static char *execat(path, name, buf)
register char *path, *name;
char *buf; /* */
{
register char *s = buf;
while(*path && *path != LIM )
*s++ = *path++; /* */
if( s != buf ) *s++ = '/';
while( *name )
*s++ = *name++; /* */
*s = '\0';
return ( *path ? ++path /* LIM */ : NULL );
}
. , 1992-95 - 276 - UNIX
/* */
void callshell(progr, av, envp) char *progr, **av, **envp;
{
register i; char *sh; char *newav[MAXARGS+2];
int fd; char first = 0;
if((fd = open(progr, O_RDONLY)) < 0 )
sh = "/bin/sh";
else{
read(fd, &first, 1); close(fd);
sh = (first == '#') ? "/bin/csh" : "/bin/sh";
}
newav[0] = "Shellscript"; newav[1] = progr;
for(i=1; av[i]; i++)
newav[i+1] = av[i];
newav[i+1] = NULL;
printf( " %s\n", sh );
execve(sh, newav, envp);
}
/* , . */
void dowait(){
int ws; int pid;
while((pid = wait( &ws)) > 0 ){
if( WIFEXITED(ws)){
printf( " %d %d\n",
pid, WEXITSTATUS(ws));
}else if( WIFSIGNALED(ws)){
printf( " %d %d\n",
pid, WTERMSIG(ws));
if(WCOREDUMP(ws)) printf( " core\n" );
/* core - adb */
}else if( WIFSTOPPED(ws)){
printf( " %d %d\n",
pid, WSTOPSIG(ws));
}
}
}
. , 1992-95 - 277 - UNIX
/* . ,
* .
*/
void glob(dir, args, indx, str /* */, quote )
char *args[], *dir; int *indx; char *str;
char quote; /* , str */
{
static char globchars[] = "*?[";
char *p; char **start = &args[ *indx ];
short nglobbed = 0;
register struct dirent *dirbuf;
DIR *fd; extern DIR *opendir();
/* : */
if( *str == '\\' ){ str++; goto noGlob; }
/* $NAME */
if( *str == '$' && quote != '\'' ){
char *s = getenv(str+1);
if( s ) str = s;
}
/* : */
if( quote ) goto noGlob;
for( p=str; *p; p++ ) /* ? */
if( strchr(globchars, *p))
goto doGlobbing;
noGlob:
args[ (*indx)++ ] = strdup(str);
return;
doGlobbing:
if((fd = opendir (dir)) == NULL){
fprintf(stderr, "Can't read %s\n", dir); return;
}
while ((dirbuf = readdir (fd)) != NULL ) {
if (dirbuf->d_ino == 0) continue;
if (strcmp (dirbuf->d_name, ".") == 0 ||
strcmp (dirbuf->d_name, "..") == 0) continue;
if( match( dirbuf->d_name, str)){
args[ (*indx)++ ] = strdup(dirbuf->d_name);
nglobbed++;
}
}
closedir(fd);
if( !nglobbed){
printf( "%s: no match\n", str);
goto noGlob;
}else{ /* */
qsort(start, nglobbed, sizeof (char *), cmps);
}
}
. , 1992-95 - 278 - UNIX
/* */
int parse(s) register char *s;
{
int i; register char *p;
char tmp[80]; /* */
char c;
/* */
for(i=0; arg[i]; i++) free(arg[i]), arg[i] = NULL;
if( fin ) free(fin ), fin = NULL;
if( fout ) free(fout), fout = NULL;
rout = 0;
/* */
for( i=0 ;; ){
char quote = '\0';
/* - */
while((c = *s) && isspace(c)) s++;
if( !c ) break;
/* */
p = tmp;
if(*s == '\'' || *s == '"' ){
/* */
quote = *s++; /* */
while((c = *s) != '\0' && c != quote){
if( c == '\\' ){ /* */
c = *++s;
if( !c ) break;
}
*p++ = c; ++s;
}
if(c == '\0')
fprintf(stderr, " %c\n", quote);
else s++; /* */
. , 1992-95 - 279 - UNIX
} else
while((c = *s) && !isspace(c)){
if(c == '\\') /* */
if( !(c = *++s))
break /* while */;
*p++ = c; s++;
}
*p = '\0';
/* ,
* /. sh csh
* > <
* >< .
*/
p = tmp; /* */
if( *p == '>'){ /* */
p++;
if( fout ) free(fout), rout = 0; /* */
if( *p == '>' ){ rout |= APPEND; p++; }
if( *p == '&' ){ rout |= ERRTOO; p++; }
if( !*p ){
fprintf(stderr, " >\n");
fout = NULL; rout = 0;
} else fout = strdup(p);
} else if( *p == '<' ){ /* */
p++;
if( fin ) free(fin); /* */
if( !*p ){
fprintf(stderr, " <\n");
fin = NULL;
} else fin = strdup(p);
} else /* */
glob( ".", arg, &i, p, quote );
}
arg[i] = NULL; return i;
}
/* */
void setuser(){
int uid = getuid(); /* , */
char *user = "mr. Nobody"; /* */
char *home = "/tmp"; /* */
struct passwd *pp = getpwuid( uid );
if( pp != NULL ){
if(pp->pw_name && *pp->pw_name ) user = pp->pw_name;
if( *pp->pw_dir ) home = pp->pw_dir;
}
setenv("USER", user); setenv("HOME", home);
}
void setcwd(){ /* */
char cwd[512];
getwd(cwd); setenv( "CWD", cwd );
}
. , 1992-95 - 280 - UNIX
void main(ac, av, ev) char *av[], *ev[]; {
int argc; /* */
char *prompt; /* */
setuser(); setcwd();
signal(SIGINT, SIG_IGN);
setbuf(stdout, NULL); /* */
for(;;){
prompt = getenv( "prompt" ); /* setenv prompt -->\ */
printf( prompt ? prompt : "@ ");/* */
if( gets(cmd) == NULL /* at EOF */ ) exit(0);
argc = parse(cmd);
if( !argc) continue;
if( !strcmp(arg[0], "exit" )) exit(0);
if( !strcmp(arg[0], "cd" )){
char *d = (argc==1) ? getenv("HOME"):arg[1];
if(chdir(d) < 0)
printf( " %s\n", d );
else setcwd();
continue;
}
if( !strcmp(arg[0], "echo" )){
register i; FILE *fp;
if( fout ){
if((fp = fopen(fout, rout & APPEND ? "a":"w"))
== NULL) continue;
} else fp = stdout;
for(i=1; i < argc; i++ )
fprintf( fp, "%s%s", arg[i], i == argc-1 ? "\n":" ");
if( fp != stdout ) fclose(fp);
continue;
}
if( !strcmp(arg[0], "setenv" )){
if( argc == 1 ) printenv();
else if( argc == 2 ) setenv( arg[1], "" );
else setenv( arg[1], arg[2]);
continue;
}
cmdExec(arg[0], (char **) arg, environ, fin, fout, rout);
}
}
. , 1992-95 - 281 - UNIX
/* -----------------------------------------------------------*/
/* */
void printenv(){
char *e[40]; register i = 0; char *p, **q = e;
do{
p = e[i] = environ[i]; i++;
} while( p );
#ifdef SORT
qsort( e, --i /* */, sizeof(char *), cmps);
#endif
while( *q )
printf( "%s\n", *q++ );
}
/* name */
static char *envcmp(name, evstr) char *name, *evstr;
{
char *p; int code;
if((p = strchr(evstr, '=')) == NULL ) return NULL; /* error ! */
*p = '\0'; /* */
code = strcmp(name, evstr);
*p = '='; /* */
return code==0 ? p+1 : NULL;
}
/* */
void setenv( name, value ) char *name, *value;
{
static malloced = 0; /* 1, environ */
char *s, **p, **newenv;
int len, change_at = (-1), i;
/* name environ- ? */
for(p = environ; *p; p++ )
if(s = envcmp(name, *p)){ /* */
if((len = strlen(s)) >= strlen(value)){
/* */
strcpy(s, value); return;
}
/* environ ... */
if( malloced ){
free( *p ); *p = str3spl(name, "=", value);
return;
}
/* environ- */
change_at = p - environ; /* */
break;
}
. , 1992-95 - 282 - UNIX
/* environ-. change_at == (-1),
* */
for(p=environ, len=0; *p; p++, len++ );
/* */
if( change_at < 0 ) len++;
if((newenv = (char **) malloc( sizeof(char *) * (len+1)))
== (char **) NULL) return;
for(i=0; i < len+1; i++ ) newenv[i] = NULL; /* */
/* environ */
if( !malloced ) /* environ ( ) */
for(i=0; environ[i]; i++ ) newenv[i] = strdup(environ[i]);
else for(i=0; environ[i]; i++ ) newenv[i] = environ[i];
/* , */
/* , : */
if( change_at >= 0 ){
free( newenv[change_at] );
newenv[change_at] = str3spl(name, "=", value);
} else { /* */
newenv[len-1] = str3spl(name, "=", value);
}
/* environ */
if( malloced ) free( environ );
environ = newenv; malloced++;
qsort( environ, len, sizeof(char *), cmps);
}
/* :
unsetenv _ - ;
exit N -
N ( );
*/
. , 1992-95 - 283 - UNIX
7. .
" " ( " ") -
, -
, , , , -
, , ,
...
7.1. , ""
. "",
. ,
list.txt
7.2. , .
7.3. , , -
/ .
.
7.4. . -
, , . "-
" , , :
#include <ctype.h>
#include <stdio.h>
const int YES=1, NO=0;
main(){
register int inWord = NO; /* */
int words = 0, c;
while((c = getchar()) != EOF)
if(isspace(c) || c == '\n') inWord = NO;
else if(inWord == NO){
inWord = YES; ++words;
}
printf("%d \n", words);
}
const. . -
#define YES 1
- , .. ;
- ;
- .
main(){ /* cc 00.c -o 00 -lm */
double sqrt(double);
const double sq12 = sqrt(12.0);
#define SQRT2 sqrt(2.0)
double x;
x = sq12 * sq12 * SQRT2 * SQRT2; /* @1 */
sq12 = 3.4641; /* @2 */
printf("%g %g\n", sq12, x);
}
#define @1
x = sq12 * sq12 * sqrt(2.0) * sqrt(2.0);
sqrt. const
.
. , 1992-95 - 284 - UNIX
, @2 -
.
, -
isWord, . -
( ):
#include <ctype.h>
#include <stdio.h>
int wordLength, inWord, words; /* = 0 */
char aWord[128], *wrd;
void space (c){}
void letter (c){ wordLength++; *wrd++ = c; }
void begWord(c){ wordLength=0; inWord=1;
wrd=aWord; words++; letter(c); }
void endWord(c){ inWord=0; *wrd = '\0';
printf(" '%s' %d\n",
aWord, wordLength); }
void (*sw[2][2])() = {
/* !isWord */ { space, endWord },
/* isWord */ { begWord, letter }
/* !inWord inWord */
};
#define isWord(c) (isalnum(c) || c=='-' || c=='_')
main(){ register c;
while((c = getchar()) != EOF)
(*sw[isWord(c)][inWord])(c);
printf("%d \n", words);
}
7.5. , (.. :
0 -, 1 - -, ...,
).
7.6. , in
out.
7.7. , ,
.
7.8. , .
7.9. , -
, . :
(malloc) ; -
.
: .
: ;
.
7.10. , , -
.
.
7.11. ,
.
. , 1992-95 - 285 - UNIX
7.12. ,
.
uniq UNIX. :
#include <stdio.h> /* char *gets(); */
char buf1[4096], buf2[4096];
char *this = buf1, *prev = buf2;
main(){
long nline =0L; char *tmp;
while( gets(this)){
if(nline){ /* */
if( strcmp(this, prev)) /* ? */
puts(prev);
}
/* : */ tmp=prev; prev=this; this=tmp;
nline++; /* */
}/* endwhile */
if( nline ) puts(prev);
/* */
}
7.13. , ( )
, ,
.
7.14. ,
.
( - ,
!),
, :
/* */
void untab(s) register char *s;
{
char newstr[256]; /* */
char *src = s;
int n; /* */
register dstx; /* x */
for(dstx = 0; *s != '\0'; s++)
if( *s == '\t'){
for(n = 8 - dstx % 8 ; n > 0 ; n--)
newstr[dstx++] = ' ';
}else newstr[dstx++] = *s;
newstr[dstx] = '\0';
strcpy(src, newstr); /* */
}
7.15. , .
. , 1992-95 - 286 - UNIX
void tabify(){
int chr;
int icol, ocol; /* input/output columns */
for(icol = ocol = 0; ; ){
if((chr = getchar()) == EOF)
break;
switch(chr){
case ' ':
icol++;
break;
case '\n':
case '\r':
ocol = icol = 0;
putchar(chr);
break;
case '\t':
icol += 8;
icol &= ~07; /* icol -= icol % 8; */
break;
default:
while(((ocol + 8) & ~07) <= icol){
#ifdef NOTDEF
if(ocol + 1 == icol)
break;
/* ' ' '\t' */
#endif
putchar('\t');
ocol += 8;
ocol &= ~07;
}
while(ocol < icol){
putchar(' ');
ocol++;
}
putchar(chr);
icol++;
ocol++;
break;
}
}
}
7.16. ,
. , -
!
7.17. , 60 .
.
. , 1992-95 - 287 - UNIX
7.18. , -
, 60 .
7.19. , .
( ).
60.
7.20. , ,
.. ,
40- (, 80 ).
7.21. , n ( n
). , n (
).
#include <stdio.h>
/* ... untab(); ... */
void process(char name[], int n, int spacesOnly){
char line[256]; int length, shift, nline = 0;
char newname[128]; FILE *fpin, *fpout;
if((fpin = fopen(name, "r")) == NULL){
fprintf(stderr, " %s\n", name);
return;
}
sprintf(newname, "_%s", name); /* */
if((fpout = fopen(newname, "w")) == NULL){
fprintf(stderr, " %s\n",
newname); fclose(fpin); return;
}
while(fgets(line, sizeof line, fpin)){ ++nline;
if((length = strlen(line)) &&
line[length-1] == '\n')
line[--length] = '\0'; /* '\n' */
untab(line); /* */
for(shift=0; line[shift] != '\0' && shift < n ;
++shift)
if(spacesOnly && line[shift] != ' ') break;
if(*line && shift != n ) /* */
fprintf(stderr,
" #%d \n", nline);
fprintf(fpout, "%s\n", line+shift);
/* fputs(line+n, fpout);
* ..
*/
}
fclose(fpin); fclose(fpout);
}
void main(int argc, char **argv){
if( argc != 3 ) exit(1);
process(argv[2], atoi(argv[1]) /* 8 */, 1);
exit(0);
}
7.22. , : -
, - .
main(). - 40 .
7.23. . ,
strcmp() , .
, , !
. , 1992-95 - 288 - UNIX
, ,
strcmp().
7.24. ,
.
7.25.
( ).
/* : dihotomia */
#include <stdio.h>
struct elem {
char *name; /* */
int value;
} table[] = {
/* */
{ "andrew", 17 },
{ "bill", 23 },
{ "george", 55 },
{ "jack", 54 },
{ "jaw", 43 },
{ "john", 33 },
{ "mike", 99 },
{ "paul", 21 },
{ "sue", 66 }, /* SIZE - 2 */
{ NULL, -1 }, /* SIZE - 1 */
/* NULL */
};
#define SIZE (sizeof(table) / sizeof(struct elem))
/* */
struct elem *find(s, table, size)
char *s; /* ? */
struct elem table[]; /* ? */
int size; /* size */
{
register top, bottom, middle;
register code;
top = 0; /* */
bottom = size - 1; /* : "sue" */
while( top <= bottom ){
middle = (top + bottom) / 2; /* */
/* */
code = strcmp( s, table[middle].name ) ;
if( code > 0 ){
top = middle + 1;
}else if( code < 0 ){
bottom = middle - 1;
}else return &table[ middle ];
}
return (struct elem *) NULL; /* */
}
. , 1992-95 - 289 - UNIX
/* */
void printtable(tbl) register struct elem *tbl; {
for( ; tbl->name != NULL ; tbl++ ){