Example #1
0
File: if.c Project: quajo/v6shell
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);
}
Example #2
0
File: if.c Project: quajo/v6shell
/*
 * 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;
}
Example #3
0
File: if.c Project: quajo/v6shell
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;
}
Example #4
0
File: tester.c Project: jre/upart
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);
}
Example #5
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;
}
Example #6
0
File: if.c Project: quajo/v6shell
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;
}
Example #7
0
File: pay.c Project: xczs666/space
/*
 * 改进:使用多线程 线程池 测试客户端的信息 查看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  ---------- */
Example #8
0
File: pay.c Project: xczs666/space
/* 
 * ===  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;
}
Example #9
0
File: fd2.c Project: quajo/v6shell
/*
 * 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;
}
Example #10
0
File: fd2.c Project: quajo/v6shell
static void
usage(void)
{

	err(FC_ERR, FD2_USAGE, getmyname());
}
Example #11
0
/*
 * 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);
			}
		}
	}
}
Example #12
0
File: getopt.c Project: jre/upart
/*
 * 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);
}