/* * Copyright (c) 1995, 1996 Gunther Schadow. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #include #include #include #include #include #include #include #include #define A_STX 0x02 #define A_CAN 0x18 static void reaper(int sig); static int recv_oob(sockinetbuf &isb); main(int argc, char *argv[]) { char *service = argv[1]; sockinetbuf serve_sb(sockbuf::sock_stream); ssignal(SIGCHLD, reaper, 0); serve_sb.bind(INADDR_ANY,service,"tcp"); cout << "accepting connections at" << serve_sb.localport() << '%' << serve_sb.localhost() << endl; serve_sb.listen(1); while(TRUE) { iosockinet client_io(serve_sb.accept()); if(fork() != 0) { client_io->close(); continue; } serve_sb.close(); cout << "connection made from" << client_io->peerhost() << endl; /* * Prepare for exceptions */ cerr << "file descriptor: " << client_io->operator int() << endl; #ifdef hpux pid_t minuspid = -getpid(); if(ioctl(client_io->operator int(), SIOCSPGRP, &minuspid) == FAIL) #else if(fcntl(client_io->operator int(), F_SETOWN, getpid()) == FAIL) #endif { cerr << "F_SETOWN: " << sys_errlist[errno] << endl; exit(0); } atsignal(SIGURG, 0) { cerr << "SIGURG trapped" << endl; int c = recv_oob(*client_io.rdbuf()); switch(c) { case A_STX: cerr << "message restarted" << endl; goto restart; case A_CAN: cerr << "transaction cancelled by server" << endl; exit(1); case FAIL: exit(2); default: cerr << "undefined out of band signal " << (int)c << endl; exit(3); } } restart: char *s; client_io.gets(&s, 0x04); cout << s << endl; client_io.clear(); client_io << s; client_io.flush(); client_io->shutdown(sockbuf::shut_write); cout << "end" << endl; exit(0); } } static void reaper(int sig) { int status; pid_t pid; cout << "reaper called by signal " << sig << " `" << sys_siglist[sig] << "'" << endl; while((pid = wait3(&status, WNOHANG, 0)) > 0) { if(WIFEXITED(status)) { cout << "process " << pid << " exited with " << WEXITSTATUS(status) << endl; } else if(WIFSIGNALED(status)) { int tsig = WTERMSIG(status); cout << "process " << pid << " received signal " << tsig << " `" << sys_siglist[tsig] << "'" << endl; } else if(WIFSTOPPED(status)) { int ssig = WSTOPSIG(status); cout << "process " << pid << " stopped by signal " << ssig << " `" << sys_siglist[ssig] << "'" << endl; kill(pid, SIGCONT); } } } static int recv_oob(sockinetbuf &isb) { int atmark = FALSE; char waist[1024]; int c = 0; do { if(ioctl((int)isb, SIOCATMARK, &atmark) == FAIL) { cerr << "SIOCATMARK: " << sys_errlist[errno] << endl; return FAIL; } if(atmark) break; if(read((int)isb, waist, 1024) == 0) { cerr << "connection closed by client" << endl; return FAIL; } } while(TRUE); if(recv((int)isb, &c, 1, MSG_OOB) < 1) { cerr << "connection closed by client" << endl; return FAIL; } return c; }