예제 #1
0
/*------------------------------------------------------------------------
 * xsh_nvram  -  shell command to list all items in NVRAM (Flash) or to
 *			display one item
 *------------------------------------------------------------------------
 */
shellcmd xsh_nvram(int nargs, char *args[])
{
	char	*value;			/* value to print		*/
	uint16	n;			/* iterates through items	*/
	uint16	count;			/* counts items found		*/
	struct nvram_tuple *tuple;

	/* insure nvram can be initialized */

	if (nvramInit() == SYSERR) {
		fprintf(stderr, "error: device does not appear to have nvram.\n");
		return 1;
	}

	/* For argument '--help', emit help about the 'nvram' command	*/

	if (nargs == 2 && strncmp(args[1], "--help", 7) == 0) {
		printf("Use: %s OPTION \n\n", args[0]);
		printf("Description:\n");
		printf("%s,%s\n", "\tDisplays a list of items in NVRAM ",
				"or the value of an item");
		printf("Options:\n");
		printf("\tlist\t\t\tdisplay all <NAME>=<VALUE> tuples\n");
		printf("\tget <NAME>\t\tdisplay the value of <NAME>\n");
		printf("\t--help\t display this help and exit\n");
		return 0;
	}


	if ( (nargs==2) && (strncmp(args[1], "list", 5)==0) ) {
		count = 0;
		for (n = 0; n < NVRAM_NHASH; n++) {
			tuple = nvram_tuples[n];
			if (tuple == NULL) {
				continue;
			}
			do {
				printf("%s\n", tuple->pair);
				count++;
			} while ((tuple = tuple->next) != NULL);
		}
		printf("%d pairs occupt %d bytes (%d bytes remain unused)\n",
			   count, nvram_header->length,
			   NVRAM_SIZE - nvram_header->length);
			return 0;
	} else if ( (nargs == 3) && (strncmp(args[1], "get", 4) == 0) ) {
		value = nvramGet(args[2]);
		if (value != 0) {
			printf("%s\n", nvramGet(args[2]));
			return 0;
		} else {
			fprintf(stderr, "error: no NVRAM binding\n");
			return 1;
		}
	}
	fprintf(stderr, "%s: incorrect arguments\n", args[0]);
	fprintf(stderr, "Try '%s --help' for more information\n",
			args[0]);
	return 1;
}
예제 #2
0
/**
 * Initialize virtual ethernet device structures.
 * @param devptr TTY device table entry
 * @return OK if device is intialized successfully
 */
devcall vlanInit(device *devptr)
{
    struct ether *ethptr;

    /* Initialize structure pointers */
    ethptr = &ethertab[devptr->minor];
    bzero(ethptr, sizeof(struct ether));
    ethptr->dev = devptr;
    ethptr->csr = (struct bcm4713 *)devptr->csr;
    /* Physical ethernet device to which the VLAN attaches */
    ethptr->phy = (device *)&devtab[ETH0];

    ethptr->errors = 0;
    ethptr->state = ETH_STATE_DOWN;
    ethptr->rxRingSize = ETH_RX_RING_ENTRIES;
    ethptr->txRingSize = ETH_TX_RING_ENTRIES;
    ethptr->mtu = ETH_MTU;

    ethptr->isema = semcreate(0);
    ethptr->istart = 0;
    ethptr->icount = 0;
    ethptr->ovrrun = 0;
    ethptr->rxOffset = sizeof(struct rxHeader);

    /* Lookup MAC in NVRAM, and store it in ether dev struct. */
    /* Modify first octet with device minor and set local admin bit */
    colon2mac(nvramGet("et0macaddr"), ethptr->devAddress);
    ethptr->devAddress[0] |= ((uchar)devptr->minor << 2) | ETH_LOCAL_MAC;

    ethptr->interruptMask = IMASK_DEF;

    /* As there is only one DMA ring for the physical ethernet, and
     * none for virtual interfaces, certain values in the ether struct
     * are set to invalid
     */
    ethptr->rxBufs = (struct ethPktBuffer **)ETH_INVALID;
    ethptr->txBufs = (struct ethPktBuffer **)ETH_INVALID;
    ethptr->rxRing = (struct dmaDescriptor *)ETH_INVALID;
    ethptr->txRing = (struct dmaDescriptor *)ETH_INVALID;

    return OK;
}
예제 #3
0
파일: nvram.c 프로젝트: JamesLinus/xinu
/**
 * Change the variable name to value. If name does not exist, create it,
 * otherwise replace the old value with the new.
 * @param *name  name to modify
 * @param *value value to set name
 * @return OK on successful change, SYSERR on failure
 */
devcall nvramSet(char *name, char *value)
{
    struct nvram_tuple *tuple;
    ulong length, offset;

    if (OK != nvramInit())
    {
        return SYSERR;
    }

    length = sizeof(struct nvram_tuple) + strnlen(name, NVRAM_STRMAX)
        + 1 + strnlen(value, NVRAM_STRMAX);

    /* check if name is already defined somewhere */
    /* if so unset, so we can reset */
    if (nvramGet(name) != NULL)
    {
        nvramUnset(name);
    }

    /* get enough space for both to be rounded up with \0 stored */
    if (NULL == (tuple = (struct nvram_tuple *)memget(length)))
    {
        return SYSERR;
    }

    /* copy name into memory */
    offset = 0;
    strncpy(tuple->pair, name, strnlen(name, NVRAM_STRMAX));
    offset += strnlen(name, NVRAM_STRMAX);
    strncpy(tuple->pair + offset, "=", 1);
    offset += 1;
    strncpy(tuple->pair + offset, value, strnlen(value, NVRAM_STRMAX));
    offset += strnlen(value, NVRAM_STRMAX);
    strncpy(tuple->pair + offset, "\0", 1);

    /* store pointer to name in nvram_tuple struct */
    nvramInsert(tuple);

    return OK;
}
예제 #4
0
/**
 * Shell command (netup) to start a network interface.
 * @param nargs  number of arguments in args array
 * @param args   array of arguments
 * @return OK for success, SYSERR for syntax error
 */
shellcmd xsh_netup(int nargs, char *args[])
{
    int descrp;
    struct netaddr ip;
    struct netaddr mask;
    struct netaddr gateway;
    char *str_ip, *str_mask, *str_gateway;
    char nvramLookup[DEVMAXNAME + NVRAM_STRMAX];

    /* Enable interrupts */
    enable();

    /* Help */
    if ((2 == nargs) && (0 == strncmp(args[1], "--help", 7)))
    {
        usage(args[0]);
        return SHELL_OK;
    }

    /* Parse device */
    if (nargs > 1)
    {
        descrp = getdev(args[1]);
        if (SYSERR == descrp)
        {
            fprintf(stderr, "%s is not a valid device.\n", args[1]);
            return SHELL_ERROR;
        }
    }
    else
    {
        /* assume first ethernet interface */
        descrp = (ethertab[0].dev)->num;
    }

    if (5 == nargs)
    {
        /* grab string data */
        str_ip = args[2];
        str_mask = args[3];
        str_gateway = args[4];
    }
    else if (nargs < 3)
    {
        /* lookup information in nvram */
        bzero(nvramLookup, DEVMAXNAME + NVRAM_STRMAX);
        sprintf(nvramLookup, "%s_%s", (ethertab[0].dev)->name,
                NET_LAN_IPADDR);
#if NVRAM
        str_ip = nvramGet(nvramLookup);
        if (NULL == str_ip)
        {
            str_ip = nvramGet("lan_ipaddr");
        }
#else
        str_ip = NULL;
#endif                          /* NVRAM */

        bzero(nvramLookup, DEVMAXNAME + NVRAM_STRMAX);
        sprintf(nvramLookup, "%s_%s", (ethertab[0].dev)->name,
                NET_SUBNET_MASK);
#if NVRAM
        str_mask = nvramGet(nvramLookup);
        if (NULL == str_mask)
        {
            str_mask = nvramGet("lan_netmask");
        }
#else
        str_mask = NULL;
#endif                          /* NVRAM */

#if NVRAM
        str_gateway = nvramGet(NET_GATEWAY);
        if (NULL == str_gateway)
        {
            str_gateway = nvramGet("lan_gateway");
        }
#else
        str_gateway = NULL;
#endif                          /* NVRAM */
    }
    else
    {
        fprintf(stderr, "Invalid number of arguments\n");
        return SHELL_ERROR;
    }

    /* Make sure we have valid IPv4 style parameters */
    if (NULL == str_ip)
    {
        str_ip = "0.0.0.0";
    }

    if (NULL == str_mask)
    {
        str_mask = "0.0.0.0";
    }

    if (NULL == str_gateway)
    {
        str_gateway = "0.0.0.0";
    }

    /* Parse IP */
    if (SYSERR == dot2ipv4(str_ip, &ip))
    {
        fprintf(stderr, "%s is not a valid IPv4 address.\n", str_ip);
        return SHELL_ERROR;
    }

    /* Parse Mask */
    if (SYSERR == dot2ipv4(str_mask, &mask))
    {
        fprintf(stderr, "%s is not a valid IPv4 address mask.\n",
                str_mask);
        return SHELL_ERROR;
    }

    /* Parse Gateway */
    if (SYSERR == dot2ipv4(str_gateway, &gateway))
    {
        fprintf(stderr, "%s is not a valid IPv4 address.\n", str_gateway);
        return SHELL_ERROR;
    }

    if (SYSERR == netUp(descrp, &ip, &mask, &gateway))
    {
        fprintf(stderr, "Failed to start network interface on %s\n",
                args[1]);
        return SHELL_ERROR;
    }

    printf("%s is %s with netmask %s (gateway: %s)\n",
           devtab[descrp].name, str_ip, str_mask, str_gateway);

    return SHELL_OK;
}
예제 #5
0
/**
 * Interpret ond act on an HTTP POST request of the config.html page.
 * @param webptr pointer to the HTTP device
 */
int postConfig(struct http *webptr)
{
    int cntr, curlen, valuelen;
    bool nvram_altered;
    char *name;
    char *value, *curval;

    /* Set flag to false initially */
    nvram_altered = FALSE;

    /* Check the content of the POST */
    if (*webptr->content != NULL)
    {
        /* Find the name and value for each variable */
        name = NULL;
        value = NULL;
        for (cntr = 0; cntr < webptr->contentlen; cntr++)
        {
            /* Setup name pointer if not set */
            if (NULL == name)
            {
                name = (webptr->content + cntr);
            }

            /* Replace all plus symbols with spaces */
            if ('+' == *(webptr->content + cntr))
            {
                *(webptr->content + cntr) = ' ';
            }
            /* Check for equals, signifies end of name */
            else if ('=' == *(webptr->content + cntr))
            {
                /* Change the char to terminate the string */
                *(webptr->content + cntr) = '\0';

                /* Setup the value pointer */
                value = (webptr->content + (cntr + 1));
            }
            /* Check for ampersand, signifies end of value */
            else if ('&' == *(webptr->content + cntr))
            {
                /* Change the char to terminate the string */
                *(webptr->content + (cntr)) = '\0';

                curval = nvramGet(name);
                if (NULL != curval)
                {
                    curlen = strnlen(curval, NVRAM_STRMAX);
                    valuelen = strnlen(value, NVRAM_STRMAX);
                    if ((curlen != valuelen) ||
                        (0 != memcmp(curval, value, valuelen)))
                    {
                        nvramSet(name, value);
                        nvram_altered = TRUE;
                    }
                }
                else
                {
                    nvramSet(name, value);
                    nvram_altered = TRUE;
                }

                /* Reset pointers */
                curval = NULL;
                name = NULL;
                value = NULL;
            }
        }

        /* Check for last variable found since end of buffer was reached */
        curval = nvramGet(name);
        if (NULL != curval)
        {
            curlen = strnlen(curval, NVRAM_STRMAX);
            valuelen = strnlen(value, NVRAM_STRMAX);
            if ((curlen != valuelen) ||
                (0 != memcmp(curval, value, valuelen)))
            {
                nvramSet(name, value);
                nvram_altered = TRUE;
            }
        }
        else
        {
            nvramSet(name, value);
            nvram_altered = TRUE;
        }
    }

    if (nvram_altered)
    {
        if (SYSERR == nvramCommit())
        {
            return 1;
        }
        else
        {
            return 0;
        }
    }

    return 2;
}
예제 #6
0
/**
 * Finalize the configuration page and output it to the HTTP device.
 * @param devptr pointer to the current device for httpWrite calls
 */
int outputConfig(device *devptr, int flashSuccess)
{
    device *ethptr;
    struct http *webptr;
    int cntr;

    /* Format strings for output to underlying device */
    char *oneforall, *oneper, *formsubmit, *flashReport;
    flashReport = NULL;

    /* Pointers for nvramGet() return values */
    char *configDomainname, *configGatewayIP;
    char *configHostname, *configIP, *configSubnetMask;

    /* Size variables for NVRAM configuration options */
    int hostname_strsz, domainname_strsz, lan_ip_strsz;
    int subnet_mask_strsz, gate_ip_strsz;

    /* Lengths of NVRAM lookup strings + null termination character */
    hostname_strsz = strnlen(NET_HOSTNAME, NVRAM_STRMAX) + 1;
    domainname_strsz = strnlen(NET_DOMAINNAME, NVRAM_STRMAX) + 1;
    lan_ip_strsz = strnlen(NET_LAN_IPADDR, NVRAM_STRMAX) + 1;
    subnet_mask_strsz = strnlen(NET_SUBNET_MASK, NVRAM_STRMAX) + 1;
    gate_ip_strsz = strnlen(NET_GATEWAY, NVRAM_STRMAX) + 1;

    /* Setup device pointer */
    webptr = &httptab[devptr->minor];

    /* Setup local pointers to device character pointers */
    char *hostname_str = webptr->hostname_str;
    char *domainname_str = webptr->domainname_str;
    char *lan_ip_str = webptr->lan_ip_str;
    char *subnet_mask_str = webptr->subnet_mask_str;
    char *gate_ip_str = webptr->gate_ip_str;

    /* Zero out the nvram string lookup buffers */
    bzero(hostname_str, hostname_strsz + DEVMAXNAME);
    bzero(domainname_str, domainname_strsz + DEVMAXNAME);
    bzero(lan_ip_str, lan_ip_strsz + DEVMAXNAME);
    bzero(subnet_mask_str, subnet_mask_strsz + DEVMAXNAME);
    bzero(gate_ip_str, gate_ip_strsz + DEVMAXNAME);


    /* Configuration settings, 1 for all devices */
    oneforall =
        "<form method='POST' name='configform'"
        " action='config.html' target='_self'>"
        "<table align=center>"
        "<tr>"
        "<td>Gateway IP Address:</td>"
        "<td>"
        "<input type='text' name='%s'"
        " value='%s' maxlength='%d' width='32' />"
        "</td>" "</tr>" "<tr>" "<td colspan='2'><hr></td>" "</tr>";

    /* Configuration settings, 1 per device */
    oneper =
        "<tr>"
        "<td colspan='2' align='left'>%s:</td>"
        "</tr>"
        "<tr>"
        "<td>Host Name:</td>"
        "<td>"
        "<input type='text' name='%s'"
        " value='%s' maxlength='%d' width='32' />"
        "</td>"
        "<tr>"
        "<tr>"
        "<td>Domain Name:</td>"
        "<td>"
        "<input type='text' name='%s'"
        " value='%s' maxlength='%d' width='32' />"
        "</td>"
        "<tr>"
        "<td>Local IP Address:</td>"
        "<td>"
        "<input type='text' name='%s'"
        " value='%s' maxlength='%d' width='32' />"
        "</td>"
        "</tr>"
        "<td>Subnet Mask:</td>"
        "<td>"
        "<input type='text' name='%s'"
        " value='%s' maxlength='%d' width='32' />"
        "</td>" "</tr>" "<tr>" "<td colspan='2'><hr></td>" "</tr>";

    formsubmit =
        "<tr>"
        "<td align='center' colspan='2'>"
        "<input type='submit' value='Submit Changes' />"
        "</td>" "</table>" "</form>";

    /* Report on the success of updating router configuration in NVRAM */
    switch (flashSuccess)
    {
    case 0:
        flashReport = "<div style='color:#00ff00' align='center'>"
            "Updated router configuration settings, restart required."
            "</div>";
        break;

    case 1:
        flashReport = "<div style='color:#ff0000' align='center'>"
            "Failed to update router configuration settings." "</div>";
        break;
    default:
        flashReport = NULL;
    }
    if (NULL != flashReport)
    {
        httpWrite(devptr, flashReport, strnlen(flashReport, HTTP_STR_SM));
    }

    /* Settings that pertain to all devices */
    if (NULL == (configGatewayIP = nvramGet(NET_GATEWAY)))
    {
        configGatewayIP = "not set";
    }
    printf(oneforall, NET_GATEWAY, configGatewayIP, IPv4_DOTDEC_MAXLEN);

    /* Settings that are per device */
    for (cntr = 0; cntr < NETHER; cntr++)
    {
        ethptr = ethertab[cntr].dev;
        if (NULL == ethptr)
        {
            continue;
        }

        sprintf(hostname_str, "%s_%s", ethptr->name, NET_HOSTNAME);
        sprintf(domainname_str, "%s_%s", ethptr->name, NET_DOMAINNAME);
        sprintf(lan_ip_str, "%s_%s", ethptr->name, NET_LAN_IPADDR);
        sprintf(subnet_mask_str, "%s_%s", ethptr->name, NET_SUBNET_MASK);

        if (NULL == (configHostname = nvramGet(hostname_str)))
        {
            configHostname = "not set";
        }
        if (NULL == (configDomainname = nvramGet(domainname_str)))
        {
            configDomainname = "not set";
        }
        if (NULL == (configIP = nvramGet(lan_ip_str)))
        {
            configIP = "not set";
        }
        if (NULL == (configSubnetMask = nvramGet(subnet_mask_str)))
        {
            configSubnetMask = "not set";
        }

        printf(oneper,          /* Format string for settings per device */
               ethptr->name,    /* Device name */
               hostname_str, configHostname, NET_HOSTNM_MAXLEN,
               domainname_str, configDomainname, NVRAM_STRMAX,
               lan_ip_str, configIP, IPv4_DOTDEC_MAXLEN,
               subnet_mask_str, configSubnetMask, IPv4_DOTDEC_MAXLEN);
    }

    /* Output the bottom of the configuration page body */
    httpWrite(devptr, formsubmit, strnlen(formsubmit, HTTP_STR_MD));


    /* Free memory of configuration page strings */
    if (hostname_str != NULL)
    {
        free(hostname_str);
    }
    if (domainname_str != NULL)
    {
        free(domainname_str);
    }
    if (lan_ip_str != NULL)
    {
        free(lan_ip_str);
    }
    if (subnet_mask_str != NULL)
    {
        free(subnet_mask_str);
    }
    if (gate_ip_str != NULL)
    {
        free(gate_ip_str);
    }

    return OK;
}
예제 #7
0
파일: etherInit.c 프로젝트: JamesLinus/xinu
/* Implementation of etherInit() for the ag71xx; see the documentation for this
 * function in ether.h.  */
devcall etherInit(device *devptr)
{
    struct ether *ethptr;
    struct ag71xx *nicptr;
    uint *rstptr;
    uint rstbit;

    /* Initialize structure pointers */
    ethptr = &ethertab[devptr->minor];
    bzero(ethptr, sizeof(struct ether));
    ethptr->dev = devptr;
    ethptr->csr = devptr->csr;
    nicptr = (struct ag71xx *)devptr->csr;
    rstptr = (uint *)RESET_CORE;
    if (0 == devptr->minor)
    {
        rstbit = RESET_E0_MAC;
    }
    else
    {
        rstbit = RESET_E1_MAC;
    }

    ethptr->state = ETH_STATE_DOWN;
    ethptr->rxRingSize = ETH_RX_RING_ENTRIES;
    ethptr->txRingSize = ETH_TX_RING_ENTRIES;
    ethptr->mtu = ETH_MTU;
    ethptr->interruptMask = IRQ_TX_PKTSENT | IRQ_TX_BUSERR
        | IRQ_RX_PKTRECV | IRQ_RX_OVERFLOW | IRQ_RX_BUSERR;

    ethptr->errors = 0;
    ethptr->isema = semcreate(0);
    ethptr->istart = 0;
    ethptr->icount = 0;
    ethptr->ovrrun = 0;
    ethptr->rxOffset = ETH_PKT_RESERVE;

    /* Lookup canonical MAC in NVRAM, and store in ether struct */
    colon2mac(nvramGet("et0macaddr"), ethptr->devAddress);
    ethptr->addressLength = ETH_ADDR_LEN;

    // Reset the device.
    nicptr->macConfig1 |= MAC_CFG1_SOFTRESET;
    udelay(20);
    *rstptr |= rstbit;
    mdelay(100);
    *rstptr &= ~rstbit;
    mdelay(100);

    // Enable Tx and Rx.
    nicptr->macConfig1 = MAC_CFG1_TX | MAC_CFG1_SYNC_TX |
        MAC_CFG1_RX | MAC_CFG1_SYNC_RX;
    // Configure full duplex, auto padding CRC, and interface mode.
    nicptr->macConfig2 |=
        MAC_CFG2_FDX | MAC_CFG2_PAD | MAC_CFG2_LEN_CHECK |
        MAC_CFG2_IMNIBBLE;

    // Enable FIFO modules.
    nicptr->fifoConfig0 = FIFO_CFG0_WTMENREQ | FIFO_CFG0_SRFENREQ |
        FIFO_CFG0_FRFENREQ | FIFO_CFG0_STFENREQ | FIFO_CFG0_FTFENREQ;

    // FIXME
    // -> ag71xx_mii_ctrl_set_if(ag, pdata->mii_if);
    // Stores a '1' in 0x18070000 (MII mode)
    // Stores a '1' in 0x18070004 (RMII mode)

    // FRRD may be asserted only after the completion of the input frame.
    nicptr->fifoConfig1 = 0x0FFF0000;
    // Max out number of words to store in Rx RAM;
    nicptr->fifoConfig2 = 0x00001FFF;
    // Drop anything with errors in the Rx stats vector.
    nicptr->fifoConfig4 = 0x0003FFFF;
    // Drop short packets, set "don't care" on Rx stats vector bits.
    nicptr->fifoConfig5 = 0x0003FFFF;

    /* NOTE: because device initialization runs early in the system, */
    /*  we are assured that this stkget() call will return          */
    /*  page-aligned (and cache-aligned) boundaries.                */
    ethptr->rxBufs = stkget(PAGE_SIZE);
    ethptr->txBufs = stkget(PAGE_SIZE);
    ethptr->rxRing = stkget(PAGE_SIZE);
    ethptr->txRing = stkget(PAGE_SIZE);

    if ((SYSERR == (int)ethptr->rxBufs)
        || (SYSERR == (int)ethptr->txBufs)
        || (SYSERR == (int)ethptr->rxRing)
        || (SYSERR == (int)ethptr->txRing))
    {
#ifdef DETAIL
        kprintf("eth%d ring buffer allocation error.\r\n", devptr->minor);
#endif                          /* DETAIL */
        return SYSERR;
    }

    /* bump buffer pointers/rings to KSEG1 */
    ethptr->rxBufs =
        (struct ethPktBuffer
         **)(((ulong)ethptr->rxBufs - PAGE_SIZE +
              sizeof(int)) | KSEG1_BASE);
    ethptr->txBufs =
        (struct ethPktBuffer
         **)(((ulong)ethptr->txBufs - PAGE_SIZE +
              sizeof(int)) | KSEG1_BASE);
    ethptr->rxRing =
        (struct dmaDescriptor
         *)(((ulong)ethptr->rxRing - PAGE_SIZE +
             sizeof(int)) | KSEG1_BASE);
    ethptr->txRing =
        (struct dmaDescriptor
         *)(((ulong)ethptr->txRing - PAGE_SIZE +
             sizeof(int)) | KSEG1_BASE);

    /* Zero out the buffer pointers and rings */
    bzero(ethptr->rxBufs, PAGE_SIZE);
    bzero(ethptr->txBufs, PAGE_SIZE);
    bzero(ethptr->rxRing, PAGE_SIZE);
    bzero(ethptr->txRing, PAGE_SIZE);

    interruptVector[devptr->irq] = devptr->intr;
    enable_irq(devptr->irq);

    return OK;
}
예제 #8
0
파일: shell.c 프로젝트: osa1/osdev
/**
 * @ingroup shell
 *
 * The Xinu shell.  Provides an interface to execute commands.
 * @param descrp descriptor of device on which the shell is open
 * @return OK for successful exit, SYSERR for unrecoverable error
 */
thread shell(int indescrp, int outdescrp, int errdescrp)
{
    char buf[SHELL_BUFLEN];     /* line input buffer        */
    short buflen;               /* length of line input     */
    char tokbuf[SHELL_BUFLEN + SHELL_MAXTOK];   /* token value buffer       */
    short ntok;                 /* number of tokens         */
    char *tok[SHELL_MAXTOK];    /* pointers to token values */
    char *outname;              /* name of output file      */
    char *inname;               /* name of input file       */
    bool background;            /* is background proccess?  */
    syscall child;              /* pid of child thread      */
    ushort i, j;                /* temp variables           */
    irqmask im;                 /* interrupt mask state     */
    char *hostptr = NULL;       /* pointer to hostname      */

    /* Setup buffer for string for nvramGet call for hostname */
#if defined(ETH0) && NVRAM
    char hostnm[NET_HOSTNM_MAXLEN + 1]; /* hostname of backend      */
    if (!isbaddev(ETH0))
    {
        size_t hostname_strsz;          /* nvram hostname name size */

        bzero(hostnm, NET_HOSTNM_MAXLEN + 1);

        /* Determine the hostname of the main network device */
        hostname_strsz = strlen(NET_HOSTNAME);
        hostname_strsz += 1;
        hostname_strsz += DEVMAXNAME;
        hostname_strsz += 1;
        char nvramget_hostname_str[hostname_strsz];
        sprintf(nvramget_hostname_str, "%s_%s", devtab[ETH0].name,
                NET_HOSTNAME);

        /* Acquire the backend's hostname */
        hostptr = nvramGet(nvramget_hostname_str);
        if (hostptr != NULL)
        {
            strncpy(hostnm, hostptr, NET_HOSTNM_MAXLEN);
            hostptr = hostnm;
        }
    }
#endif

    /* Set command devices for input, output, and error */
    stdin = indescrp;
    stdout = outdescrp;
    stderr = errdescrp;

    /* Print shell banner to framebuffer, if exists */
#if defined(FRAMEBUF)
    if (indescrp == FRAMEBUF)
    {
        foreground = RASPBERRY;
        printf(SHELL_BANNER_NONVT100);
        foreground = LEAFGREEN;
        printf(SHELL_START);
        foreground = GREEN;
    }
    else
#endif
    {
        printf(SHELL_BANNER);
        printf(SHELL_START);
    }

    /* Continually receive and handle commands */
    while (TRUE)
    {
        /* Display prompt */
        printf(SHELL_PROMPT);

        if (NULL != hostptr)
        {
            printf("@%s$ ", hostptr);
        }
        else
        {
            printf("$ ");
        }

        /* Setup proper tty modes for input and output */
        control(stdin, TTY_CTRL_CLR_IFLAG, TTY_IRAW, NULL);
        control(stdin, TTY_CTRL_SET_IFLAG, TTY_ECHO, NULL);

        /* Read command */
        buflen = read(stdin, buf, SHELL_BUFLEN - 1);

        /* Check for EOF and exit gracefully if seen */
        if (EOF == buflen)
        {
            break;
        }

        /* Parse line input into tokens */
        if (SYSERR == (ntok = lexan(buf, buflen, &tokbuf[0], &tok[0])))
        {
            fprintf(stderr, SHELL_SYNTAXERR);
            continue;
        }

        /* Ensure parse generated tokens */
        if (0 == ntok)
        {
            continue;
        }

        /* Initialize command options */
        inname = NULL;
        outname = NULL;
        background = FALSE;

        /* Mark as background thread, if last token is '&' */
        if ('&' == *tok[ntok - 1])
        {
            ntok--;
            background = TRUE;
        }

        /* Check each token and perform special handling of '>' and '<' */
        for (i = 0; i < ntok; i++)
        {
            /* Background '&' should have already been handled; Syntax error */
            if ('&' == *tok[i])
            {
                ntok = -1;
                break;
            }

            /* Setup for output redirection if token is '>'  */
            if ('>' == *tok[i])
            {
                /* Syntax error */
                if (outname != NULL || i >= ntok - 1)
                {
                    ntok = -1;
                    break;
                }

                outname = tok[i + 1];
                ntok -= 2;

                /* shift tokens (not to be passed to command */
                for (j = i; j < ntok; j++)
                {
                    tok[j] = tok[j + 2];
                }
                continue;
            }

            /* Setup for input redirection if token is '<' */
            if ('<' == *tok[i])
            {
                /* Syntax error */
                if (inname != NULL || i >= ntok - 1)
                {
                    ntok = -1;
                    break;
                }
                inname = tok[i + 1];
                ntok -= 2;

                /* shift tokens (not to be passed to command */
                for (j = i; j < ntok; j++)
                {
                    tok[j] = tok[j + 2];
                }

                continue;
            }
        }

        /* Handle syntax error */
        if (ntok <= 0)
        {
            fprintf(stderr, SHELL_SYNTAXERR);
            continue;
        }

        /* Lookup first token in the command table */
        for (i = 0; i < ncommand; i++)
        {
            if (0 == strcmp(commandtab[i].name, tok[0]))
            {
                break;
            }
        }

        /* Handle command not found */
        if (i >= ncommand)
        {
            fprintf(stderr, "%s: command not found\n", tok[0]);
            continue;
        }

        /* Handle command if it is built-in */
        if (commandtab[i].builtin)
        {
            if (inname != NULL || outname != NULL || background)
            {
                fprintf(stderr, SHELL_SYNTAXERR);
            }
            else
            {
                (*commandtab[i].procedure) (ntok, tok);
            }
            continue;
        }

        /* Spawn child thread for non-built-in commands */
        child =
            create(commandtab[i].procedure,
                   SHELL_CMDSTK, SHELL_CMDPRIO,
                   commandtab[i].name, 2, ntok, tok);

        /* Ensure child command thread was created successfully */
        if (SYSERR == child)
        {
            fprintf(stderr, SHELL_CHILDERR);
            continue;
        }

        /* Set file descriptors for newly created thread */
        if (NULL == inname)
        {
            thrtab[child].fdesc[0] = stdin;
        }
        else
        {
            thrtab[child].fdesc[0] = getdev(inname);
        }
        if (NULL == outname)
        {
            thrtab[child].fdesc[1] = stdout;
        }
        else
        {
            thrtab[child].fdesc[1] = getdev(outname);
        }
        thrtab[child].fdesc[2] = stderr;

        if (background)
        {
            /* Make background thread ready, but don't reschedule */
            im = disable();
            ready(child, RESCHED_NO);
            restore(im);
        }
        else
        {
            /* Clear waiting message; Reschedule; */
            while (recvclr() != NOMSG);
            im = disable();
            ready(child, RESCHED_YES);
            restore(im);

            /* Wait for command thread to finish */
            while (receive() != child);
            sleep(10);
        }
    }

    /* Close shell */
    fprintf(stdout, SHELL_EXIT);
    sleep(10);
    return OK;
}
예제 #9
0
/**
 * The Xinu shell.  Provides an interface to execute commands.
 * @param descrp descriptor of device on which the shell is open
 * @return OK for successful exit, SYSERR for unrecoverable error
 */
thread shell(int indescrp, int outdescrp, int errdescrp)
{
  char buf[SHELL_BUFLEN];     /* line input buffer        */
  short buflen;               /* length of line input     */
  char tokbuf[SHELL_BUFLEN + SHELL_MAXTOK];   /* token value buffer       */
  short ntok;                 /* number of tokens         */
  char *tok[SHELL_MAXTOK];    /* pointers to token values */
  char *outname;              /* name of output file      */
  char *inname;               /* name of input file       */
  bool background;            /* is background proccess?  */
  syscall child;              /* pid of child thread      */
  ushort i, j;                /* temp variables           */
  irqmask im;                 /* interrupt mask state     */

  /* hostname variables */
  char hostnm[NET_HOSTNM_MAXLEN + 1]; /* hostname of backend      */
  char *hostptr;              /* pointer to hostname      */
  int hostname_strsz;         /* nvram hostname name size */
  device *devptr;             /* device pointer           */

  printf( "Welcome to the shell!\n" );

  /* Enable interrupts */
  enable();

  hostptr = NULL;
  devptr = NULL;
  hostname_strsz = 0;
  bzero(hostnm, NET_HOSTNM_MAXLEN + 1);

  /* Setup buffer for string for nvramGet call for hostname */
#ifdef ETH0
  if (!isbaddev(ETH0))
  {
    /* Determine the hostname of the main network device */
    devptr = (device *)&devtab[ETH0];
    hostname_strsz = strnlen(NET_HOSTNAME, NVRAM_STRMAX) + 1;
    hostname_strsz += DEVMAXNAME;
    char nvramget_hostname_str[hostname_strsz];
    sprintf(nvramget_hostname_str, "%s_%s", devptr->name,
        NET_HOSTNAME);

    /* Acquire the backend's hostname */
#if NVRAM
    hostptr = nvramGet(nvramget_hostname_str);
#endif                          /* NVRAM */
    if (hostptr != NULL)
    {
      memcpy(hostnm, hostptr, NET_HOSTNM_MAXLEN);
      hostptr = hostnm;
    }
  }
#endif

  /* Set command devices for input, output, and error */
  stdin = indescrp;
  stdout = outdescrp;
  stderr = errdescrp;

  /* Print shell banner */
  printf(SHELL_BANNER);
  /* Print shell welcome message */
  printf(SHELL_START);

  /* Continually receive and handle commands */
  while (TRUE)
  {
    /* Display prompt */
    printf(SHELL_PROMPT);

    if (NULL != hostptr)
    {
      printf("@%s$ ", hostptr);
    }
    else
    {
      printf("$ ");
    }

    /* Setup proper tty modes for input and output */
    control(stdin, TTY_CTRL_CLR_IFLAG, TTY_IRAW, NULL);
    control(stdin, TTY_CTRL_SET_IFLAG, TTY_ECHO, NULL);

    /* Null out the buf and read command */
    memset(buf, '\0', SHELL_BUFLEN);
    buflen = shellRead(stdin, buf, SHELL_BUFLEN);

    if(buf[0] != '!') {
      addHistoryItem(buf, buflen);
    }

    /* Check for EOF and exit gracefully if seen */
    if (EOF == buflen)
    {
      break;
    }

    // Check for indicator of history command
    if (buf[0] == '!')
    {
      int index;

      // handler for !! (just execute most recent command)
      if(buf[1] == '!') {
        index = 0;
      } else {
        // extract the number string
        char indexString[buflen];
        strncpy(indexString, &buf[1], buflen - 1);
        indexString[buflen] = '\0';

        // convert number string into a valid index
        // calculation is done because the index numbers
        // are reverse of their numbers printed using 'history'
        index = numHistoryItems - atoi(indexString);
      }

      //replace buf and buflen with the last command
      strncpy(buf, history[index].command, SHELL_BUFLEN);
      buflen = history[index].commandLength + 1;
    }

    /* Parse line input into tokens */
    if (SYSERR == (ntok = lexan(buf, buflen, &tokbuf[0], &tok[0])))
    {
      fprintf(stderr, SHELL_SYNTAXERR);
      continue;
    }

    /* Ensure parse generated tokens */
    if (0 == ntok)
    {
      continue;
    }

    /* Initialize command options */
    inname = NULL;
    outname = NULL;
    background = FALSE;

    /* Mark as background thread, if last token is '&' */
    if ('&' == *tok[ntok - 1])
    {
      ntok--;
      background = TRUE;
    }

    /* Check each token and perform special handling of '>' and '<' */
    for (i = 0; i < ntok; i++)
    {
      /* Background '&' should have already been handled; Syntax error */
      if ('&' == *tok[i])
      {
        ntok = -1;
        break;
      }

      /* Setup for output redirection if token is '>'  */
      if ('>' == *tok[i])
      {
        /* Syntax error */
        if (outname != NULL || i >= ntok - 1)
        {
          ntok = -1;
          break;
        }

        outname = tok[i + 1];
        ntok -= 2;

        /* shift tokens (not to be passed to command */
        for (j = i; j < ntok; j++)
        {
          tok[j] = tok[j + 2];
        }
        continue;
      }

      /* Setup for input redirection if token is '<' */
      if ('<' == *tok[i])
      {
        /* Syntax error */
        if (inname != NULL || i >= ntok - 1)
        {
          ntok = -1;
          break;
        }
        inname = tok[i + 1];
        ntok -= 2;

        /* shift tokens (not to be passed to command */
        for (j = i; j < ntok; j++)
        {
          tok[j] = tok[j + 2];
        }

        continue;
      }
    }

    /* Handle syntax error */
    if (ntok <= 0)
    {
      fprintf(stderr, SHELL_SYNTAXERR);
      continue;
    }

    /* Lookup first token in the command table */
    for (i = 0; i < ncommand; i++)
    {
      if (0 == strncmp(commandtab[i].name, tok[0], SHELL_BUFLEN))
      {
        break;
      }
    }

    /* Handle command not found */
    if (i >= ncommand)
    {
      fprintf(stderr, "%s: command not found\n", tok[0]);
      continue;
    }

    /* Handle command if it is built-in */
    if (commandtab[i].builtin)
    {
      if (inname != NULL || outname != NULL || background)
      {
        fprintf(stderr, SHELL_SYNTAXERR);
      }
      else
      {
        (*commandtab[i].procedure) (ntok, tok);
      }
      continue;
    }

    /* Spawn child thread for non-built-in commands */
    child =
      create(commandtab[i].procedure,
          SHELL_CMDSTK, SHELL_CMDPRIO,
          commandtab[i].name, 2, ntok, tok);



    /* Ensure child command thread was created successfully */
    if (SYSERR == child)
    {
      fprintf(stderr, SHELL_CHILDERR);
      continue;
    }

    /* Set file descriptors for newly created thread */
    if (NULL == inname)
    {
      thrtab[child].fdesc[0] = stdin;
    }
    else
    {
      thrtab[child].fdesc[0] = getdev(inname);
    }
    if (NULL == outname)
    {
      thrtab[child].fdesc[1] = stdout;
    }
    else
    {
      thrtab[child].fdesc[1] = getdev(outname);
    }
    thrtab[child].fdesc[2] = stderr;

    if (background)
    {
      /* Make background thread ready, but don't reschedule */
      im = disable();
      ready(child, RESCHED_NO);
      restore(im);
    }
    else
    {
      /* Clear waiting message; Reschedule; */
      while (recvclr() != NOMSG);
      im = disable();
      ready(child, RESCHED_YES);
      restore(im);

      /* Wait for command thread to finish */
      while (receive() != child);
      sleep(10);
    }
  }

  /* Close shell */
  fprintf(stdout, SHELL_EXIT);
  sleep(10);
  return OK;
}