| 59 | }; |
| 60 | |
| 61 | static int |
| 62 | WriteCmd(int ac, char **av) |
| 63 | { |
| 64 | u_int32_t sagbuf[64]; |
| 65 | struct sockaddr_ng *sag = (struct sockaddr_ng *)sagbuf; |
| 66 | u_char buf[BUF_SIZE]; |
| 67 | const char *hook; |
| 68 | FILE *fp; |
| 69 | u_int len; |
| 70 | int byte; |
| 71 | int i; |
| 72 | |
| 73 | /* Get arguments */ |
| 74 | if (ac < 3) |
| 75 | return (CMDRTN_USAGE); |
| 76 | hook = av[1]; |
| 77 | |
| 78 | /* Get data */ |
| 79 | if (strcmp(av[2], "-f") == 0) { |
| 80 | if (ac != 4) |
| 81 | return (CMDRTN_USAGE); |
| 82 | if ((fp = fopen(av[3], "r")) == NULL) { |
| 83 | warn("can't read file \"%s\"", av[3]); |
| 84 | return (CMDRTN_ERROR); |
| 85 | } |
| 86 | if ((len = fread(buf, 1, sizeof(buf), fp)) == 0) { |
| 87 | if (ferror(fp)) |
| 88 | warn("can't read file \"%s\"", av[3]); |
| 89 | else |
| 90 | warnx("file \"%s\" is empty", av[3]); |
| 91 | fclose(fp); |
| 92 | return (CMDRTN_ERROR); |
| 93 | } |
| 94 | fclose(fp); |
| 95 | } else { |
| 96 | for (i = 2, len = 0; i < ac && len < sizeof(buf); i++, len++) { |
| 97 | if (sscanf(av[i], "%i", &byte) != 1 |
| 98 | || (byte < -128 || byte > 255)) { |
| 99 | warnx("invalid byte \"%s\"", av[i]); |
| 100 | return (CMDRTN_ERROR); |
| 101 | } |
| 102 | buf[len] = (u_char)byte; |
| 103 | } |
| 104 | if (len == 0) |
| 105 | return (CMDRTN_USAGE); |
| 106 | } |
| 107 | |
| 108 | /* Send data */ |
| 109 | sag->sg_len = 3 + strlen(hook); |
| 110 | sag->sg_family = AF_NETGRAPH; |
| 111 | #if __GNUC__ >= 13 |
| 112 | #pragma GCC diagnostic push |
| 113 | #pragma GCC diagnostic ignored "-Wstringop-overflow" |
| 114 | #endif |
| 115 | strlcpy(sag->sg_data, hook, sizeof(sagbuf) - 2); |
| 116 | #if __GNUC__ >= 13 |
| 117 | #pragma GCC diagnostic pop |
| 118 | #endif |