int __system(const char *command) { pid_t pid; sig_t intsave, quitsave; sigset_t mask, omask; int pstat; char *argp[] = {"sh", "-c", NULL, NULL}; if (!command) /* just checking... */ return(1); argp[2] = (char *)command; sigemptyset(&mask); sigaddset(&mask, SIGCHLD); sigprocmask(SIG_BLOCK, &mask, &omask); switch (pid = vfork()) { case -1: /* error */ sigprocmask(SIG_SETMASK, &omask, NULL); return(-1); case 0: /* child */ sigprocmask(SIG_SETMASK, &omask, NULL); execve(_PATH_BSHELL, argp, environ); _exit(127); } intsave = (sig_t) bsd_signal(SIGINT, SIG_IGN); quitsave = (sig_t) bsd_signal(SIGQUIT, SIG_IGN); pid = waitpid(pid, (int *)&pstat, 0); sigprocmask(SIG_SETMASK, &omask, NULL); (void)bsd_signal(SIGINT, intsave); (void)bsd_signal(SIGQUIT, quitsave); return (pid == -1 ? -1 : pstat); }
int exec_and_wait(char ** argp) { pid_t pid; sig_t intsave, quitsave; sigset_t mask, omask; int pstat; sigemptyset(&mask); sigaddset(&mask, SIGCHLD); sigprocmask(SIG_BLOCK, &mask, &omask); switch (pid = vfork()) { case -1: /* error */ sigprocmask(SIG_SETMASK, &omask, NULL); return(-1); case 0: /* child */ sigprocmask(SIG_SETMASK, &omask, NULL); execve(argp[0], argp, environ); _exit(127); } intsave = (sig_t) bsd_signal(SIGINT, SIG_IGN); quitsave = (sig_t) bsd_signal(SIGQUIT, SIG_IGN); pid = waitpid(pid, (int *)&pstat, 0); sigprocmask(SIG_SETMASK, &omask, NULL); (void)bsd_signal(SIGINT, intsave); (void)bsd_signal(SIGQUIT, quitsave); return (pid == -1 ? -1 : pstat); }
int system_nosh(const char *command) { pid_t pid; sig_t intsave, quitsave; sigset_t mask, omask; int pstat; char buffer[255]; char *argp[32]; char *next = buffer; char *tmp; int i = 0; if (!command) /* just checking... */ return(1); /* * The command to argp splitting is from code that was * reverted in Change: 11b4e9b2 */ if (strnlen(buffer, sizeof(buffer) - 1) == sizeof(buffer) - 1) { LOGE("command line too long while processing: %s", command); errno = E2BIG; return -1; } strcpy(buffer, command); // Command len is already checked. while ((tmp = strsep(&next, " "))) { argp[i++] = tmp; if (i == 32) { LOGE("argument overflow while processing: %s", command); errno = E2BIG; return -1; } } argp[i] = NULL; sigemptyset(&mask); sigaddset(&mask, SIGCHLD); sigprocmask(SIG_BLOCK, &mask, &omask); switch (pid = vfork()) { case -1: /* error */ sigprocmask(SIG_SETMASK, &omask, NULL); return(-1); case 0: /* child */ sigprocmask(SIG_SETMASK, &omask, NULL); execve(argp[0], argp, environ); _exit(127); } intsave = (sig_t) bsd_signal(SIGINT, SIG_IGN); quitsave = (sig_t) bsd_signal(SIGQUIT, SIG_IGN); pid = waitpid(pid, (int *)&pstat, 0); sigprocmask(SIG_SETMASK, &omask, NULL); (void)bsd_signal(SIGINT, intsave); (void)bsd_signal(SIGQUIT, quitsave); return (pid == -1 ? -1 : pstat); }
void ignoresig(int signo, int vforked) { if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) bsd_signal(signo, SIG_IGN); if (!vforked) sigmode[signo - 1] = S_HARD_IGN; }
void intr (int sig) { (void) sig; /* Quiet unused warning */ bsd_signal (SIGALRM, SIG_IGN); alarm (0); siglongjmp (toplevel, -1); }
void onsig(int signo) { bsd_signal(signo, onsig); if (signo == SIGINT && trap[SIGINT] == NULL) { onint(); return; } gotsig[signo - 1] = 1; pendingsigs++; }
// The difference between the two is that bsd_signal() is guaranteed to // provide reliable signal semantics, that is: a) the disposition of the // signal is not reset to the default when the handler is invoked; b) // delivery of further instances of the signal is blocked while the signal // handler is executing; and c) if the handler interrupts a blocking sys- // tem call, then the system call is automatically restarted. A portable // application cannot rely on signal(2) to provide these guarantees. // // bsd_signal - signal handling with BSD semantics // On modern Linux systems, bsd_signal() and signal(2) are equivalent. // But on older systems, signal(2) provided unreliable signal semantics; // see signal(2) for details. // bsd_signal 和 signal 语义一样,在现代操作系统上 int main(void) { // rt_sigaction(SIGUSR1, {0x8048515, [USR1], SA_RESTART}, {SIG_DFL, [], 0}, 8) = 0 __sighandler_t handler = bsd_signal(SIGINT, sig_int); if (handler == SIG_ERR) { err_sys("can't catch SIGINT"); } else { fprintf(stderr, "old handler= %p\n", handler); } //if (sysv_signal(SIGINT, sig_int) == SIG_ERR) // rt_sigaction(SIGINT, {0x8048535, [], SA_INTERRUPT|SA_NODEFER|SA_RESETHAND}, {SIG_DFL, [], 0}, 8) = 0 //if (signal(SIGUSR1, sig_usr) == SIG_ERR) // rt_sigaction(SIGUSR1, {0x8048515, [USR1], SA_RESTART}, {SIG_DFL, [], 0}, 8) = 0 for (; ;) pause(); return 0; }
int main(int argc, char **argv) { struct tftphdr *tp; struct passwd *pw; struct options *opt; struct sockaddr_in myaddr; struct sockaddr_in servaddr; int n = 0; int on = 1; int fd = 0; int pid, xx; int c; int setrv; int timeout = 900; /* Default timeout */ // char *user = "******"; /* Default user */ char *user = "******"; /* Default user */ __progname = basename(argv[0]); openlog(__progname, LOG_PID | LOG_NDELAY, LOG_DAEMON); while ((c = getopt(argc, argv, "csu:r:t:")) != -1) switch (c) { case 'c': cancreate = 1; break; case 's': secure = 1; break; case 't': timeout = atoi(optarg); break; case 'u': user = optarg; break; case 'r': for ( opt = options ; opt->o_opt ; opt++ ) { if ( !strcasecmp(optarg, opt->o_opt) ) { opt->o_opt = ""; /* Don't support this option */ break; } } if ( !opt->o_opt ) { syslog(LOG_ERR, "Unknown option: %s", optarg); exit(1); } break; default: usage(); break; } for (; optind != argc; optind++) { if (dirs) dirs = realloc(dirs, (ndirs+2) * sizeof (char *)); else dirs = calloc(ndirs+2, sizeof(char *)); if (dirs == NULL) { syslog(LOG_ERR, "malloc: %m"); exit(1); } dirs[n++] = argv[optind]; dirs[n] = NULL; ndirs++; } if (secure) { if (ndirs == 0) { syslog(LOG_ERR, "no -s directory"); exit(1); } if (ndirs > 1) { syslog(LOG_ERR, "too many -s directories"); exit(1); } if (chdir(dirs[0])) { syslog(LOG_ERR, "%s: %m", dirs[0]); exit(1); } } pw = getpwnam(user); if (!pw) { syslog(LOG_ERR, "no user %s: %m", user); exit(1); } #if KAM_LATER // not needed if not by inetd if (ioctl(fd, FIONBIO, &on) < 0) { syslog(LOG_ERR, "ioctl(FIONBIO): %m"); exit(1); } #else // bind to default tftp port if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { exit(1); } //printf("fd=%d\n",fd); on = 1; setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void*)&on, sizeof(on)); bzero(&servaddr, sizeof(servaddr)); /* zero the struct */ servaddr.sin_family = AF_INET; /* host byte order */ servaddr.sin_port = htons(IPPORT_TFTP);/* short, network byte order */ servaddr.sin_addr.s_addr = INADDR_ANY; /* auto-fill with my IP */ if (bind(fd, (struct sockaddr *)&servaddr, sizeof(struct sockaddr)) == -1) { close(fd); exit(1); } #endif /* This means we don't want to wait() for children */ bsd_signal(SIGCHLD, SIG_IGN); // Set up signal handlers so we can clear up our child processes // signal(SIGTERM, signal_handler); signal(SIGHUP, signal_handler); signal(SIGINT, signal_handler); signal(SIGCHLD, signal_handler); signal(SIGKILL, signal_handler); xx = fork(); if(xx==-1) { syslog(LOG_CRIT, "Could not fork() tftpd into background\n"); closelog(); close(fd); exit(1); } if(xx != 0) { // Parent... printf("tftp in background pid=%d\n",xx); exit(0); } do { fromlen = sizeof (from); // printf("recvfrom %d: ",fd); #if KAM_LATER n = myrecvfrom(fd, buf, sizeof (buf), 0, (struct sockaddr *)&from, &fromlen, &myaddr); #else bzero(&myaddr, sizeof(struct sockaddr_in)); myaddr.sin_family = AF_INET; myaddr.sin_port = htons(IPPORT_TFTP); n = recvfrom(fd, buf, sizeof (buf), 0, (struct sockaddr *)&from, &fromlen); #endif if (n < 0) { syslog(LOG_ERR, "recvfrom: %m"); exit(1); } //printf("%d bytes ",n); #if KAM_LATER //#ifdef HAVE_TCPWRAPPERS /* Verify if this was a legal request for us. This has to be done before the chroot, while /etc is still accessible. */ request_init(&wrap_request, RQ_DAEMON, __progname, RQ_FILE, fd, RQ_CLIENT_SIN, &from, RQ_SERVER_SIN, &myaddr, 0); sock_methods(&wrap_request); if ( hosts_access(&wrap_request) == 0 ) { if ( deny_severity != -1 ) syslog(deny_severity, "connection refused from %s", inet_ntoa(from.sin_addr)); exit(1); /* Access denied */ } else if ( allow_severity != -1 ) { syslog(allow_severity, "connect from %s", inet_ntoa(from.sin_addr)); } #endif /* * Now that we have read the message out of the UDP * socket, we fork and go back to listening to the * socket. */ pid = fork(); if (pid < 0) { syslog(LOG_ERR, "fork: %m"); exit(1); /* Return to inetd, just in case */ } } while ( pid > 0 ); /* Parent process continues... */ /* Child process: handle the actual request here */ /* Chroot and drop privileges */ if (secure && chroot(".")) { syslog(LOG_ERR, "chroot: %m"); exit(1); } #ifdef HAVE_SETREGID setrv = setregid(pw->pw_gid, pw->pw_gid); #else setrv = setegid(pw->pw_gid) || setgid(pw->pw_gid); #endif #ifdef HAVE_SETREUID setrv = setrv || setreuid(pw->pw_uid, pw->pw_uid); #else /* Important: setuid() must come first */ setrv = setrv || setuid(pw->pw_uid) || (geteuid() != pw->pw_uid && seteuid(pw->pw_uid)); #endif if ( setrv ) { syslog(LOG_ERR, "cannot drop privileges: %m"); exit(1); } /* Close file descriptors we don't need */ from.sin_family = AF_INET; alarm(0); #if KAM_LATER close(fd); close(1); #endif /* Process the request... */ peer = socket(AF_INET, SOCK_DGRAM, 0); if (peer < 0) { syslog(LOG_ERR, "socket: %m"); exit(1); } myaddr.sin_port = htons(0); /* We want a new local port */ if (bind(peer, (struct sockaddr *)&myaddr, sizeof (myaddr)) < 0) { syslog(LOG_ERR, "bind: %m"); exit(1); } if (connect(peer, (struct sockaddr *)&from, sizeof(from)) < 0) { syslog(LOG_ERR, "connect: %m"); exit(1); } tp = (struct tftphdr *)buf; tp->th_opcode = ntohs(tp->th_opcode); if (tp->th_opcode == RRQ || tp->th_opcode == WRQ) { tftp(tp, n); } exit(0); }
int main(int argc, char **argv) { int i; int socketHandle; struct sockaddr_in socketInfo; pthread_t data_thread; if (argc != 2 || atoi(argv[1]) == 0) { printf("Usage: %s <port_number>\n", argv[0]); return -1; } // Initialize data for (i = 0; i < MAX_HISTORY; i++) data_history[i].timestamp = 0; pthread_create( &data_thread, NULL, data_thread_main, NULL); // Start the web server. bsd_signal(SIGINT, sig_handler); bsd_signal(SIGPIPE, SIG_IGN); // Main loop socketHandle = socket(AF_INET, SOCK_STREAM, 0); socketInfo.sin_family = AF_INET; // Use any address available to the system. This is a typical configuration for a server. // Note that this is where the socket client and socket server differ. // A socket client will specify the server address to connect to. socketInfo.sin_addr.s_addr = htonl(INADDR_ANY); // Translate long integer to network byte order. socketInfo.sin_port = htons(atoi(argv[1])); // Set port number // Bind the socket to a local socket address if( bind(socketHandle, (struct sockaddr *) &socketInfo, sizeof(struct sockaddr_in)) < 0) { close(socketHandle); perror("bind"); exit(EXIT_FAILURE); } listen(socketHandle, 1); printf("Entering main thread...\n"); int socketConnection; while (!shuttingdown_flag) { fd_set fds; FD_ZERO(&fds); FD_SET(socketHandle, &fds); int ret = select(socketHandle+1, &fds, NULL, NULL, NULL); if (ret >= 0 && FD_ISSET(socketHandle, &fds)) { printf("Accepting a new connection.\n"); socketConnection = accept(socketHandle, NULL, NULL); pthread_mutex_lock(&active_thread_count_mutex); active_thread_count += 1; pthread_mutex_unlock(&active_thread_count_mutex); int* thread_data = malloc(sizeof(int)); *thread_data = socketConnection; pthread_t child_thread; pthread_create( &child_thread, NULL, connection_thread_main, thread_data); } } // Close bind socket close(socketHandle); data_thread_shutdown_flag = 1; printf("Waiting on data thread to shutdown.\n"); pthread_join( data_thread, NULL ); printf("Waiting for active threads to return.\n"); pthread_mutex_lock(&active_thread_count_mutex); while (active_thread_count > 0) { // Make sure threads aren't just sleeping pthread_mutex_lock(&new_info_mutex); pthread_cond_broadcast(&new_info_cond); pthread_mutex_unlock(&new_info_mutex); pthread_cond_wait(&active_thread_returned_cond, &active_thread_count_mutex); } pthread_mutex_unlock(&active_thread_count_mutex); printf("Clean shutdown.\n"); return 0; }
/* * Send the requested file. */ int tftp_sendfile(int f, union sock_addr *peeraddr, int fd, const char *name, const char *mode) { struct tftphdr *ap; /* data and ack packets */ struct tftphdr *dp; int n; volatile int is_request; volatile u_short block; volatile int size, convert; volatile off_t amount; union sock_addr from; socklen_t fromlen; FILE *file; u_short ap_opcode, ap_block; startclock(); /* start stat's clock */ dp = r_init(); /* reset fillbuf/read-ahead code */ ap = (struct tftphdr *)ackbuf; convert = !strcmp(mode, "netascii"); file = fdopen(fd, convert ? "rt" : "rb"); block = 0; is_request = 1; /* First packet is the actual WRQ */ amount = 0; bsd_signal(SIGALRM, timer); do { if (is_request) { size = makerequest(WRQ, name, dp, mode) - 4; } else { /* size = read(fd, dp->th_data, SEGSIZE); */ size = readit(file, &dp, convert); if (size < 0) { nak(f, peeraddr, errno + 100, NULL); break; } dp->th_opcode = htons((u_short) DATA); dp->th_block = htons((u_short) block); } timeout = 0; (void)sigsetjmp(timeoutbuf, 1); if (trace) tpacket("sent", dp, size + 4); n = sendto(f, dp, size + 4, 0, &(peeraddr->sa), SOCKLEN(peeraddr)); if (n != size + 4) { perror("tftp: sendto"); goto abort; } read_ahead(file, convert); for (;;) { alarm(rexmtval); do { fromlen = sizeof(from); n = recvfrom(f, ackbuf, sizeof(ackbuf), 0, &from.sa, &fromlen); } while (n <= 0); alarm(0); if (n < 0) { perror("tftp: recvfrom"); goto abort; } sa_set_port(peeraddr, SOCKPORT(&from)); /* added */ if (trace) tpacket("received", ap, n); /* should verify packet came from server */ ap_opcode = ntohs((u_short) ap->th_opcode); ap_block = ntohs((u_short) ap->th_block); if (ap_opcode == ERROR) { printf("Error code %d: %s\n", ap_block, ap->th_msg); goto abort; } if (ap_opcode == ACK) { int j; if (ap_block == block) { break; } /* On an error, try to synchronize * both sides. */ j = synchnet(f); if (j && trace) { printf("discarded %d packets\n", j); } /* * RFC1129/RFC1350: We MUST NOT re-send the DATA * packet in response to an invalid ACK. Doing so * would cause the Sorcerer's Apprentice bug. */ } } if (!is_request) amount += size; is_request = 0; block++; } while (size == SEGSIZE || block == 1); abort: fclose(file); stopclock(); //if (amount > 0) // printstats("Sent", amount); return amount; }
/* * Receive a file. */ int tftp_recvfile(int f, union sock_addr *peeraddr, int fd, const char *name, const char *mode) { struct tftphdr *ap; struct tftphdr *dp; int n; volatile u_short block; volatile int size, firsttrip; volatile unsigned long amount; union sock_addr from; socklen_t fromlen; FILE *file; volatile int convert; /* true if converting crlf -> lf */ u_short dp_opcode, dp_block; startclock(); dp = w_init(); ap = (struct tftphdr *)ackbuf; convert = !strcmp(mode, "netascii"); file = fdopen(fd, convert ? "wt" : "wb"); block = 1; firsttrip = 1; amount = 0; bsd_signal(SIGALRM, timer); do { if (firsttrip) { size = makerequest(RRQ, name, ap, mode); firsttrip = 0; } else { ap->th_opcode = htons((u_short) ACK); ap->th_block = htons((u_short) block); size = 4; block++; } timeout = 0; (void)sigsetjmp(timeoutbuf, 1); send_ack: if (trace) tpacket("sent", ap, size); if (sendto(f, ackbuf, size, 0, &(peeraddr->sa), SOCKLEN(peeraddr)) != size) { alarm(0); perror("tftp: sendto"); goto abort; } write_behind(file, convert); for (;;) { alarm(rexmtval); do { fromlen = sizeof(from); n = recvfrom(f, dp, PKTSIZE, 0, &from.sa, &fromlen); } while (n <= 0); alarm(0); if (n < 0) { perror("tftp: recvfrom"); goto abort; } sa_set_port(peeraddr, SOCKPORT(&from)); /* added */ if (trace) tpacket("received", dp, n); /* should verify client address */ dp_opcode = ntohs((u_short) dp->th_opcode); dp_block = ntohs((u_short) dp->th_block); if (dp_opcode == ERROR) { printf("Error code %d: %s\n", dp_block, dp->th_msg); goto abort; } if (dp_opcode == DATA) { int j; if (dp_block == block) { break; /* have next packet */ } /* On an error, try to synchronize * both sides. */ j = synchnet(f); if (j && trace) { printf("discarded %d packets\n", j); } if (dp_block == (block - 1)) { goto send_ack; /* resend ack */ } } } /* size = write(fd, dp->th_data, n - 4); */ size = writeit(file, &dp, n - 4, convert); if (size < 0) { nak(f, peeraddr, errno + 100, NULL); break; } amount += size; } while (size == SEGSIZE); abort: /* ok to ack, since user */ ap->th_opcode = htons((u_short) ACK); /* has seen err msg */ ap->th_block = htons((u_short) block); (void)sendto(f, ackbuf, 4, 0, (struct sockaddr *)peeraddr, SOCKLEN(peeraddr)); write_behind(file, convert); /* flush last buffer */ fclose(file); stopclock(); //if (amount > 0) // printstats("Received", amount); return amount; }
__sighandler_t signal(int s, __sighandler_t f) { return bsd_signal(s,f); }
int main(int argc, char **argv) { void (*rcSig)(int); pthread_t hThread; char szName[1024]; int i; int rc; /* * Set up the signal handlers. */ rcSig = bsd_signal(SIGALRM, SigHandler); if (rcSig != SIG_ERR) rcSig = bsd_signal(SIGCHLD, SigHandler); if (rcSig == SIG_ERR) { fprintf(stderr, "bsd_signal failed: %s\n", strerror(errno)); return 1; } if (argc == 2) /* testing... */ { siginterrupt(SIGALRM, 1); siginterrupt(SIGCHLD, 1); } /* * Kick off a thread that will signal us like there was no tomorrow. */ g_hMainThread = pthread_self(); rc = pthread_create(&hThread, NULL, ThreadProc, NULL); if (rc != 0) { fprintf(stderr, "pthread_create failed: %s\n", strerror(rc)); return 1; } /* * Do path related stuff. */ snprintf(szName, sizeof(szName), "%s-test2", argv[0]); for (i = 0; i < 100*1000*1000; i++) { struct stat St; int fd; rc = stat(argv[0], &St); if (rc == 0 || errno != EINTR) rc = stat(szName, &St); if (errno == EINTR && rc != 0) { printf("iteration %d: stat: %u\n", i, errno); break; } fd = open(szName, O_CREAT | O_RDWR, 0666); if (errno == EINTR && fd < 0) { printf("iteration %d: open: %u\n", i, errno); break; } close(fd); rc = unlink(szName); if (errno == EINTR && rc != 0) { printf("iteration %d: unlink: %u\n", i, errno); break; } /* Show progress info */ if ((i % 100000) == 0) { printf("."); if ((i % 1000000) == 0) printf("[%d/%ld/%ld]\n", i, g_cSigs, g_cSigsOther); fflush(stdout); } } g_fShutdown = 1; if (rc) printf("No EINTR in %d iterations - system is working nicely!\n", i); NanoSleep(10000000); return rc ? 1 : 0; }
int main (int argc, char *argv[]) { struct sockaddr_in s_in; int c; int pargc; char **pargv; while ((c = getopt (argc, argv, "Vv")) != -1) { switch (c) { case 'v': verbose = 1; break; case 'V': /* Print version and configuration to stdout and exit */ printf ("%s\n", TFTP_CONFIG_STR); exit (0); default: fprintf (stderr, "Usage: %s [-v] [host]\n", argv[0]); exit (EX_USAGE); } } pargc = argc - (optind - 1); pargv = argv + (optind - 1); sp = getservbyname ("tftp", "udp"); if (sp == 0) { /* Use canned values */ fprintf (stderr, "tftp: tftp/udp: unknown service, faking it...\n"); sp = xmalloc (sizeof (struct servent)); sp->s_name = (char *) "tftp"; sp->s_aliases = NULL; sp->s_port = htons (IPPORT_TFTP); sp->s_proto = (char *) "udp"; exit (1); } f = socket (AF_INET, SOCK_DGRAM, 0); if (f < 0) { perror ("tftp: socket"); exit (3); } bzero ((char *) &s_in, sizeof (s_in)); s_in.sin_family = AF_INET; if (bind (f, (struct sockaddr *) &s_in, sizeof (s_in)) < 0) { perror ("tftp: bind"); exit (1); } mode = MODE_DEFAULT; bsd_signal (SIGINT, intr); if (pargc > 1) { if (sigsetjmp (toplevel, 1) != 0) exit (0); setpeer (pargc, pargv); } if (sigsetjmp (toplevel, 1) != 0) (void) putchar ('\n'); #ifdef WITH_READLINE #ifdef HAVE_READLINE_HISTORY_H using_history (); #endif #endif command (); return 0; /* Never reached */ }