/** * @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; }
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);) }
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) {
/* 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(); } }
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(×tamp))) 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 }
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; }
bool set_union(int x, int y) { return set_link(set_find(x), set_find(y)); }
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); }
/* * 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); } }