windows-nt/Source/XPSP1/NT/base/subsys/posix/client/tst/tstnpipe.c

421 lines
7.7 KiB
C
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
#include <nt.h>
#include <ntrtl.h>
#include <string.h>
#include <signal.h>
#include <errno.h>
#include <sys/wait.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include "tsttmp.h" // defines DbgPrint as printf
extern int errno;
VOID npipe0(char *);
VOID npipe1(char *);
VOID npipe2(char *);
VOID npipe3(char *);
VOID npipe4(char *);
VOID npipe5(VOID);
//
// 'tstnpipe named.pip'.
//
// The directory /psx/test is used as the base directory. The zero-length
// file named 'named.pip must exist in that directory.
//
char
nulltouch(char *f)
{
return 'a';
}
int
main(int argc, char *argv[])
{
if (argc != 2) {
DbgPrint("Usage: 'tstnpipe named.pip'\n");
return 1;
}
ASSERT(strcmp(argv[1],"named.pip") == 0);
npipe0(argv[1]);
npipe1(argv[1]);
npipe2(argv[1]);
npipe3(argv[1]);
npipe4(argv[1]);
npipe5();
return 1;
}
VOID
npipe0(char *f)
{
int rc,wfd,rfd;
char buf[512];
DbgPrint("npipe0:++ %s\n",f);
nulltouch(f);
//
// Open for read with NONBLOCK. Open should complete
// without delay.
//
rfd = open(f, O_RDONLY | O_NONBLOCK);
ASSERT(rfd != -1);
//
// Since there is no data in pipe, read should complete and
// return 0 as the byte count.
//
rc = read(rfd,buf,512);
ASSERT(rc == 0);
//
// Open for write with NONBLOCK. Should succeed
//
wfd = open(f,O_WRONLY | O_NONBLOCK);
ASSERT(wfd != -1);
rc = write(wfd,"Hello World\n",13);
ASSERT(rc == 13);
rc = read(rfd,buf,512);
ASSERT(rc == 13 && (strcmp(buf,"Hello World\n") == 0 ));
rc = close(rfd);
ASSERT(rc != -1);
rc = close(wfd);
ASSERT(rc != -1);
//
// Open for write with NONBLOCK. Should fail since read handle was
// closed.
//
wfd = open(f,O_WRONLY | O_NONBLOCK);
ASSERT(wfd == -1 && errno == ENXIO);
DbgPrint("npipe0:--\n");
}
VOID
npipe1(char *f)
{
int rc,wfd,rfd,stat_loc;
pid_t child;
char buf[512];
DbgPrint("npipe1:++ %s\n",f);
wfd = open("foobar.bad",O_WRONLY);
nulltouch(f);
child = fork();
nulltouch(f);
//
// Make sure that in the simple case,
// the named pipe open protocol works
//
if ( child == 0 ) {
rfd = open(f,O_RDONLY);
ASSERT(rfd != -1);
rc = read(rfd,buf,512);
ASSERT(rc == 13 && (strcmp(buf,"Hello World\n") == 0 ));
_exit(rc);
}
wfd = open(f,O_WRONLY);
ASSERT(wfd != -1);
rc = write(wfd,"Hello World\n",13);
ASSERT(rc == 13);
rc = waitpid(child,&stat_loc,0);
ASSERT(rc == child && WIFEXITED(stat_loc) && WEXITSTATUS(stat_loc) == 13);
rc = close(wfd);
ASSERT(rc != -1);
//
// Open for write with NONBLOCK. Should fail since read handle was
// closed by childs process exit.
//
wfd = open(f,O_WRONLY | O_NONBLOCK);
ASSERT(wfd == -1 && errno == ENXIO);
DbgPrint("npipe1:--\n");
}
VOID
npipe2(char *f)
{
int rc,wfd,rfd,rfd2,stat_loc;
pid_t child1,child2;
char buf[512];
DbgPrint("npipe2:++ %s\n",f);
nulltouch(f);
child1 = fork();
nulltouch(f);
//
// Make sure that if we have a case where two readers open the
// pipe, one writers open will catch them both
//
if ( child1 == 0 ) {
nulltouch(f);
child2 = fork();
nulltouch(f);
if ( child2 == 0 ) {
rfd2 = open(f,O_RDONLY);
ASSERT(rfd != -1);
rc = read(rfd2,buf,512);
ASSERT(rc == 13 && (strcmp(buf,"Hello World\n") == 0 ));
_exit(rc);
}
rfd = open(f,O_RDONLY);
ASSERT(rfd != -1);
rc = waitpid(child2,&stat_loc,0);
ASSERT(rc == child2 && WIFEXITED(stat_loc) && WEXITSTATUS(stat_loc) == 13);
_exit(WEXITSTATUS(stat_loc));
}
sleep(30);
wfd = open(f,O_WRONLY);
ASSERT(wfd != -1);
rc = write(wfd,"Hello World\n",13);
ASSERT(rc == 13);
rc = waitpid(child1,&stat_loc,0);
ASSERT(rc == child1 && WIFEXITED(stat_loc) && WEXITSTATUS(stat_loc) == 13);
rc = close(wfd);
ASSERT(rc != -1);
//
// Open for write with NONBLOCK. Should fail since read handle was
// closed by childs process exit.
//
wfd = open(f,O_WRONLY | O_NONBLOCK);
ASSERT(wfd == -1 && errno == ENXIO);
DbgPrint("npipe2:--\n");
}
void
npipe3_handler(
IN int sig
)
{
int wfd;
ASSERT(sig == SIGUSR1);
wfd = open("named.pip",O_WRONLY | O_NONBLOCK);
ASSERT(wfd == -1 && errno == ENXIO);
}
VOID
npipe3(char *f)
{
int rc,wfd,rfd,stat_loc;
pid_t child;
struct sigaction act;
DbgPrint("npipe3:++ %s\n",f);
nulltouch(f);
child = fork();
nulltouch(f);
//
// While child is blocked in open, terminate him with a signal
// and make sure everything is ok.
//
if ( child == 0 ) {
rfd = open(f,O_RDONLY);
ASSERT(FALSE);
}
sleep(20);
rc = kill(child,SIGKILL);
ASSERT(rc==0);
rc = waitpid(child,&stat_loc,0);
ASSERT(rc == child && WIFSIGNALED(stat_loc) && WTERMSIG(stat_loc) == SIGKILL);
wfd = open(f,O_WRONLY | O_NONBLOCK);
ASSERT(wfd == -1 && errno == ENXIO);
//
// Now Try again. This time send a signal that child catches. He should
// come back from his open with EINTR and the pipe should not be left
// open.
//
nulltouch(f);
child = fork();
nulltouch(f);
//
// While child is blocked in open, terminate him with a signal
// and make sure everything is ok.
//
act.sa_flags = 0;
sigfillset(&act.sa_mask);
act.sa_handler = npipe3_handler;
rc = sigaction(SIGUSR1, &act, NULL);
ASSERT( rc == 0 );
if ( child == 0 ) {
rfd = open(f,O_RDONLY);
ASSERT(rfd == -1 && errno == EINTR);
wfd = open(f,O_WRONLY | O_NONBLOCK);
ASSERT(wfd == -1 && errno == ENXIO);
rc = kill(getpid(),SIGKILL);
ASSERT(FALSE);
}
sleep(20);
rc = kill(child,SIGUSR1);
ASSERT(rc==0);
rc = waitpid(child,&stat_loc,0);
ASSERT(rc == child && WIFSIGNALED(stat_loc) && WTERMSIG(stat_loc) == SIGKILL);
wfd = open(f,O_WRONLY | O_NONBLOCK);
ASSERT(wfd == -1 && errno == ENXIO);
DbgPrint("npipe3:--\n");
}
VOID
npipe4(char *f)
{
int rc,rfd;
int fildes[2];
off_t off;
DbgPrint("npipe4:++ %s\n",f);
nulltouch(f);
//
// Open for read with NONBLOCK. Open should complete
// without delay.
//
rfd = open(f,O_RDONLY | O_NONBLOCK);
ASSERT(rfd != -1);
//
// lseek on named pipe should fail
//
off = (off_t) 1;
errno = 0;
off = lseek(rfd,off,SEEK_SET);
ASSERT(off == -1 && errno == ESPIPE);
rc = close(rfd);
ASSERT(rc != -1);
rc = pipe(fildes);
ASSERT(rc == 0);
//
// lseek on regular pipe should fail
//
off = (off_t)11;
errno = 0;
off = lseek(fildes[0],off,SEEK_SET);
ASSERT(off == -1 && errno == ESPIPE);
off = 10;
errno = 0;
off = lseek(fildes[1],off,SEEK_SET);
ASSERT(off == -1 && errno == ESPIPE);
DbgPrint("npipe4:--\n");
}
VOID
npipe5()
{
int rc,rfd;
off_t off;
DbgPrint("npipe5:++\n");
rc = mkfifo("xpipe.pip",0);
ASSERT(rc==0 || ( rc == -1 && errno == EEXIST ) );
if ( rc == -1 ) {
DbgPrint("npipe5: **** Warning Fifo Exists ****\n");
}
//
// Open for read with NONBLOCK. Open should complete
// without delay.
//
rfd = open("xpipe.pip",O_RDONLY | O_NONBLOCK);
ASSERT(rfd != -1);
//
// lseek on named pipe should fail
//
off = 1;
errno = 0;
off = lseek(rfd,off,SEEK_SET);
ASSERT(off == -1 && errno == ESPIPE);
rc = close(rfd);
ASSERT(rc != -1);
DbgPrint("npipe5:--\n");
}