static void doex(bool forked) { char **xap, **xav; if (ap < 2 || ap > ac) /* should never (but can) be true */ err(FC_ERR, FMT2S, getmyname(), ERR_AVIINVAL); xav = xap = &av[ap]; while (*xap != NULL) { if (forked && equal(*xap, "}")) break; xap++; } if (forked && xap - xav > 0 && !equal(*xap, "}")) err(FC_ERR, FMT3S, getmyname(), av[ap - 1], ERR_BRACE); *xap = NULL; if (xav[0] == NULL) { if (forked) err(FC_ERR, FMT3S, getmyname(),av[ap - 1],ERR_COMMAND); else /* Currently unreachable; do not remove. */ err(FC_ERR, FMT2S, getmyname(), ERR_COMMAND); } /* Invoke the ":" or "exit" special command. */ if (equal(xav[0], ":")) EXIT(SH_TRUE); if (equal(xav[0], "exit")) { (void)lseek(FD0, (off_t)0, SEEK_END); EXIT(SH_TRUE); } (void)err_pexec(xav[0], xav); }
/* * NAME * if - conditional command * * SYNOPSIS * if [expression [command [arg ...]]] * * DESCRIPTION * See the if(1) manual page for full details. */ int main(int argc, char **argv) { bool re; /* return value of expr() */ setmyerrexit(&ut_errexit); setmyname(argv[0]); setmypid(getpid()); ifeuid = geteuid(); /* * Set-ID execution is not supported. */ if (ifeuid != getuid() || getegid() != getgid()) err(FC_ERR, FMT2S, getmyname(), ERR_SETID); (void)sasignal(SIGCHLD, SIG_DFL); if (argc > 1) { ac = argc; av = argv; ap = 1; re = expr(); if (re && ap < ac) doex(!FORKED); } else re = false; return re ? SH_TRUE : SH_FALSE; }
static char * nxtarg(bool reterr) { char *nap; if (ap < 1 || ap > ac) /* should never (but can) be true */ err(FC_ERR, FMT2S, getmyname(), ERR_AVIINVAL); if (ap == ac) { if (reterr) { ap++; return NULL; } err(FC_ERR, FMT3S, getmyname(), av[ap - 1], ERR_ARGUMENT); } nap = av[ap]; ap++; return nap; }
int main(int argc, char *argv[]) { void (*mode)(FILE *); FILE *idx; int opt; myname = getmyname(argv[0]); mode = testfiles; while ((opt = getopt(argc, argv, "chrtv")) != -1) { switch (opt) { case 'c': mode = cleanfiles; break; case 'r': mode = regenfiles; break; case 't': mode = testfiles; break; case 'v': verbose = 1; break; default: printf("usage: %s [-chr] -f path -u path\n" " -c clean test output\n" " -h show this message and exit.\n" " -r regenerate test output.\n" " -t run tests (the default)\n" " -v verbose mode\n", myname); exit(EXIT_FAILURE); } } changedir(); if ((idx = fopen(TESTINDEX_PATH, "r")) == NULL) fail("failed to open %s for reading", TESTINDEX_PATH); (*mode)(idx); return (0); }
/* * Convert a string value into an int integer value. */ bool strtoint(const char *string, int *integer) { long lint; char *lintbad; const char *name; name = getmyname(); /* * Fail if the specified string or integer is (or points to) NULL. */ errno = 0; if (string == NULL || integer == NULL) { errno = EINVAL; fd_print(FD2, FMT3S, name, "strtoint", strerror(errno)); if (integer != NULL) *integer = 0; return false; } lint = strtol(string, &lintbad, 10); if (*string == EOS || *lintbad != EOS) { errno = EINVAL; if (EQUAL(name, "if")) fd_print(FD2, FMT3S, name, string, ERR_NOTINTEGER); *integer = 0; return false; } if ((errno == ERANGE && (lint == LONG_MAX || lint == LONG_MIN)) || (lint > INT_MAX || lint < INT_MIN)) { errno = ERANGE; if (EQUAL(name, "if")) fd_print(FD2, FMT3S, name, string, ERR_RANGE); *integer = 0; return false; } *integer = (int)lint; return true; }
static bool e3(void) { bool re; pid_t cpid, tpid; int cstat, d; char *a, *b; if ((a = nxtarg(RETERR)) == NULL) err(FC_ERR, FMT3S, getmyname(), av[ap - 2], ERR_EXPR); /* * Deal w/ parentheses for grouping. */ if (equal(a, "(")) { re = expr(); if (!equal(nxtarg(RETERR), ")")) err(FC_ERR, FMT3S, getmyname(), a, ERR_PAREN); return re; } /* * Execute { command [arg ...] } to obtain its exit status. */ if (equal(a, "{")) { if ((cpid = fork()) == -1) err(FC_ERR, FMT2S, getmyname(), ERR_FORK); if (cpid == 0) /**** Child! ****/ doex(FORKED); else { /**** Parent! ****/ tpid = wait(&cstat); while ((a = nxtarg(RETERR)) != NULL && !equal(a, "}")) ; /* nothing */ if (a == NULL) ap--; return (tpid == cpid && cstat == 0) ? true : false; } } /* * file existence/permission tests */ if (equal(a, "-e")) return ifaccess(nxtarg(!RETERR), F_OK); if (equal(a, "-r")) return ifaccess(nxtarg(!RETERR), R_OK); if (equal(a, "-w")) return ifaccess(nxtarg(!RETERR), W_OK); if (equal(a, "-x")) return ifaccess(nxtarg(!RETERR), X_OK); /* * file existence/type tests */ if (equal(a, "-d")) return ifstat1(nxtarg(!RETERR), S_IFDIR); if (equal(a, "-f")) return ifstat1(nxtarg(!RETERR), S_IFREG); if (equal(a, "-h")) return ifstat1(nxtarg(!RETERR), S_IFLNK); if (equal(a, "-s")) return ifstat1(nxtarg(!RETERR), F_GZ); if (equal(a, "-t")) { /* Does the descriptor refer to a terminal device? */ b = nxtarg(RETERR); if (b == NULL || *b == EOS) err(FC_ERR, FMT3S, getmyname(), a, ERR_DIGIT); if (*b >= '0' && *b <= '9' && *(b + 1) == EOS) { d = *b - '0'; if (IS_DIGIT(d, *b)) return isatty(d) != 0; } err(FC_ERR, FMT3S, getmyname(), b, ERR_NOTDIGIT); } /* * binary comparisons */ if ((b = nxtarg(RETERR)) == NULL) err(FC_ERR, FMT3S, getmyname(), a, ERR_OPERATOR); if (equal(b, "=")) return equal(a, nxtarg(!RETERR)); if (equal(b, "!=")) return !equal(a, nxtarg(!RETERR)); if (equal(b, "-ot")) return ifstat2(a, nxtarg(!RETERR), F_OT); if (equal(b, "-nt")) return ifstat2(a, nxtarg(!RETERR), F_NT); if (equal(b, "-ef")) return ifstat2(a, nxtarg(!RETERR), F_EF); err(FC_ERR, FMT3S, getmyname(), b, ERR_OPUNKNOWN); /*NOTREACHED*/ return false; }
/* * 改进:使用多线程 线程池 测试客户端的信息 查看connect后自动分配的信息 * 来报文写到文件中 * 使用进程监控状态自动重启 * 系统守护进程 */ int main ( int argc, char *argv[] ) { struct addrinfo *ailist; int listenfd; int unixfd; char *host; char buf[128]; #ifdef DEBUG /* 进程和客户端无关 后台执行 */ signal(SIGHUP,SIG_IGN);//终端推出 signal(SIGINT,SIG_IGN);//ctrl+C signal(SIGCLD,SIG_IGN);//子进程退出时发送的信号 if( fork() != 0 ) exit(0); else setpgrp(); #endif signal(SIGALRM,SIG_IGN);//子进程退出时发送的信号 /* 第一次执行 */ if(!sonpid) initson(); #if defined(Darwin) atexit(killson); #endif /* 自己的unix域连接 */ // sleep(1); // if((unixfd=cli_conn(UNIXFILE))<0) // err_sys( "cli_conn error" ); /* 父进程获取外部数据 由wrfd写到子进程 由子进程处理业务 */ //setenvadd( "LD_LIBRARY_PATH", "/home/cbs/priv/xcz/project/src", 1 ); /* 获取本机主机名 */ if( (host=getmyname( )) == NULL ) err_sys( "get host name err" ); printf("%s\n", host); /* 根据主机名和端口号初始化sockaddr结构 */ // preconnect( host, "12345", SOCK_STREAM, &ailist ); // free( host ); // host = NULL; // // printf("%hu\n", ntohs((( struct sockaddr_in * )( ailist->ai_addr ))->sin_port)); // // struct in_addr saddr; // // saddr=(( struct sockaddr_in * )( ailist->ai_addr ))->sin_addr; // // struct sockaddr a; // // a=*( ailist->ai_addr ); // // printf("AF_INET %d %d\n", a.sa_family, AF_INET); // /* 侦听所有网卡 */ // (( struct sockaddr_in * )(ailist->ai_addr))->sin_addr.s_addr=htonl( INADDR_ANY ); // /* 打印一些信息 */ // zl_connect_out_func( ailist->ai_addr ); // /* 绑定端口 声明最大连接数 */ // if ( ( listenfd = initserver( ailist->ai_socktype, ailist->ai_addr, ailist->ai_addrlen, 200 ) ) < 0 ) // { // err_sys( "initserver err" ); // } // freeaddrinfo( ailist ); struct sockaddr_in addr; struct sockaddr *addrp; int socktype; socklen_t addrlen; memset( &addr, 0x00, sizeof(addr) ); addr.sin_family = AF_INET; addr.sin_port = htons(12345); addr.sin_addr.s_addr = htonl(INADDR_ANY); addrlen=sizeof(struct sockaddr); addrp=(struct sockaddr *)&addr; /* 绑定端口 声明最大连接数 */ if ( ( listenfd = initserver( SOCK_STREAM, addrp, addrlen, 100 ) ) < 0 ) { err_sys( "initserver err" ); } zl_connect_out_func( addrp ); unsigned long addrsize; int connectfd; int n,i; char *p=NULL; char recvbuf[SIZERCV+1]; addrsize = sizeof( struct sockaddr ); if(0) { i=0; costtime(0); system("date"); while(++i<20000) { /* 自发送 测试unix域套接字效率 */ if((unixfd=cli_conn(UNIXFILE))<0) { printf("%s%d\n",AT,i); fflush(NULL); err_sys( "%scli_conn error %d", AT, unixfd ); } switch(i%7) { case 0: sprintf(buf,"%d 111",i); break; case 1: sprintf(buf,"%d 121",i); break; case 2: sprintf(buf,"%d 314",i); break; case 3: sprintf(buf,"%d 315",i); break; case 4: sprintf(buf,"%d 604",i); break; case 5: sprintf(buf,"%d 900",i); break; case 6: sprintf(buf,"%d 990",i); break; } if((n=write( unixfd, buf, strlen(buf) ))<0) printf("%s,send faild %s\n", AT, strerror(errno)); close( unixfd ); if(i%100==0) printf("%d %lf\n", i, costtime(1)); } system("date"); } while(1) { /* 这样单节点的accept对大并发的支持简直惨不忍睹 2w笔来账单纯接收不进行任何处理花了70s * 而使用select+多线程只需要10s 还是服务器运行在台式机虚拟机2核cpu 1G内存的情况下 */ if (( connectfd = accept( listenfd, NULL, ( socklen_t *)&addrsize ) ) == -1 ) { printf( "%saccept err", AT ); continue; } i=0; p=NULL; while( (n = recv( connectfd, recvbuf, SIZERCV, 0 )) > 0 ) { recvbuf[n]=0; if (p) p=realloc(p,strlen(p)+n+1); else p=malloc(n+1); strcpy( p+i, recvbuf ); i+=n; } close( connectfd ); if (n<0) printf("%s,recv out err %d\n", AT,n); // printf("%s %s\n", AT, p); n=0; do { if((unixfd=cli_conn(UNIXFILE))<0) { /* 来的数据太多 unix域套接字connect的时候 会refuse 重新尝试就好 * 经测试 也就尝试140次左右可connect成功 */ n++; if(!(n&0xFF))//256的倍数打印 printf( "%scli_conn error %d retried %d times", AT, unixfd, n ); continue; } }while(0); write(unixfd, p, i); close( unixfd ); free(p); p=NULL; } close( listenfd ); return EXIT_SUCCESS; } /* ---------- end of function main ---------- */
/* * === FUNCTION ====================================================================== * Name: listenout * Author: Chenzhi Xu * Created: 11/19/15 14:29:29 * Description: 侦听外部来报 * 当和外部使用中间件时,此函数接收来自中间件的数据 * 将数据传给儿子,由儿子处理数据,父亲只负责接收数据 * ===================================================================================== */ int listenout() { struct addrinfo *ailist; struct sockaddr_in addr; struct sockaddr *addrp; int socktype; socklen_t addrlen; int listensockfd; int listenunixfd; int nzero; char *host; #if defined(NZERO) nzero=NZERO; #elif defined(_SC_NZERO) nzero=sysconf(_SC_NZERO); #else #error NZERO undefined #endif /* 获取本机主机名 */ if( (host=getmyname( )) == NULL ) err_sys( "get host name err" ); printf("%s%s\n", AT, host); /* 根据主机名和端口号初始化sockaddr结构 */ // preconnect( host, "12344", SOCK_STREAM, &ailist ); // addrlen=ailist->ai_addrlen; // /* 直接取第一条记录 不考虑匹配多条的情况 */ // memcpy( &addr, ailist->ai_addr, addrlen ); // socktype=ailist->ai_socktype; // free( host ); // host = NULL; // freeaddrinfo( ailist ); // printf("%hu\n", ntohs((( struct sockaddr_in * )( ailist->ai_addr ))->sin_port)); // struct in_addr saddr; // saddr=(( struct sockaddr_in * )( ailist->ai_addr ))->sin_addr; // struct sockaddr a; // a=*( ailist->ai_addr ); // printf("AF_INET %d %d\n", a.sa_family, AF_INET); /* sock套接字 侦听内部其他系统的数据 * 外部使用中间件 中间件进程和此进程使用unix域套接字通讯 */ memset( &addr, 0x00, sizeof(addr) ); addr.sin_family = AF_INET; addr.sin_port = htons(12344); addr.sin_addr.s_addr = htonl(INADDR_ANY); addrlen=sizeof(struct sockaddr); addrp=(struct sockaddr *)&addr; /* 绑定端口 声明最大连接数 */ if ( ( listensockfd = initserver( SOCK_STREAM, addrp, addrlen, 100 ) ) < 0 ) { err_sys( "initserver err" ); } zl_connect_out_func( addrp ); /* 打开及设置keepalive内容 */ SocketKeepalive( listensockfd ); /* unix域套接字 */ if ((listenunixfd=serv_listen(UNIXFILE))<0) { printf("%s%d %s\n",AT, listenunixfd, strerror(errno)); err_sys("serv_listen error"); } /* 设置执行时关闭 */ set_cloexec( listensockfd ); set_cloexec( listenunixfd ); /* 设置进程优先级 */ // ni=getpriority(PRIO_PROCESS,0); // printf("%s,now nice=%d\n", AT, ni); //#ifndef Darwin nice(nzero/2); //#endif // setpriority(PRIO_PROCESS,0,nzero); printf("%snice=%d\n", AT, getpriority(PRIO_PROCESS,0)); // printf("%s,sockfd=%d unixfd=%d\n", AT, listensockfd, listenunixfd); if( SelectAndHandle( listensockfd, listenunixfd ) != 0 ) err_msg( "handle err" ); close( listensockfd ); close( listenunixfd ); return 0; }
/* * NAME * fd2 - redirect from/to file descriptor 2 * * SYNOPSIS * fd2 [-e] [-f file] [--] command [arg ...] * * DESCRIPTION * See the fd2(1) manual page for full details. */ int main(int argc, char **argv) { bool eopt; int efd, fd, nfd, ofd, opt; char *file; setmyerrexit(&ut_errexit); setmyname(argv[0]); setmypid(getpid()); /* * Set-ID execution is not supported. */ if (geteuid() != getuid() || getegid() != getgid()) err(FC_ERR, FMT2S, getmyname(), ERR_SETID); /* * File descriptors 0, 1, and 2 must be open. */ for (fd = 0; fd < 3; fd++) if (!fd_isopen(fd)) err(FC_ERR, "%s: %u: %s\n", getmyname(), (unsigned)fd, strerror(errno)); ofd = FD1, efd = FD2; eopt = false, file = NULL; while ((opt = getopt(argc, argv, ":ef:")) != -1) switch (opt) { case 'e': eopt = true; break; case 'f': file = optarg; break; default: usage(); } argc -= optind; argv += optind; if (argc < 1) usage(); if (file != NULL) { if ((nfd = open(file, O_WRONLY|O_APPEND|O_CREAT, 0666)) == -1) err(FC_ERR, FMT3S, getmyname(), file, ERR_CREATE); if (dup2(nfd, efd) == -1) err(FC_ERR, FMT2S, getmyname(), strerror(errno)); if (eopt && dup2(efd, ofd) == -1) err(FC_ERR, FMT2S, getmyname(), strerror(errno)); (void)close(nfd); } else { if (eopt) ofd = FD2, efd = FD1; if (dup2(ofd, efd) == -1) err(FC_ERR, FMT2S, getmyname(), strerror(errno)); } /* * Try to execute the specified command. */ (void)err_pexec(argv[0], argv); /*NOTREACHED*/ return FC_ERR; }
static void usage(void) { err(FC_ERR, FD2_USAGE, getmyname()); }
/* * Execute a file or path name w/ error handling. * This function never returns. */ void err_pexec(const char *file, char *const *argv) { long l; const char *f, *n; (void)pexec(file, argv); #ifdef DEBUG fd_print(FD2, "err_pexec: strerror(errno) == %s;\n", strerror(errno)); #endif f = (file == NULL) ? "(null)" : file; n = getmyname(); if (EQUAL(n, "glob6")) { if (errno == ENOEXEC) err(SH_ERR, FMT1S, ERR_NOSHELL); if (errno == E2BIG) err(SH_ERR, FMT1S, ERR_E2BIG); err(SH_ERR, FMT1S, ERR_GNOTFOUND); } else if (EQUAL(n, "sh6")) { if (errno == ENOEXEC) err(125, FMT1S, ERR_NOSHELL); if (errno == E2BIG) err(126, FMT2S, f, ERR_E2BIG); if (errno != ENOENT && errno != ENOTDIR) err(126, FMT2S, f, ERR_EXEC); err(127, FMT2S, f, ERR_NOTFOUND); } else { l = no_lnum ? -1 : get_lnum(); if (name != NULL) { if (l != -1) { if (errno == ENOEXEC) err(125,FMT4LS,n,name,l,f, ERR_NOSHELL); if (errno == E2BIG) err(126,FMT4LS,n,name, l, f, ERR_E2BIG); if (errno != ENOENT && errno != ENOTDIR) err(126,FMT4LS,n, name, l, f, ERR_EXEC); err(127, FMT4LS, n, name, l, f, ERR_NOTFOUND); } else { if (errno == ENOEXEC) err(125,FMT4S, n, name, f, ERR_NOSHELL); if (errno == E2BIG) err(126, FMT4S, n, name, f, ERR_E2BIG); if (errno != ENOENT && errno != ENOTDIR) err(126, FMT4S, n, name, f, ERR_EXEC); err(127, FMT4S, n, name, f, ERR_NOTFOUND); } } else { if (l != -1) { if (errno == ENOEXEC) err(125, FMT3LFS, n, l, f, ERR_NOSHELL); if (errno == E2BIG) err(126, FMT3LFS, n, l, f, ERR_E2BIG); if (errno != ENOENT && errno != ENOTDIR) err(126, FMT3LFS, n, l, f, ERR_EXEC); err(127, FMT3LFS, n, l, f, ERR_NOTFOUND); } else { if (errno == ENOEXEC) err(125, FMT3S, n, f, ERR_NOSHELL); if (errno == E2BIG) err(126, FMT3S, n, f, ERR_E2BIG); if (errno != ENOENT && errno != ENOTDIR) err(126, FMT3S, n, f, ERR_EXEC); err(127, FMT3S, n, f, ERR_NOTFOUND); } } } }
/* * getopt -- * Parse argc/argv argument vector. */ int getopt(int nargc, char * const *nargv, const char *options) { char *oli; /* option letter list index */ int optchar; static int posixly_correct = -1; if (options == NULL) return (-1); /* * Disable GNU extensions if POSIXLY_CORRECT is set or options * string begins with a '+'. */ if (posixly_correct == -1) posixly_correct = (getenv("POSIXLY_CORRECT") != NULL); if (*options == '+' || *options == '-') options++; /* * XXX Some GNU programs (like cvs) set optind to 0 instead of * XXX using optreset. Work around this braindamage. */ if (optind == 0) optind = optreset = 1; optarg = NULL; if (optreset || !*place) { /* update scanning pointer */ optreset = 0; if (optind >= nargc) { /* end of argument vector */ place = EMSG; return (-1); } if (*(place = nargv[optind]) != '-' || (place[1] == '\0' && strchr(options, '-') == NULL)) { place = EMSG; /* found non-option */ return (-1); } /* * If we have "-" do nothing, if "--" we are done. */ if (place[1] != '\0' && *++place == '-' && place[1] == '\0') { optind++; place = EMSG; return (-1); } } if ((optchar = (int)*place++) == (int)':' || (optchar == (int)'-' && *place != '\0') || (oli = strchr(options, optchar)) == NULL) { /* * If the user specified "-" and '-' isn't listed in * options, return -1 (non-option) as per POSIX. * Otherwise, it is an unknown option character (or ':'). */ if (optchar == (int)'-' && *place == '\0') return (-1); if (!*place) ++optind; if (PRINT_ERROR) fprintf(stderr, "%s: " ILLOPTCHAR "\n", getmyname(nargv[0]), optchar); optopt = optchar; return (BADCH); } if (*++oli != ':') { /* doesn't take argument */ if (!*place) ++optind; } else { /* takes (optional) argument */ optarg = NULL; if (*place) /* no white space */ optarg = place; else if (oli[1] != ':') { /* arg not optional */ if (++optind >= nargc) { /* no arg */ place = EMSG; if (PRINT_ERROR) fprintf(stderr, "%s: " RECARGCHAR "\n", getmyname(nargv[0]), optchar); optopt = optchar; return (BADARG); } else optarg = nargv[optind]; } place = EMSG; ++optind; } /* dump back option letter */ return (optchar); }