Exemplo n.º 1
14
/**
 * @ingroup intern
 * @brief send_mod_request - send a linkinfo modification request
 *
 * @param fd decriptor to a priorly opened netlink socket
 * @param n netlink message containing the request
 *
 * sends a request to setup the the linkinfo to netlink layer and awaits the
 * status.
 *
 * @return 0 if success
 * @return negativ if failed
 */
static int send_mod_request(int fd, struct nlmsghdr *n)
{
	int status;
	struct sockaddr_nl nladdr;
	struct nlmsghdr *h;

	struct iovec iov = {
		.iov_base = (void *)n,
		.iov_len = n->nlmsg_len
	};
	struct msghdr msg = {
		.msg_name = &nladdr,
		.msg_namelen = sizeof(nladdr),
		.msg_iov = &iov,
		.msg_iovlen = 1,
	};
	char buf[16384];

	memset(&nladdr, 0, sizeof(nladdr));

	nladdr.nl_family = AF_NETLINK;
	nladdr.nl_pid = 0;
	nladdr.nl_groups = 0;

	n->nlmsg_seq = 0;
	n->nlmsg_flags |= NLM_F_ACK;

	status = sendmsg(fd, &msg, 0);

	if (status < 0) {
		perror("Cannot talk to rtnetlink");
		return -1;
	}

	iov.iov_base = buf;
	while (1) {
		iov.iov_len = sizeof(buf);
		status = recvmsg(fd, &msg, 0);
		for (h = (struct nlmsghdr *)buf; (size_t) status >= sizeof(*h);) {
			int len = h->nlmsg_len;
			int l = len - sizeof(*h);
			if (l < 0 || len > status) {
				if (msg.msg_flags & MSG_TRUNC) {
					fprintf(stderr, "Truncated message\n");
					return -1;
				}
				printf("!!!malformed message: len=%d\n", len);
				return -1;
			}

			if (h->nlmsg_type == NLMSG_ERROR) {
				struct nlmsgerr *err =
				    (struct nlmsgerr *)NLMSG_DATA(h);
				if ((size_t) l < sizeof(struct nlmsgerr)) {
					fprintf(stderr, "ERROR truncated\n");
				} else {
					errno = -err->error;
					if (errno == 0)
						return 0;

					perror("RTNETLINK answers");
				}
				return -1;
			}
			status -= NLMSG_ALIGN(len);
			h = (struct nlmsghdr *)((char *)h + NLMSG_ALIGN(len));
		}
	}

	return 0;
}

/**
 * @ingroup intern
 * @brief send_dump_request - send a dump linkinfo request
 *
 * @param fd decriptor to a priorly opened netlink socket
 * @param family rt_gen message family
 * @param type netlink message header type
 *
 * @return 0 if success
 * @return negativ if failed
 */
static int send_dump_request(int fd, int family, int type)
{
	struct get_req req;

	memset(&req, 0, sizeof(req));

	req.n.nlmsg_len = sizeof(req);
	req.n.nlmsg_type = type;
	req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_ROOT | NLM_F_MATCH;
	req.n.nlmsg_pid = 0;
	req.n.nlmsg_seq = 0;

	req.g.rtgen_family = family;

	return send(fd, (void *)&req, sizeof(req), 0);
}



  
//extern int optind, opterr, optopt;

/**
 * @ingroup intern
 * @brief open_nl_sock - open a netlink socket
 *
 * opens a netlink socket and returns the socket descriptor
 *
 * @return 0 if success
 * @return negativ if failed
 */
static int open_nl_sock()
{
	int fd;
	int sndbuf = 32768;
	int rcvbuf = 32768;
	unsigned int addr_len;
	struct sockaddr_nl local;

	fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
	if (fd < 0) {
		printf("Cannot open netlink socket");
		return -1;
	}

	setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (void *)&sndbuf, sizeof(sndbuf));

	setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (void *)&rcvbuf, sizeof(rcvbuf));

	memset(&local, 0, sizeof(local));
	local.nl_family = AF_NETLINK;
	local.nl_groups = 0;

	if (bind(fd, (struct sockaddr *)&local, sizeof(local)) < 0) {
		printf("Cannot bind netlink socket");
		return -1;
	}

	addr_len = sizeof(local);
	if (getsockname(fd, (struct sockaddr *)&local, &addr_len) < 0) {
		printf("Cannot getsockname");
		return -1;
	}
	if (addr_len != sizeof(local)) {
		printf("Wrong address length %u\n", addr_len);
		return -1;
	}
	if (local.nl_family != AF_NETLINK) {
		printf("Wrong address family %d\n", local.nl_family);
		return -1;
	}
	return fd;
}

/**
 * @ingroup intern
 * @brief do_get_nl_link - get linkinfo
 *
 * @param fd socket file descriptor to a priorly opened netlink socket
 * @param acquire  which parameter we want to get
 * @param name name of the can device. This is the netdev name, as ifconfig -a
 * shows in your system. usually it contains prefix "can" and the numer of the
 * can line. e.g. "can0"
 * @param res pointer to store the result
 *
 * This callback send a dump request into the netlink layer, collect the packet
 * containing the linkinfo and fill the pointer res points to depending on the
 * acquire mode set in param acquire.
 *
 * @return 0 if success
 * @return -1 if failed
 */

static int do_get_nl_link(int fd, __u8 acquire, const char *name, void *res)
{
	struct sockaddr_nl peer;

	char cbuf[64];
	char nlbuf[1024 * 8];

	int ret = -1;
	int done = 0;

	struct iovec iov = {
		.iov_base = (void *)nlbuf,
		.iov_len = sizeof(nlbuf),
	};

	struct msghdr msg = {
		.msg_name = (void *)&peer,
		.msg_namelen = sizeof(peer),
		.msg_iov = &iov,
		.msg_iovlen = 1,
		.msg_control = &cbuf,
		.msg_controllen = sizeof(cbuf),
		.msg_flags = 0,
	};
	struct nlmsghdr *nl_msg;
	ssize_t msglen;

	struct rtattr *linkinfo[IFLA_INFO_MAX + 1];
	struct rtattr *can_attr[IFLA_CAN_MAX + 1];

	if (send_dump_request(fd, AF_PACKET, RTM_GETLINK) < 0) {
		perror("Cannot send dump request");
		return ret;
	}

	while (!done && (msglen = recvmsg(fd, &msg, 0)) > 0) {
		size_t u_msglen = (size_t) msglen;
		/* Check to see if the buffers in msg get truncated */
		if (msg.msg_namelen != sizeof(peer) ||
		    (msg.msg_flags & (MSG_TRUNC | MSG_CTRUNC))) {
			fprintf(stderr, "Uhoh... truncated message.\n");
			return -1;
		}

		for (nl_msg = (struct nlmsghdr *)nlbuf;
		     NLMSG_OK(nl_msg, u_msglen);
		     nl_msg = NLMSG_NEXT(nl_msg, u_msglen)) {
			int type = nl_msg->nlmsg_type;
			int len;

			if (type == NLMSG_DONE) {
				done++;
				continue;
			}
			if (type != RTM_NEWLINK)
				continue;

			struct ifinfomsg *ifi = NLMSG_DATA(nl_msg);
			struct rtattr *tb[IFLA_MAX + 1];

			len =
				nl_msg->nlmsg_len - NLMSG_LENGTH(sizeof(struct ifaddrmsg));
			parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len);

			if (strcmp
			    ((char *)RTA_DATA(tb[IFLA_IFNAME]), name) != 0)
				continue;

			if (tb[IFLA_LINKINFO])
				parse_rtattr_nested(linkinfo,
						    IFLA_INFO_MAX, tb[IFLA_LINKINFO]);
			else
				continue;

			if (acquire == GET_XSTATS) {
				if (!linkinfo[IFLA_INFO_XSTATS])
					fprintf(stderr, "no can statistics found\n");
				else {
					memcpy(res, RTA_DATA(linkinfo[IFLA_INFO_XSTATS]),
					       sizeof(struct can_device_stats));
					ret = 0;
				}
				continue;
			}

			if (!linkinfo[IFLA_INFO_DATA]) {
				fprintf(stderr, "no link data found\n");
				return ret;
			}

			parse_rtattr_nested(can_attr, IFLA_CAN_MAX,
					    linkinfo[IFLA_INFO_DATA]);

			switch (acquire) {
			case GET_STATE:
				if (can_attr[IFLA_CAN_STATE]) {
					*((int *)res) = *((__u32 *)
							  RTA_DATA(can_attr
								   [IFLA_CAN_STATE]));
					ret = 0;
				} else {
					fprintf(stderr, "no state data found\n");
				}

				break;
			case GET_RESTART_MS:
				if (can_attr[IFLA_CAN_RESTART_MS]) {
					*((__u32 *) res) = *((__u32 *)
							     RTA_DATA(can_attr
								      [IFLA_CAN_RESTART_MS]));
					ret = 0;
				} else
					fprintf(stderr, "no restart_ms data found\n");

				break;
			case GET_BITTIMING:
				if (can_attr[IFLA_CAN_BITTIMING]) {
					memcpy(res,
					       RTA_DATA(can_attr[IFLA_CAN_BITTIMING]),
					       sizeof(struct can_bittiming));
					ret = 0;
				} else
					fprintf(stderr, "no bittiming data found\n");

				break;
			case GET_CTRLMODE:
				if (can_attr[IFLA_CAN_CTRLMODE]) {
					memcpy(res,
					       RTA_DATA(can_attr[IFLA_CAN_CTRLMODE]),
					       sizeof(struct can_ctrlmode));
					ret = 0;
				} else
					fprintf(stderr, "no ctrlmode data found\n");

				break;
			case GET_CLOCK:
				if (can_attr[IFLA_CAN_CLOCK]) {
					memcpy(res,
					       RTA_DATA(can_attr[IFLA_CAN_CLOCK]),
					       sizeof(struct can_clock));
					ret = 0;
				} else
					fprintf(stderr,
						"no clock parameter data found\n");

				break;
			case GET_BITTIMING_CONST:
				if (can_attr[IFLA_CAN_BITTIMING_CONST]) {
					memcpy(res,
					       RTA_DATA(can_attr[IFLA_CAN_BITTIMING_CONST]),
					       sizeof(struct can_bittiming_const));
					ret = 0;
				} else
					fprintf(stderr, "no bittiming_const data found\n");

				break;
			case GET_BERR_COUNTER:
				if (can_attr[IFLA_CAN_BERR_COUNTER]) {
					memcpy(res,
					       RTA_DATA(can_attr[IFLA_CAN_BERR_COUNTER]),
					       sizeof(struct can_berr_counter));
					ret = 0;
				} else
					fprintf(stderr, "no berr_counter data found\n");

				break;

			default:
				fprintf(stderr, "unknown acquire mode\n");
			}
		}
	}

	return ret;
}

/**
 * @ingroup intern
 * @brief get_link - get linkinfo
 *
 * @param name name of the can device. This is the netdev name, as ifconfig -a shows
 * in your system. usually it contains prefix "can" and the numer of the can
 * line. e.g. "can0"
 * @param acquire which parameter we want to get
 * @param res pointer to store the result
 *
 * This is a wrapper for do_get_nl_link
 *
 * @return 0 if success
 * @return -1 if failed
 */
static int get_link(const char *name, __u8 acquire, void *res)
{
	int err, fd;

	fd = open_nl_sock();
	if (fd < 0)
		return -1;

	err = do_get_nl_link(fd, acquire, name, res);
	close(fd);

	return err;

}

/**
 * @ingroup intern
 * @brief do_set_nl_link - setup linkinfo
 *
 * @param fd socket file descriptor to a priorly opened netlink socket
 * @param if_state state of the interface we want to put the device into. this
 * parameter is only set if you want to use the callback to driver up/down the
 * device
 * @param name name of the can device. This is the netdev name, as ifconfig -a shows
 * in your system. usually it contains prefix "can" and the numer of the can
 * line. e.g. "can0"
 * @param req_info request parameters
 *
 * This callback can do two different tasks:
 * - bring up/down the interface
 * - set up a netlink packet with request, as set up in req_info
 * Which task this callback will do depends on which parameters are set.
 *
 * @return 0 if success
 * @return -1 if failed
 */
static int do_set_nl_link(int fd, __u8 if_state, const char *name,
			  struct req_info *req_info)
{
	struct set_req req;

	const char *type = "can";

	memset(&req, 0, sizeof(req));

	req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
	req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
	req.n.nlmsg_type = RTM_NEWLINK;
	req.i.ifi_family = 0;

	req.i.ifi_index = if_nametoindex(name);
	if (req.i.ifi_index == 0) {
		fprintf(stderr, "Cannot find device \"%s\"\n", name);
		return -1;
	}

	if (if_state) {
		switch (if_state) {
		case IF_DOWN:
			req.i.ifi_change |= IFF_UP;
			req.i.ifi_flags &= ~IFF_UP;
			break;
		case IF_UP:
			req.i.ifi_change |= IFF_UP;
			req.i.ifi_flags |= IFF_UP;
			break;
		default:
			fprintf(stderr, "unknown state\n");
			return -1;
		}
	}

	if (req_info != NULL) {
		/* setup linkinfo section */
		struct rtattr *linkinfo = NLMSG_TAIL(&req.n);
		addattr_l(&req.n, sizeof(req), IFLA_LINKINFO, NULL, 0);
		addattr_l(&req.n, sizeof(req), IFLA_INFO_KIND, type,
			  strlen(type));
		/* setup data section */
		struct rtattr *data = NLMSG_TAIL(&req.n);
		addattr_l(&req.n, sizeof(req), IFLA_INFO_DATA, NULL, 0);

		if (req_info->restart_ms > 0 || req_info->disable_autorestart)
			addattr32(&req.n, 1024, IFLA_CAN_RESTART_MS,
				  req_info->restart_ms);

		if (req_info->restart)
			addattr32(&req.n, 1024, IFLA_CAN_RESTART, 1);

		if (req_info->bittiming != NULL) {
			addattr_l(&req.n, 1024, IFLA_CAN_BITTIMING,
				  req_info->bittiming,
				  sizeof(struct can_bittiming));
		}

		if (req_info->ctrlmode != NULL) {
			addattr_l(&req.n, 1024, IFLA_CAN_CTRLMODE,
				  req_info->ctrlmode,
				  sizeof(struct can_ctrlmode));
		}

		/* mark end of data section */
		data->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)data;

		/* mark end of link info section */
		linkinfo->rta_len =
		    (void *)NLMSG_TAIL(&req.n) - (void *)linkinfo;
	}

	return send_mod_request(fd, &req.n);
}

/**
 * @ingroup intern
 * @brief set_link - open a netlink socket and setup linkinfo
 *
 * @param name name of the can device. This is the netdev name, as ifconfig -a
 * shows in your system. usually it contains prefix "can" and the numer of the
 * can line. e.g. "can0"
 * @param if_state state of the interface we want to put the device into. this
 * parameter is only set if you want to use the callback to driver up/down the
 * device
 * @param req_info request parameters
 *
 * This is a wrapper for do_set_nl_link. It opens a netlink socket and sends
 * down the requests.
 *
 * @return 0 if success
 * @return -1 if failed
 */
static int set_link(const char *name, __u8 if_state, struct req_info *req_info)
{
	int err, fd;

	fd = open_nl_sock();
	if (fd < 0)
		return -1;

	err = do_set_nl_link(fd, if_state, name, req_info);
	close(fd);

	return err;
}

/**
 * @ingroup extern
 * can_do_start - start the can interface
 * @param name name of the can device. This is the netdev name, as ifconfig -a shows
 * in your system. usually it contains prefix "can" and the numer of the can
 * line. e.g. "can0"
 *
 * This starts the can interface with the given name. It simply changes the if
 * state of the interface to up. All initialisation works will be done in
 * kernel. The if state can also be queried by a simple ifconfig.
 *
 * @return 0 if success
 * @return -1 if failed
 */
int can_do_start(const char *name)
{
	return set_link(name, IF_UP, NULL);
}

/**
 * @ingroup extern
 * can_do_stop - stop the can interface
 * @param name name of the can device. This is the netdev name, as ifconfig -a shows
 * in your system. usually it contains prefix "can" and the numer of the can
 * line. e.g. "can0"
 *
 * This stops the can interface with the given name. It simply changes the if
 * state of the interface to down. Any running communication would be stopped.
 *
 * @return 0 if success
 * @return -1 if failed
 */
int can_do_stop(const char *name)
{
	return set_link(name, IF_DOWN, NULL);
}

/**
 * @ingroup extern
 * can_do_restart - restart the can interface
 * @param name name of the can device. This is the netdev name, as ifconfig -a shows
 * in your system. usually it contains prefix "can" and the numer of the can
 * line. e.g. "can0"
 *
 * This triggers the start mode of the can device.
 *
 * NOTE:
 * - restart mode can only be triggerd if the device is in BUS_OFF and the auto
 * restart not turned on (restart_ms == 0)
 *
 * @return 0 if success
 * @return -1 if failed
 */
int can_do_restart(const char *name)
{
	int state;
	__u32 restart_ms;

	/* first we check if we can restart the device at all */
	if ((can_get_state(name, &state)) < 0) {
		fprintf(stderr, "cannot get bustate, "
			"something is seriously wrong\n");
		return -1;
	} else if (state != CAN_STATE_BUS_OFF) {
		fprintf(stderr,
			"Device is not in BUS_OFF," " no use to restart\n");
		return -1;
	}

	if ((can_get_restart_ms(name, &restart_ms)) < 0) {
		fprintf(stderr, "cannot get restart_ms, "
			"something is seriously wrong\n");
		return -1;
	} else if (restart_ms > 0) {
		fprintf(stderr,
			"auto restart with %ums interval is turned on,"
			" no use to restart\n", restart_ms);
		return -1;
	}

	struct req_info req_info = {
		.restart = 1,
	};

	return set_link(name, 0, &req_info);
}

/**
 * @ingroup extern
 * can_set_restart_ms - set interval of auto restart.
 *
 * @param name name of the can device. This is the netdev name, as ifconfig -a shows
 * in your system. usually it contains prefix "can" and the numer of the can
 * line. e.g. "can0"
 * @param restart_ms interval of auto restart in milliseconds
 *
 * This sets how often the device shall automatically restart the interface in
 * case that a bus_off is detected.
 *
 * @return 0 if success
 * @return -1 if failed
 */
int can_set_restart_ms(const char *name, __u32 restart_ms)
{
	struct req_info req_info = {
		.restart_ms = restart_ms,
	};

	if (restart_ms == 0)
		req_info.disable_autorestart = 1;

	return set_link(name, 0, &req_info);
}

/**
 * @ingroup extern
 * can_set_ctrlmode - setup the control mode.
 *
 * @param name name of the can device. This is the netdev name, as ifconfig -a shows
 * in your system. usually it contains prefix "can" and the numer of the can
 * line. e.g. "can0"
 *
 * @param cm pointer of a can_ctrlmode struct
 *
 * This sets the control mode of the can device. There're currently three
 * different control modes:
 * - LOOPBACK
 * - LISTEN_ONLY
 * - TRIPPLE_SAMPLING
 *
 * You have to define the control mode struct yourself. a can_ctrlmode struct
 * is declared as:
 *
 * @code
 * struct can_ctrlmode {
 *	__u32 mask;
 *	__u32 flags;
 * }
 * @endcode
 *
 * You can use mask to select modes you want to control and flags to determine
 * if you want to turn the selected mode(s) on or off. Every control mode is
 * mapped to an own macro
 *
 * @code
 * #define CAN_CTRLMODE_LOOPBACK   0x1
 * #define CAN_CTRLMODE_LISTENONLY 0x2
 * #define CAN_CTRLMODE_3_SAMPLES  0x4
 * @endcode
 *
 * e.g. the following pseudocode
 *
 * @code
 * struct can_ctrlmode cm;
 * memset(&cm, 0, sizeof(cm));
 * cm.mask = CAN_CTRLMODE_LOOPBACK | CAN_CTRLMODE_LISTENONLY;
 * cm.flags = CAN_CTRLMODE_LOOPBACK;
 * can_set_ctrlmode(candev, &cm);
 * @endcode
 *
 * will turn the loopback mode on and listenonly mode off.
 *
 * @return 0 if success
 * @return -1 if failed
 */

int can_set_ctrlmode(const char *name, struct can_ctrlmode *cm)
{
	struct req_info req_info = {
		.ctrlmode = cm,
	};

	return set_link(name, 0, &req_info);
}

/**
 * @ingroup extern
 * can_set_bittiming - setup the bittiming.
 *
 * @param name name of the can device. This is the netdev name, as ifconfig -a shows
 * in your system. usually it contains prefix "can" and the numer of the can
 * line. e.g. "can0"
 * @param bt pointer to a can_bittiming struct
 *
 * This sets the bittiming of the can device. This is for advantage usage. In
 * normal cases you should use can_set_bitrate to simply define the bitrate and
 * let the driver automatically calculate the bittiming. You will only need this
 * function if you wish to define the bittiming in expert mode with fully
 * manually defined timing values.
 * You have to define the bittiming struct yourself. a can_bittiming struct
 * consists of:
 *
 * @code
 * struct can_bittiming {
 *	__u32 bitrate;
 *	__u32 sample_point;
 *	__u32 tq;
 *	__u32 prop_seg;
 *	__u32 phase_seg1;
 *	__u32 phase_seg2;
 *	__u32 sjw;
 *	__u32 brp;
 * }
 * @endcode
 *
 * to define a customized bittiming, you have to define tq, prop_seq,
 * phase_seg1, phase_seg2 and sjw. See http://www.can-cia.org/index.php?id=88
 * for more information about bittiming and synchronizations on can bus.
 *
 * @return 0 if success
 * @return -1 if failed
 */

int can_set_bittiming(const char *name, struct can_bittiming *bt)
{
	struct req_info req_info = {
		.bittiming = bt,
	};

	return set_link(name, 0, &req_info);
}

/**
 * @ingroup extern
 * can_set_bitrate - setup the bitrate.
 *
 * @param name name of the can device. This is the netdev name, as ifconfig -a shows
 * in your system. usually it contains prefix "can" and the numer of the can
 * line. e.g. "can0"
 * @param bitrate bitrate of the can bus
 *
 * This is the recommended way to setup the bus bit timing. You only have to
 * give a bitrate value here. The exact bit timing will be calculated
 * automatically. To use this function, make sure that CONFIG_CAN_CALC_BITTIMING
 * is set to y in your kernel configuration. bitrate can be a value between
 * 1000(1kbit/s) and 1000000(1000kbit/s).
 *
 * @return 0 if success
 * @return -1 if failed
 */

int can_set_bitrate(const char *name, __u32 bitrate)
{
	struct can_bittiming bt;

	memset(&bt, 0, sizeof(bt));
	bt.bitrate = bitrate;

	return can_set_bittiming(name, &bt);
}

/**
 * @ingroup extern
 * can_set_bitrate_samplepoint - setup the bitrate.
 *
 * @param name name of the can device. This is the netdev name, as ifconfig -a shows
 * in your system. usually it contains prefix "can" and the numer of the can
 * line. e.g. "can0"
 * @param bitrate bitrate of the can bus
 * @param sample_point sample point value
 *
 * This one is similar to can_set_bitrate, only you can additionally set up the
 * time point for sampling (sample point) customly instead of using the
 * CIA recommended value. sample_point can be a value between 0 and 999.
 *
 * @return 0 if success
 * @return -1 if failed
 */
int can_set_bitrate_samplepoint(const char *name, __u32 bitrate,
				__u32 sample_point)
{
	struct can_bittiming bt;

	memset(&bt, 0, sizeof(bt));
	bt.bitrate = bitrate;
	bt.sample_point = sample_point;

	return can_set_bittiming(name, &bt);
}

/**
 * @ingroup extern
 * can_get_state - get the current state of the device
 *
 * @param name name of the can device. This is the netdev name, as ifconfig -a shows
 * in your system. usually it contains prefix "can" and the numer of the can
 * line. e.g. "can0"
 * @param state pointer to store the state
 *
 * This one stores the current state of the can interface into the given
 * pointer. Valid states are:
 * - CAN_STATE_ERROR_ACTIVE
 * - CAN_STATE_ERROR_WARNING
 * - CAN_STATE_ERROR_PASSIVE
 * - CAN_STATE_BUS_OFF
 * - CAN_STATE_STOPPED
 * - CAN_STATE_SLEEPING
 *
 * The first four states is determined by the value of RX/TX error counter.
 * Please see relevant can specification for more information about this. A
 * device in STATE_STOPPED is an inactive device. STATE_SLEEPING is not
 * implemented on all devices.
 *
 * @return 0 if success
 * @return -1 if failed
 */

int can_get_state(const char *name, int *state)
{
	return get_link(name, GET_STATE, state);
}

/**
 * @ingroup extern
 * can_get_restart_ms - get the current interval of auto restarting.
 *
 * @param name name of the can device. This is the netdev name, as ifconfig -a shows
 * in your system. usually it contains prefix "can" and the numer of the can
 * line. e.g. "can0"
 * @param restart_ms pointer to store the value.
 *
 * This one stores the current interval of auto restarting into the given
 * pointer.
 *
 * The socketcan framework can automatically restart a device if it is in
 * bus_off in a given interval. This function gets this value in milliseconds.
 * restart_ms == 0 means that autorestarting is turned off.
 *
 * @return 0 if success
 * @return -1 if failed
 */

int can_get_restart_ms(const char *name, __u32 *restart_ms)
{
	return get_link(name, GET_RESTART_MS, restart_ms);
}

/**
 * @ingroup extern
 * can_get_bittiming - get the current bittimnig configuration.
 *
 * @param name name of the can device. This is the netdev name, as ifconfig -a shows
 * in your system. usually it contains prefix "can" and the numer of the can
 * line. e.g. "can0"
 * @param bt pointer to the bittiming struct.
 *
 * This one stores the current bittiming configuration.
 *
 * Please see can_set_bittiming for more information about bit timing.
 *
 * @return 0 if success
 * @return -1 if failed
 */
int can_get_bittiming(const char *name, struct can_bittiming *bt)
{
	return get_link(name, GET_BITTIMING, bt);
}

/**
 * @ingroup extern
 * can_get_ctrlmode - get the current control mode.
 *
 * @param name name of the can device. This is the netdev name, as ifconfig -a shows
 * in your system. usually it contains prefix "can" and the numer of the can
 * line. e.g. "can0"
 * @param cm pointer to the ctrlmode struct.
 *
 * This one stores the current control mode configuration.
 *
 * Please see can_set_ctrlmode for more information about control modes.
 *
 * @return 0 if success
 * @return -1 if failed
 */

int can_get_ctrlmode(const char *name, struct can_ctrlmode *cm)
{
	return get_link(name, GET_CTRLMODE, cm);
}

/**
 * @ingroup extern
 * can_get_clock - get the current clock struct.
 *
 * @param name: name of the can device. This is the netdev name, as ifconfig -a shows
 * in your system. usually it contains prefix "can" and the numer of the can
 * line. e.g. "can0"
 * @param clock pointer to the clock struct.
 *
 * This one stores the current clock configuration. At the time of writing the
 * can_clock struct only contains information about the clock frequecy. This
 * information is e.g. essential while setting up the bit timing.
 *
 * @return 0 if success
 * @return -1 if failed
 */
int can_get_clock(const char *name, struct can_clock *clock)
{
	return get_link(name, GET_CLOCK, clock);
}

/**
 * @ingroup extern
 * can_get_bittiming_const - get the current bittimnig constant.
 *
 * @param name name of the can device. This is the netdev name, as ifconfig -a shows
 * in your system. usually it contains prefix "can" and the numer of the can
 * line. e.g. "can0"
 * @param btc pointer to the bittiming constant struct.
 *
 * This one stores the hardware dependent bittiming constant. The
 * can_bittiming_const struct consists:
 *
 * @code
 * struct can_bittiming_const {
 *	char name[16];
 *	__u32 tseg1_min;
 *	__u32 tseg1_max;
 *	__u32 tseg2_min;
 *	__u32 tseg2_max;
 *	__u32 sjw_max;
 *	__u32 brp_min;
 *	__u32 brp_max;
 *	__u32 brp_inc;
 *	};
 * @endcode
 *
 * The information in this struct is used to calculate the bus bit timing
 * automatically.
 *
 * @return 0 if success
 * @return -1 if failed
 */
int can_get_bittiming_const(const char *name, struct can_bittiming_const *btc)
{
	return get_link(name, GET_BITTIMING_CONST, btc);
}


/**
 * @ingroup extern
 * can_get_berr_counter - get the tx/rx error counter.
 *
 * @param name name of the can device. This is the netdev name, as ifconfig -a shows
 * in your system. usually it contains prefix "can" and the numer of the can
 * line. e.g. "can0"
 * @param bc pointer to the error counter struct..
 *
 * This one gets the current rx/tx error counter from the hardware.
 *
 * @code
 * struct can_berr_counter {
 *	__u16 txerr;
 *	__u16 rxerr;
 *	};
 * @endcode
 *
 * @return 0 if success
 * @return -1 if failed
 */
int can_get_berr_counter(const char *name, struct can_berr_counter *bc)
{
	return get_link(name, GET_BERR_COUNTER, bc);
}

/**
 * @ingroup extern
 * can_get_device_stats - get the can_device_stats.
 *
 * @param name name of the can device. This is the netdev name, as ifconfig -a shows
 * in your system. usually it contains prefix "can" and the numer of the can
 * line. e.g. "can0"
 * @param bc pointer to the error counter struct..
 *
 * This one gets the current can_device_stats.
 *
 * Please see struct can_device_stats for more information.
 *
 * @return 0 if success
 * @return -1 if failed
 */
int can_get_device_stats(const char *name, struct can_device_stats *cds)
{
	return get_link(name, GET_XSTATS, cds);
}

int main(int argc, char **argv)
{
	struct can_frame frame;
	struct can_frame Rx_frame;
	struct ifreq ifr;
	struct sockaddr_can addr;
	
	int family = PF_CAN, type = SOCK_RAW, proto = CAN_RAW;
	int dlc = 8;
	int s[2], ret, i, rtr = 0, extended = 0;
	int j;
	int ret1;

	can_set_bitrate("can0", 500000);
	can_do_start("can0");
	can_set_bitrate("can1", 500000);
	can_do_start("can1");

	for(j = 0; j <= 1; j++)
	{
		if(j == 0)
		{
			strcpy(ifr.ifr_name, "can0");
		}
		else if(j == 1)
		{
			strcpy(ifr.ifr_name, "can1");
		}
	
		s[j] = socket(family, type, proto);
		if (s[j] < 0)
		{
			printf("ERROR");
			return 1;
		}

		addr.can_family = family;

		if (ioctl(s[j], SIOCGIFINDEX, &ifr) < 0)
		{
			printf("ERROR");
			return 1;
		}

		addr.can_ifindex = ifr.ifr_ifindex;
		if (bind(s[j], (struct sockaddr *)&addr, sizeof(addr)) < 0)
		{
			printf("ERROR");
			return 1;
		}
		
	}
	
	for(i = 0; i < dlc; i++)
	{
		frame.data[i] = 0x31 + i;
		Rx_frame.data[i] = 0;
	}

	frame.can_id = 0x100;
	frame.can_dlc = dlc;

	if (extended)
	{
		frame.can_id &= CAN_EFF_MASK;
		frame.can_id |= CAN_EFF_FLAG;
	} 
	else
	{
		frame.can_id &= CAN_SFF_MASK;
	}

	if (rtr)
		frame.can_id |= CAN_RTR_FLAG;

	printf("\n Please connect CAN0 and CAN1 to CAN bus\n");
	
	printf("\n CAN0 transfer id: %d", frame.can_id);
	printf("\n CAN0 transfer dlc: %d", frame.can_dlc);
	printf("\n CAN0 transfer Data:\n");
	for (i = 0; i < frame.can_dlc; i++)
		printf(" 0x%02x", frame.data[i]);
	printf("\n");

	ret1 = 0;
	while(ret1 < sizeof(frame))
	{
		ret = write(s[0], &frame, sizeof(frame));
		if (ret == -1)
		{
			printf("write error !! \n");
		}

		ret1 += ret;
	}

	ret1 = 0;
	while(ret1 < sizeof(Rx_frame))
	{
		ret = read(s[1], &Rx_frame, sizeof(Rx_frame));
		if (ret == -1)
		{
			printf("write error !! \n");
		}
		ret1 += ret;
	}

	printf("\n CAN1 receive id = %d", Rx_frame.can_id);
	printf("\n CAN1 receive dlc = %d", Rx_frame.can_dlc);
	printf("\n CAN1 receive Data:\n");
	for (i = 0; i < frame.can_dlc; i++)
		printf(" 0x%02x", Rx_frame.data[i]);

	printf("\n");

	can_do_stop("can0"); 
        can_do_stop("can1");
        
	return 0;
}
Exemplo n.º 2
0
void Stack<E, F>::push_segment()
{
  assert(this->_cur_seg_size == this->_seg_size, "current segment is not full");
  E* next;
  if (this->_cache_size > 0) {
    // Use a cached segment.
    next = _cache;
    _cache = get_link(_cache);
    --this->_cache_size;
  } else {
    next = alloc(segment_bytes());
    DEBUG_ONLY(zap_segment(next, true);)
  }
  const bool at_empty_transition = is_empty();
  this->_cur_seg = set_link(next, _cur_seg);
  this->_cur_seg_size = 0;
  this->_full_seg_size += at_empty_transition ? 0 : this->_seg_size;
  DEBUG_ONLY(verify(at_empty_transition);)
}
Exemplo n.º 3
0
  const bool at_empty_transition = is_empty();
  this->_cur_seg = set_link(next, _cur_seg);
  this->_cur_seg_size = 0;
  this->_full_seg_size += at_empty_transition ? 0 : this->_seg_size;
  DEBUG_ONLY(verify(at_empty_transition);)
}

template <class E, MEMFLAGS F>
void Stack<E, F>::pop_segment()
{
  assert(this->_cur_seg_size == 0, "current segment is not empty");
  E* const prev = get_link(_cur_seg);
  if (this->_cache_size < this->_max_cache_size) {
    // Add the current segment to the cache.
    DEBUG_ONLY(zap_segment(_cur_seg, false);)
    _cache = set_link(_cur_seg, _cache);
    ++this->_cache_size;
  } else {
    DEBUG_ONLY(zap_segment(_cur_seg, true);)
    free(_cur_seg, segment_bytes());
  }
  const bool at_empty_transition = prev == NULL;
  this->_cur_seg = prev;
  this->_cur_seg_size = this->_seg_size;
  this->_full_seg_size -= at_empty_transition ? 0 : this->_seg_size;
  DEBUG_ONLY(verify(at_empty_transition);)
}

template <class E, MEMFLAGS F>
void Stack<E, F>::free_segments(E* seg)
{
Exemplo n.º 4
0
/* www_process():
 *
 * The program's signal dispatcher function. Is called whenever a signal arrives.
 */
PROCESS_THREAD(www_process, ev, data)
{
    static struct ctk_widget *w;
#if WWW_CONF_WITH_WGET
    static char *argptr;
#endif /* WWW_CONF_WITH_WGET */

    w = (struct ctk_widget *)data;

    PROCESS_BEGIN();

    /* Create the main window. */
    memset(webpage, 0, sizeof(webpage));
    ctk_window_new(&mainwindow, WWW_CONF_WEBPAGE_WIDTH,
                   WWW_CONF_WEBPAGE_HEIGHT+5, "Web browser");
    make_window();
#ifdef WWW_CONF_HOMEPAGE
    strncpy(editurl, WWW_CONF_HOMEPAGE, sizeof(editurl));
#endif /* WWW_CONF_HOMEPAGE */
    CTK_WIDGET_FOCUS(&mainwindow, &urlentry);

#if WWW_CONF_WITH_WGET || defined(WWW_CONF_WGET_EXEC)
#if CTK_CONF_WINDOWS
    /* Create download dialog.*/
    ctk_dialog_new(&wgetdialog, 38, 7);
    CTK_WIDGET_ADD(&wgetdialog, &wgetlabel1);
    CTK_WIDGET_ADD(&wgetdialog, &wgetlabel2);
    CTK_WIDGET_ADD(&wgetdialog, &wgetnobutton);
    CTK_WIDGET_ADD(&wgetdialog, &wgetyesbutton);
#endif /* CTK_CONF_WINDOWS */
#endif /* WWW_CONF_WITH_WGET || WWW_CONF_WGET_EXEC */

    ctk_window_open(&mainwindow);

    while(1) {

        PROCESS_WAIT_EVENT();

        if(ev == tcpip_event) {
            webclient_appcall(data);
        } else if(ev == ctk_signal_widget_activate) {
            if(w == (struct ctk_widget *)&gobutton ||
                    w == (struct ctk_widget *)&urlentry) {
                start_loading();
                firsty = 0;
#if WWW_CONF_HISTORY_SIZE > 0
                log_back();
#endif /* WWW_CONF_HISTORY_SIZE > 0 */
                memcpy(url, editurl, WWW_CONF_MAX_URLLEN);
                petsciiconv_toascii(url, WWW_CONF_MAX_URLLEN);
                open_url();
                CTK_WIDGET_FOCUS(&mainwindow, &gobutton);
#if WWW_CONF_HISTORY_SIZE > 0
            } else if(w == (struct ctk_widget *)&backbutton) {
                firsty = 0;
                start_loading();
                --history_last;
                if(history_last > WWW_CONF_HISTORY_SIZE) {
                    history_last = WWW_CONF_HISTORY_SIZE - 1;
                }
                memcpy(url, history[(int)history_last], WWW_CONF_MAX_URLLEN);
                open_url();
                CTK_WIDGET_FOCUS(&mainwindow, &backbutton);
#endif /* WWW_CONF_HISTORY_SIZE > 0 */
            } else if(w == (struct ctk_widget *)&downbutton) {
                firsty = pagey + WWW_CONF_WEBPAGE_HEIGHT - 4;
                start_loading();
                open_url();
                CTK_WIDGET_FOCUS(&mainwindow, &downbutton);
            } else if(w == (struct ctk_widget *)&stopbutton) {
                loading = 0;
                webclient_close();
#if WWW_CONF_WITH_WGET || defined(WWW_CONF_WGET_EXEC)
            } else if(w == (struct ctk_widget *)&wgetnobutton) {
#if CTK_CONF_WINDOWS
                ctk_dialog_close();
#else /* CTK_CONF_WINDOWS */
                clear_page();
#endif /* CTK_CONF_WINDOWS */
            } else if(w == (struct ctk_widget *)&wgetyesbutton) {
#if CTK_CONF_WINDOWS
                ctk_dialog_close();
#else /* CTK_CONF_WINDOWS */
                clear_page();
#endif /* CTK_CONF_WINDOWS */
#if WWW_CONF_WITH_WGET
                quit();
                argptr = arg_alloc((char)WWW_CONF_MAX_URLLEN);
                if(argptr != NULL) {
                    strncpy(argptr, url, WWW_CONF_MAX_URLLEN);
                }
                program_handler_load("wget.prg", argptr);
#else /* WWW_CONF_WITH_WGET */
                petsciiconv_topetscii(url, sizeof(url));
                /* Clear screen */
                ctk_restore();
                WWW_CONF_WGET_EXEC(url);
                redraw_window();
                show_statustext("Cannot exec wget");
#endif /* WWW_CONF_WITH_WGET */
#endif /* WWW_CONF_WITH_WGET || WWW_CONF_WGET_EXEC */
#if WWW_CONF_FORMS
            } else {
                /* Assume form widget. */
                struct inputattrib *input = (struct inputattrib *)
                                            (((char *)w) - offsetof(struct inputattrib, widget));
                formsubmit(input->formptr);
#endif /* WWW_CONF_FORMS */
            }
        } else if(ev == ctk_signal_hyperlink_activate) {
            firsty = 0;
#if WWW_CONF_HISTORY_SIZE > 0
            log_back();
#endif /* WWW_CONF_HISTORY_SIZE > 0 */
            set_link(w->widget.hyperlink.url);
            show_url();
            open_url();
            start_loading();
            CTK_WIDGET_FOCUS(&mainwindow, &stopbutton);
        } else if(ev == ctk_signal_hyperlink_hover) {
            if(CTK_WIDGET_TYPE((struct ctk_widget *)data) == CTK_WIDGET_HYPERLINK) {
                strncpy(statustexturl, w->widget.hyperlink.url,
                        sizeof(statustexturl));
                petsciiconv_topetscii(statustexturl, sizeof(statustexturl));
                show_statustext(statustexturl);
            }
#if UIP_UDP
        } else if(ev == resolv_event_found) {
            /* Either found a hostname, or not. */
            if((char *)data != NULL &&
                    resolv_lookup((char *)data, NULL) == RESOLV_STATUS_CACHED) {
                open_url();
            } else {
                show_statustext("Host not found");
            }
#endif /* UIP_UDP */
        } else if(ev == ctk_signal_window_close ||
                  ev == PROCESS_EVENT_EXIT) {
            quit();
        }
    }
Exemplo n.º 5
0
static inline int process_article(const struct fileheader *f,int n,const struct boardheader *b){
    static const struct flock lck_set={.l_type=F_RDLCK,.l_whence=SEEK_SET,.l_start=0,.l_len=0,.l_pid=0};
    static const struct flock lck_clr={.l_type=F_UNLCK,.l_whence=SEEK_SET,.l_start=0,.l_len=0,.l_pid=0};
    static struct stat st;
    static struct tm *p;
    static char name[BOUND];
    static int fd,i,j,k,l;
    static time_t timestamp;
    static const char *S,*M,*N;
    static void *vp;
    do{
        if((timestamp=get_posttime(f))<from||timestamp>to)
            break;
        if(ISSET(PARAM_P)&&strcmp(f->owner,post))
            break;
        setbfile(name,b->filename,f->filename);
        if(stat(name,&st)==-1||!S_ISREG(st.st_mode)||st.st_size<size)
            break;
        if((fd=open(name,O_RDONLY
#ifdef O_NOATIME
            |O_NOATIME
#endif /* O_NOATIME */
            ,0644))==-1)
            break;
        if(fcntl(fd,F_SETLKW,&lck_set)==-1){
            close(fd);
            break;
        }
        vp=mmap(NULL,st.st_size,PROT_READ,MAP_PRIVATE,fd,0);
        fcntl(fd,F_SETLKW,&lck_clr);
        close(fd);
        if((S=(const char*)vp)==MAP_FAILED)
            break;
        for(p=NULL,j=0,i=0;S[i]&&i<st.st_size;i++){
#define EQUAL(cp,cs)    (((cp)==(cs))||(ISSET(PARAM_I)&&((cp)==toupper(cs))))
            while(j>0&&!EQUAL(P[j],S[i]))
                j=L[j-1];
            if(EQUAL(P[j],S[i]))
                j++;
            if(!P[j]){
                M=&S[l=((i-j)+1)];
                if(!ISSET(PARAM_N)){
                    for(k=0,N=M;!(N<S);N--)
                        if((*N)&0x80)
                            k++;
                    if(!(k&0x01))
                        continue;
                }
                if(!p&&!(p=localtime(&timestamp)))
                    continue;
                count++;
                fprintf(out,"%6d %-20.20s %4d %4s %04d%02d%02d%02d%02d%02d %-17.17s %6d %-13.13s %s\n",
                    n,b->filename,current,mode,(p->tm_year+1900),(p->tm_mon+1),(p->tm_mday),
                    (p->tm_hour),(p->tm_min),(p->tm_sec),f->filename,l,f->owner,f->title);
                if(ISSET(PARAM_S))
                    break;
                j=L[j-1];
            }
#undef EQUAL
        }
        munmap(vp,st.st_size);
        number++;
    }
    while(0);
    return 0;
}

static inline int process_board(const struct boardheader *b,int n,void *v){
    static char name[BOUND];
    do{
        if(ISSET(PARAM_A))
            break;
        if(ISSET(PARAM_U)){
            if(!check_read_perm(user,b))
                return -1;
            break;
        }
        if(ISSET(PARAM_B))
            break;
        if(!public_board(b))
            return -2;
    }
    while(0);
    current=n;
    if(!ISSET(PARAM_Q))
        fprintf(stdout,"正在处理版面 %-29.29s ... ",b->filename);
    if(!ISSET(PARAM_E)){
        mode="版面";
        setbdir(DIR_MODE_NORMAL,name,b->filename);
        APPLY_RECORD(name,process_article,sizeof(struct fileheader),b,0,true);
    }
    if(ISSET(PARAM_D)){
        mode="回收";
        setbdir(DIR_MODE_DELETED,name,b->filename);
        APPLY_RECORD(name,process_article,sizeof(struct fileheader),b,0,true);
    }
    if(ISSET(PARAM_J)){
        mode="自删";
        setbdir(DIR_MODE_JUNK,name,b->filename);
        APPLY_RECORD(name,process_article,sizeof(struct fileheader),b,0,true);
    }
    if(!ISSET(PARAM_Q))
        fprintf(stdout,"%s\n","处理完成!");
    return 0;
}

int main(int argc,char **argv){
#define EXIT(msg)  do{fprintf(stderr,"%s\n",(msg));if(out)fclose(out);exit(__LINE__);}while(0)
    const struct boardheader *board;
    char name[BOUND],path[BOUND];
    const char *desc;
    int ret;
    double cost;
    if(!getcwd(path,BOUND))
        EXIT("获取当前工作目录时发生错误");
    if(chdir(BBSHOME)==-1)
        EXIT("切换工作目录时发生错误...");
    if((mark=time(NULL))==(time_t)(-1))
        EXIT("获取时间时发生错误...");
    resolve_ucache();
    resolve_boards();
    to=mark;
    opterr=0;
    while((ret=getopt(argc,argv,"r:f:t:ab:u:p:djesnio:qh"))!=-1){
        switch(ret){
#define CHECK_CONFLICT(param)   do{if(ISSET(param))EXIT("给定的选项间存在冲突...");}while(0)
#define CHECK_DEPENDENCE(param) do{if(!ISSET(param))EXIT("给定的选项间缺少依赖...");}while(0)
#define CHECK_DUP(param)        do{if(ISSET(param))EXIT("给定的选项中存在重复...");}while(0)
#define SET(param)              do{CHECK_DUP(param);flag|=(param);}while(0)
            case 'r':
                CHECK_CONFLICT(PARAM_F|PARAM_T);
                SET(PARAM_R);
                do{
                    struct tm t,*p;
                    int n;
                    if(!isdigit(optarg[0]))
                        EXIT("选项 -r 的参数无法解析...");
                    n=atoi(optarg);
                    if(!(p=localtime(&mark)))
                        EXIT("解析时间时发生错误...");
                    memcpy(&t,p,sizeof(struct tm));
                    t.tm_hour=0;
                    t.tm_min=0;
                    t.tm_sec=0;
                    if((from=mktime(&t))==(time_t)(-1))
                        EXIT("设定时间时发生错误...");
                }
                while(0);
                break;
#define PARSE2(p)   ((((p)[0]*10)+((p)[1]*1))-('0'*11))
#define PARSE4(p)   ((PARSE2(p)*100)+(PARSE2(&(p)[2])*1))
            case 'f':
                CHECK_CONFLICT(PARAM_R);
                SET(PARAM_F);
                do{
                    struct tm t;
                    int i;
                    for(i=0;optarg[i];i++)
                        if(!isdigit(optarg[i]))
                            break;
                    if(i!=14)
                        EXIT("选项 -f 的参数无法解析...");
                    memset(&t,0,sizeof(struct tm));
                    t.tm_year=(PARSE4(optarg)-1900);
                    t.tm_mon=(PARSE2(&optarg[4])-1);
                    t.tm_mday=PARSE2(&optarg[6]);
                    t.tm_hour=PARSE2(&optarg[8]);
                    t.tm_min=PARSE2(&optarg[10]);
                    t.tm_sec=PARSE2(&optarg[12]);
                    if((from=mktime(&t))==(time_t)(-1))
                        EXIT("设定时间时发生错误...");
                }
                while(0);
                break;
            case 't':
                CHECK_CONFLICT(PARAM_R);
                SET(PARAM_T);
                do{
                    struct tm t;
                    int i;
                    for(i=0;optarg[i];i++)
                        if(!isdigit(optarg[i]))
                            break;
                    if(i!=14)
                        EXIT("选项 -t 的参数无法解析...");
                    memset(&t,0,sizeof(struct tm));
                    t.tm_year=(PARSE4(optarg)-1900);
                    t.tm_mon=(PARSE2(&optarg[4])-1);
                    t.tm_mday=PARSE2(&optarg[6]);
                    t.tm_hour=PARSE2(&optarg[8]);
                    t.tm_min=PARSE2(&optarg[10]);
                    t.tm_sec=PARSE2(&optarg[12]);
                    if((from=mktime(&t))==(time_t)(-1))
                        EXIT("设定时间时发生错误...");
                }
                while(0);
                break;
#undef PARSE2
#undef PARSE4
            case 'a':
                CHECK_CONFLICT(PARAM_B|PARAM_U);
                SET(PARAM_A);
                break;
            case 'b':
                CHECK_CONFLICT(PARAM_A|PARAM_U);
                SET(PARAM_B);
                if(!(current=getbid(optarg,&board)))
                    EXIT("选项 -b 所指定的版面无法获取...");
                break;
            case 'u':
                CHECK_CONFLICT(PARAM_A|PARAM_B);
                SET(PARAM_U);
                do{
                    struct userec *u;
                    if(!getuser(optarg,&u))
                        EXIT("选项 -u 所指定的用户无法获取...");
                    user=u;
                }
                while(0);
                break;
            case 'p':
                SET(PARAM_P);
                snprintf(post,OWNER_LEN,"%s",optarg);
                break;
            case 'd':
                SET(PARAM_D);
                break;
            case 'j':
                SET(PARAM_J);
                break;
            case 'e':
                CHECK_DEPENDENCE(PARAM_D|PARAM_J);
                SET(PARAM_E);
                break;
            case 's':
                SET(PARAM_S);
                break;
            case 'n':
                SET(PARAM_N);
                break;
            case 'i':
                SET(PARAM_I);
                break;
            case 'o':
                SET(PARAM_O);
                if(optarg[0]!='/')
                    snprintf(name,BOUND,"%s/%s",path,optarg);
                else
                    snprintf(name,BOUND,"%s",optarg);
                break;
            case 'q':
                SET(PARAM_Q);
                break;
            case 'h':
                usage();
                return 0;
            default:
                usage();
                EXIT("不可识别的选项...");
                break;
#undef CHECK_CONFLICT
#undef CHECK_DEPENDENCE
#undef CHECK_DUP
#undef SET
        }
    }
    if(from>to){
        usage();
        EXIT("当前时间设定不合法...");
    }
    if(!ISSET(PARAM_Q)&&setvbuf(stdout,NULL,_IONBF,BUFSIZ))
        EXIT("调整文件缓冲时发生错误...");
    if((argc-optind)!=1){
        usage();
        EXIT("不可识别的参数...");
    }
    set_pattern(argv[optind]);
    set_link(argv[optind]);
    if(!size)
        EXIT("模式串不能为空串...");
    if(!ISSET(PARAM_O))
        snprintf(name,BOUND,"%s/res_%lu.us",path,mark);
    if(!(out=fopen(name,"w")))
        EXIT("打开文件时发生错误...");
    fprintf(out,"%6s %-20.20s %4s %4s %-14.14s %-17.17s %6s %-13.13s %s\n",
        "文章号","版面名称"," BID","位置","发表时间","文件名","偏移量","作者","标题");
    if(!(P[0]&0x80))
        flag|=PARAM_N;
    if(ISSET(PARAM_B))
        process_board(board,current,NULL);
    else
        APPLY_BIDS(process_board,NULL);
    fclose(out);
    cost=difftime(time(NULL),mark);
    if(cost>86400){
        cost/=86400;
        desc="天";
    }
    else if(cost>3600){
        cost/=3600;
        desc="小时";
    }
    else if(cost>60){
        cost/=60;
        desc="分钟";
    }
    else
        desc="秒";
    fprintf(stdout,"\n操作已完成! 共处理 %d 篇文章, 获得 %d 处匹配, 耗时 %.2lf %s!\n",
        number,count,cost,desc);
    return 0;
#undef EXIT
}
Exemplo n.º 6
0
main (int argc, char *argv[]){
  int  i,j,k;

  manager_init();
  parse_util_args(argc, argv);

  iparam_set("LQUAD",3);
  iparam_set("MQUAD",3);
  iparam_set("NQUAD",3);
  iparam_set("MODES",iparam("LQUAD")-1);

  char *buf = (char*) calloc(BUFSIZ, sizeof(char));
  char *fname = (char*) calloc(BUFSIZ, sizeof(char));
  get_string("Enter name of input file", buf);
  sprintf(fname, strtok(buf, "\n"));

  Grid *grid  = new Grid(fname);
  Grid *grida = new Grid(grid);

  grida->RenumberPrisms();
  grida->FixPrismOrientation();
  grid->ImportPrismOrientation(grida);
  grida->RemovePrisms();

  grida->RemoveHexes();
  grida->FixTetOrientation();
  grid->ImportTetOrientation(grida);

  Element_List *U =  grid->gen_aux_field();
  int nel = U->nel;

  get_string("Enter name of output file", buf);
  sprintf(fname, strtok(buf, "\n"));
  FILE *fout = fopen(fname, "w");


  int Nfields, Nbdry;
  get_int   ("Enter number of fields", &Nfields);
  get_int   ("Enter number of boundaries (including default)", &Nbdry);

  char **eqn = (char**) calloc(Nfields, sizeof(char*));

  for(i=0;i<Nfields;++i){
    eqn[i] = (char*)calloc(BUFSIZ, sizeof(char));
  }

  Bndry *Bc;
  Bndry **Vbc = (Bndry**) calloc(Nfields, sizeof(Bndry*));
  char *bndryeqn = (char*) calloc(BUFSIZ, sizeof(char));
  int **bcmatrix = imatrix(0, U->nel-1, 0, Max_Nfaces-1);
  izero(U->nel*Max_Nfaces, bcmatrix[0], 1);

  int nb;
  char type;
  char curved, curvetype;
  Curve *cur;
  int curveid = 0;

  for(nb=0;nb<Nbdry;++nb){
    if(nb != Nbdry-1){
      fprintf(stderr, "#\nBoundary: %d\n#\n", nb+1);
      get_string("Enter function which has roots at boundary", bndryeqn);
      fprintf(stderr, "#\n");
    }
    else{
      fprintf(stderr, "#\nDefault Boundary:\n#\n");
    }
    get_char("Enter character type\n(v=velocity)\n"
       "(W=wall)\n(O=outflow)\n(s=flux (Compressible only))\n",
       &type);
    fprintf(stderr, "#\n");
    switch(type){
    case 'W': case 'O':
      break;
    case 'v': case 's':
      for(i=0;i<Nfields;++i){
  get_string("Enter function definition", eqn[i]);
  fprintf(stderr, "\n");
      }
    }

    get_char("Is this boundary curved (y/n)?", &curved);
    if(curved == 'y'){
      ++curveid;
      get_char("Enter curve type\n(S=sphere)\n(C=cylinder)\n(T=taurus)\n",
         &curvetype);
      switch(curvetype){
      case 'S':{
  double cx, cy, cz, cr;
  get_double("Enter center x-coord", &cx);
  get_double("Enter center y-coord", &cy);
  get_double("Enter center z-coord", &cz);
  get_double("Enter radius", &cr);
  cur = (Curve*) calloc(1, sizeof(Curve));
  cur->type = T_Sphere;
  cur->info.sph.xc = cx;
  cur->info.sph.yc = cy;
  cur->info.sph.zc = cz;
  cur->info.sph.radius = cr;
  cur->id = curveid;
  break;
      }
      case 'C':{
  double cx, cy, cz, cr;
  double ax, ay, az;
  get_double("Enter point on axis x-coord", &cx);
  get_double("Enter point on axis y-coord", &cy);
  get_double("Enter point on axis z-coord", &cz);
  get_double("Enter axis vector x-coord", &ax);
  get_double("Enter axis vector y-coord", &ay);
  get_double("Enter axis vector z-coord", &az);
  get_double("Enter radius", &cr);

  cur = (Curve*) calloc(1, sizeof(Curve));
  cur->type = T_Cylinder;
  cur->info.cyl.xc = cx;
  cur->info.cyl.yc = cy;
  cur->info.cyl.zc = cz;
  cur->info.cyl.ax = ax;
  cur->info.cyl.ay = ay;
  cur->info.cyl.az = az;
  cur->info.cyl.radius = cr;
  cur->id = curveid;
  break;
      }
      }

    }
    if(nb == Nbdry-1)
      break;

    double res;
    Element *E;
    for(E=U->fhead;E;E=E->next){
      for(i=0;i<E->Nfaces;++i){
  for(j=0;j<E->Nfverts(i);++j){
    vector_def("x y z",bndryeqn);
    vector_set(1,
         &(E->vert[E->fnum(i,j)].x),
         &(E->vert[E->fnum(i,j)].y),
         &(E->vert[E->fnum(i,j)].z),
         &res);
    if(fabs(res)> TOL)
      break;
  }
  if(j==E->Nfverts(i)){
    if(curved == 'y'){
      E->curve = (Curve*) calloc(1, sizeof(Curve));
      memcpy(E->curve, cur, sizeof(Curve));
      E->curve->face = i;
    }
    switch(type){
    case 'W': case 'O':
      for(j=0;j<Nfields;++j){
        Bc = E->gen_bndry(type, i, 0.);
        Bc->type = type;
        add_bc(&Vbc[j], Bc);
      }
      bcmatrix[E->id][i] = 1;
      break;
    case 'v': case 's':
      for(j=0;j<Nfields;++j){
        Bc = E->gen_bndry(type, i, eqn[j]);
        Bc->type = type;
        add_bc(&Vbc[j], Bc);
      }
      bcmatrix[E->id][i] = 1;
      break;
    }
  }
      }
    }
  }

  char is_periodic;
  get_char("Is there periodicity in the x-direction (y/n)?", &is_periodic);
  if(is_periodic == 'y')
    get_double("Enter periodic length",&XPERIOD);
  get_char("Is there periodicity in the y-direction (y/n)?", &is_periodic);
  if(is_periodic == 'y')
    get_double("Enter periodic length",&YPERIOD);
  get_char("Is there periodicity in the z-direction (y/n)?", &is_periodic);
  if(is_periodic == 'y')
    get_double("Enter periodic length",&ZPERIOD);

  // Do remaining connections
  Element *E, *F;
  for(E=U->fhead;E;E=E->next)
    for(i=0;i<E->Nfaces;++i)
      if(!bcmatrix[E->id][i])
  for(F=E;F;F=F->next)
    for(j=0;j<F->Nfaces;++j)
      if(!bcmatrix[F->id][j])
        if(neighbourtest(E,i,F,j) && !(E->id == F->id && i==j)){
    bcmatrix[E->id][i] = 2;
    bcmatrix[F->id][j] = 2;
    set_link(E,i,F,j);
    break;
        }

  // if the default bc is curved the make default bndries curved
  if(curved == 'y'){
    for(E=U->fhead;E;E=E->next)
      for(i=0;i<E->Nfaces;++i)
  if(!bcmatrix[E->id][i]){
    E->curve = (Curve*) calloc(1, sizeof(Curve));
    memcpy(E->curve, cur, sizeof(Curve));
    E->curve->face = i;
  }
  }

  fprintf(fout, "****** PARAMETERS *****\n");
  fprintf(fout, " SolidMes \n");
  fprintf(fout, " 3 DIMENSIONAL RUN\n");
  fprintf(fout, " 0 PARAMETERS FOLLOW\n");
  fprintf(fout, "0  Lines of passive scalar data follows2 CONDUCT; 2RHOCP\n");
  fprintf(fout, " 0  LOGICAL SWITCHES FOLLOW\n");
  fprintf(fout, "Dummy line from old nekton file\n");
  fprintf(fout, "**MESH DATA** x,y,z, values of vertices 1,2,3,4.\n");
  fprintf(fout, "%d   3       1   NEL NDIM NLEVEL\n", U->nel);


  for(E=U->fhead;E;E=E->next){
    switch(E->identify()){
    case Nek_Tet:
      fprintf(fout, "Element %d Tet\n", E->id+1);
      break;
    case Nek_Pyr:
      fprintf(fout, "Element %d Pyr\n", E->id+1);
      break;
    case Nek_Prism:
      fprintf(fout, "Element %d Prism\n", E->id+1);
      break;
    case Nek_Hex:
      fprintf(fout, "Element %d Hex\n", E->id+1);
      break;
    }

    for(i=0;i<E->Nverts;++i)
      fprintf(fout, "%lf ", E->vert[i].x);
    fprintf(fout, "\n");
    for(i=0;i<E->Nverts;++i)
      fprintf(fout, "%lf ", E->vert[i].y);
    fprintf(fout, "\n");
    for(i=0;i<E->Nverts;++i)
      fprintf(fout, "%lf ", E->vert[i].z);
    fprintf(fout, "\n");
  }

  fprintf(fout, "***** CURVED SIDE DATA ***** \n");

  fprintf(fout, "%d Number of curve types\n", curveid);

  for(i=0;i<curveid;++i){
    int flag = 0;
    for(E=U->fhead;!flag && E;E=E->next){
      if(E->curve && E->curve->type != T_Straight){
  if(E->curve->id == i+1){
    switch(E->curve->type){
    case T_Sphere:
      fprintf(fout, "Sphere\n");
      fprintf(fout, "%lf %lf %lf %lf %c\n",
        E->curve->info.sph.xc,
        E->curve->info.sph.yc,
        E->curve->info.sph.zc,
        E->curve->info.sph.radius,
        'a'+i+1);
      flag = 1;
      break;
    case T_Cylinder:
      fprintf(fout, "Cylinder\n");
      fprintf(fout, "%lf %lf %lf   %lf %lf %lf %lf %c\n",
        E->curve->info.cyl.xc,
          E->curve->info.cyl.yc,
        E->curve->info.cyl.zc,
        E->curve->info.cyl.ax,
        E->curve->info.cyl.ay,
        E->curve->info.cyl.az,
        E->curve->info.cyl.radius,
          'a'+i+1);
      flag = 1;
      break;
    }
  }
      }
    }
  }
  int ncurvedsides = 0;
  for(E=U->fhead;E;E=E->next){
    if(E->curve && E->curve->type != T_Straight)
      ++ncurvedsides;
  }

  fprintf(fout, "%d Curved sides follow\n", ncurvedsides);
  for(E=U->fhead;E;E=E->next)
    if(E->curve && E->curve->type != T_Straight)
      fprintf(fout, "%d %d %c\n", E->curve->face+1, E->id+1, 'a'+E->curve->id);

  fprintf(fout, "***** BOUNDARY CONDITIONS ***** \n");
  fprintf(fout, "***** FLUID BOUNDARY CONDITIONS ***** \n");
  for(E=U->fhead;E;E=E->next){
    for(j=0;j<E->Nfaces;++j){
      if(bcmatrix[E->id][j] == 2){
  fprintf(fout, "E %d %d %d %d\n", E->id+1, j+1,
    E->face[j].link->eid+1, E->face[j].link->id+1);
      }
      else if(bcmatrix[E->id][j] == 1){
  for(i=0;i<Nfields;++i)
    for(Bc=Vbc[i];Bc;Bc=Bc->next){
      if(Bc->elmt == E && Bc->face == j){
        if(i==0)
    switch(Bc->type){
    case 'W':
      fprintf(fout, "W %d %d 0. 0. 0.\n", E->id+1, j+1);
      break;
    case 'O':
      fprintf(fout, "O %d %d 0. 0. 0.\n", E->id+1, j+1);
      break;
    case 'v':
      fprintf(fout, "v %d %d 0. 0. 0.\n", E->id+1, j+1);
      break;
    case 's':
      fprintf(fout, "s %d %d 0. 0. 0.\n", E->id+1, j+1);
      break;
    }
        if(Bc->type == 's' || Bc->type == 'v')
    fprintf(fout, "%c=%s\n", 'u'+i,Bc->bstring);
        break;
      }
    }
      }
      else{
  switch(type){
  case 'W':
    fprintf(fout, "W %d %d 0. 0. 0.\n", E->id+1, j+1);
    break;
  case 'O':
    fprintf(fout, "O %d %d 0. 0. 0.\n", E->id+1, j+1);
    break;
  case 'v':
    fprintf(fout, "v %d %d 0. 0. 0.\n", E->id+1, j+1);
    break;
  case 's':
    fprintf(fout, "s %d %d 0. 0. 0.\n", E->id+1, j+1);
    break;
  }
  if(type == 's' || type == 'v')
    for(i=0;i<Nfields;++i)
      fprintf(fout, "%c=%s\n", 'u'+i,eqn[i]);
      }
    }
  }
  char bufa[BUFSIZ];

  fprintf(fout, "***** NO THERMAL BOUNDARY CONDITIONS *****\n");
  get_char("Are you using a field file restart (y/n)?", &type);

  if(type == 'y'){
    fprintf(fout, "%d         INITIAL CONDITIONS *****\n",1);

    get_string("Enter name of restart file:", buf);
    fprintf(fout, "Restart\n");
    fprintf(fout, "%s\n", buf);
  }
  else{
    fprintf(fout, "%d         INITIAL CONDITIONS *****\n",1+Nfields);
    fprintf(fout, "Given\n");

    for(i=0;i<Nfields;++i){
      sprintf(bufa, "Field %d ", i+1);
      get_string(bufa, buf);
      fprintf(fout, "%s\n",  buf);
    }
  }

  fprintf(fout, "***** DRIVE FORCE DATA ***** PRESSURE GRAD, FLOW, Q\n");
  get_char("Are you using a forcing function (y/n)?", &type);

  if(type == 'y'){
    fprintf(fout, "%d                Lines of Drive force data follow\n",
      Nfields);

    for(i=0;i<Nfields;++i){
      sprintf(bufa, "FF%c = ", 'X'+i);
      get_string(bufa,buf);
      fprintf(fout, "FF%c = %s\n",'X'+i, buf);
    }
  }
  else{
    fprintf(fout, "0                 Lines of Drive force data follow\n");
  }

  fprintf(fout, "***** Variable Property Data ***** Overrrides Parameter data.\n");
  fprintf(fout, " 1 Lines follow.\n");
  fprintf(fout, " 0 PACKETS OF DATA FOLLOW\n");
  fprintf(fout, "***** HISTORY AND INTEGRAL DATA *****\n");
   get_char("Are you using history points (y/n)?", &type);
  if(type == 'y'){
    int npoints;

    get_int ("Enter number of points", &npoints);
    fprintf(fout, " %d   POINTS.  Hcode, I,J,H,IEL\n", npoints);
    for(i=0;i<npoints;++i){
      sprintf(bufa, "Enter element number for point %d", i+1);
      get_int(bufa,&j);
      sprintf(bufa, "Enter vertex  number for point %d", i+1);
      get_int(bufa, &k);
      fprintf(fout, "UVWP H %d 1 1 %d\n", k, j);
    }
  }
  else{
    fprintf(fout, " 0   POINTS.  Hcode, I,J,H,IEL\n");
  }

  fprintf(fout, " ***** OUTPUT FIELD SPECIFICATION *****\n");
  fprintf(fout, "  0 SPECIFICATIONS FOLLOW\n");

  return 0;
}
Exemplo n.º 7
0
bool set_union(int x, int y) { return set_link(set_find(x), set_find(y)); }
Exemplo n.º 8
0
static void
lru_save(const br_ssl_session_cache_class **ctx,
	br_ssl_server_context *server_ctx,
	const br_ssl_session_parameters *params)
{
	br_ssl_session_cache_lru *cc;
	unsigned char id[SESSION_ID_LEN];
	uint32_t x, alx;

	cc = (br_ssl_session_cache_lru *)ctx;

	/*
	 * If the buffer is too small, we don't record anything. This
	 * test avoids problems in subsequent code.
	 */
	if (cc->store_len < LRU_ENTRY_LEN) {
		return;
	}

	/*
	 * Upon the first save in a session cache instance, we obtain
	 * a random key for our indexing.
	 */
	if (!cc->init_done) {
		br_hmac_drbg_generate(&server_ctx->eng.rng,
			cc->index_key, sizeof cc->index_key);
		cc->hash = br_hmac_drbg_get_hash(&server_ctx->eng.rng);
		cc->init_done = 1;
	}
	mask_id(cc, params->session_id, id);

	/*
	 * Look for the node in the tree. If the same ID is already used,
	 * then reject it. This is a collision event, which should be
	 * exceedingly rare.
	 * Note: we do NOT record the emplacement here, because the
	 * removal of an entry may change the tree topology.
	 */
	if (find_node(cc, id, NULL) != ADDR_NULL) {
		return;
	}

	/*
	 * Find some room for the new parameters. If the cache is not
	 * full yet, add it to the end of the area and bump the pointer up.
	 * Otherwise, evict the list tail entry. Note that we already
	 * filtered out the case of a ridiculously small buffer that
	 * cannot hold any entry at all; thus, if there is no room for an
	 * extra entry, then the cache cannot be empty.
	 */
	if (cc->store_ptr > (cc->store_len - LRU_ENTRY_LEN)) {
		/*
		 * Evict tail. If the buffer has room for a single entry,
		 * then this may also be the head.
		 */
		x = cc->tail;
		cc->tail = get_prev(cc, x);
		if (cc->tail == ADDR_NULL) {
			cc->head = ADDR_NULL;
		} else {
			set_next(cc, cc->tail, ADDR_NULL);
		}

		/*
		 * Remove the node from the tree.
		 */
		remove_node(cc, x);
	} else {
		/*
		 * Allocate room for new node.
		 */
		x = cc->store_ptr;
		cc->store_ptr += LRU_ENTRY_LEN;
	}

	/*
	 * Find the emplacement for the new node, and link it.
	 */
	find_node(cc, id, &alx);
	set_link(cc, alx, x);
	set_left(cc, x, ADDR_NULL);
	set_right(cc, x, ADDR_NULL);

	/*
	 * New entry becomes new list head. It may also become the list
	 * tail if the cache was empty at that point.
	 */
	if (cc->head == ADDR_NULL) {
		cc->tail = x;
	} else {
		set_prev(cc, cc->head, x);
	}
	set_prev(cc, x, ADDR_NULL);
	set_next(cc, x, cc->head);
	cc->head = x;

	/*
	 * Fill data in the entry.
	 */
	memcpy(cc->store + x + SESSION_ID_OFF, id, SESSION_ID_LEN);
	memcpy(cc->store + x + MASTER_SECRET_OFF,
		params->master_secret, MASTER_SECRET_LEN);
	br_enc16be(cc->store + x + VERSION_OFF, params->version);
	br_enc16be(cc->store + x + CIPHER_SUITE_OFF, params->cipher_suite);
}
Exemplo n.º 9
0
/*
 * Remove node 'x' from the tree. This function shall not be called if
 * node 'x' is not part of the tree.
 */
static void
remove_node(br_ssl_session_cache_lru *cc, uint32_t x)
{
	uint32_t alx, y, aly;

	/*
	 * Removal algorithm:
	 * ------------------
	 *
	 * - If we remove the root, then the tree becomes empty.
	 *
	 * - If the removed node has no child, then we can simply remove
	 *   it, with nothing else to do.
	 *
	 * - Otherwise, the removed node must be replaced by either its
	 *   rightmost left-descendent, or its leftmost right-descendent.
	 *   The replacement node itself must be removed from its current
	 *   place. By definition, that replacement node has either no
	 *   child, or at most a single child that will replace it in the
	 *   tree.
	 */

	/*
	 * Find node back and its ancestor link. If the node was the
	 * root, then alx is set to ADDR_NULL.
	 */
	find_node(cc, cc->store + x + SESSION_ID_OFF, &alx);

	/*
	 * Find replacement node 'y', and 'aly' is set to the address of
	 * the link to that replacement node. If the removed node has no
	 * child, then both 'y' and 'aly' are set to ADDR_NULL.
	 */
	y = find_replacement_node(cc, x, &aly);

	if (y != ADDR_NULL) {
		uint32_t z;

		/*
		 * The unlinked replacement node may have one child (but
		 * not two) that takes its place.
		 */
		z = get_left(cc, y);
		if (z == ADDR_NULL) {
			z = get_right(cc, y);
		}
		set_link(cc, aly, z);

		/*
		 * Link the replacement node in its new place, overwriting
		 * the current link to the node 'x' (which removes 'x').
		 */
		set_link(cc, alx, y);

		/*
		 * The replacement node adopts the left and right children
		 * of the removed node. Note that this also works even if
		 * the replacement node was a direct descendent of the
		 * removed node, since we unlinked it previously.
		 */
		set_left(cc, y, get_left(cc, x));
		set_right(cc, y, get_right(cc, x));
	} else {
		/*
		 * No replacement, we simply unlink the node 'x'.
		 */
		set_link(cc, alx, ADDR_NULL);
	}
}