source: trunk/software/tty/readtty_command.c @ 17

Last change on this file since 17 was 17, checked in by bouyer, 7 weeks ago

FIx for getgrouplist() different return value between BSD and linux

File size: 3.1 KB
RevLine 
[15]1#include <stdio.h>
2#include <stdlib.h>
3#include <unistd.h>
4#include <string.h>
5#include <errno.h>
6#include <err.h>
7#include <fcntl.h>
8#include <signal.h>
9#include <termios.h>
10#include <sys/ioctl.h>
11#include <sys/select.h>
[16]12#include <pwd.h>
13#include <grp.h>
[15]14
15volatile int quit;
16const char *prog;
17
18static void
19set_quit(int s)
20{
21        quit = 1;
22}
23
24static void
25usage()
26{
27        errx(1, "usage: %s <device> <cmd>", prog);
28}
29
30static void
31readline(int d, char *buf, int l)
32{
33        int i;
34        int bytes;
35        do {
36                for (i = 0; i < l; i++) {
37                        do {
38                                bytes = read(d, &buf[i], 1);
39                                if (quit)
40                                        return;
41                        } while ((bytes < 0 && errno == EAGAIN) || buf[i] == '\r');
42                        if (bytes != 1) {
43                                fprintf(stderr, "readline: read %d\n", bytes);
44                                err(1, "read line");
45                        }
46                        if (buf[i] == '\n')
47                                break;
48                }
49        } while (i == 0);
50        if (buf[i] != '\n') {
51                warnx("realine: end of line not found");
52        }
53        buf[i] = '\0';
54}
55
56int
57main(int argc, char * const argv[])
58{
59        int d;
60        int bytes;
61        int nfds;
62        int lineno = 0;
63        char buf[256];
64        int i;
65        fd_set rfds;
66        char *endp;
67        int gpioi, currenti, tensioni;
68        float current_a, tension_v;
69        int val, gpio_val;
70        int c_opt = 0, v_opt = 0;
71        extern char *optarg;
72        extern int optind;
73        int ch;
74
75        struct termios t, ot;
76
77        prog = argv[0];
78        argc -= 1;
79        argv += 1;
80
81        if (argc != 2)
82                usage();
[16]83        if (*argv[1] == 'P') {
84                /* check if user is in group wheel or sudo */
85                gid_t mygroups[64];
86                int ngroups = 64;
87                struct passwd *pwp = getpwuid(getuid());
88                if (pwp == NULL) {
89                        err(1, "getpwuid(%d)", getuid());
90                }
[17]91                if ((i = getgrouplist(pwp->pw_name, pwp->pw_gid, mygroups, &ngroups)) < 0) {
[16]92                        fprintf(stderr, "getgrouplist(%s,%d) fail: %d %d\n",
93                            pwp->pw_name, pwp->pw_gid, i, ngroups);
94                        exit(1);
95                }
96                for (i = 0; i < ngroups; i++) {
97                        struct group *grpp = getgrgid(mygroups[i]);
98                        if (grpp == NULL) {
99                                err(1, "getgrgid(%d)", mygroups[i]);
100                        }
101                        if (strcmp(grpp->gr_name, "wheel") == 0 ||
102                            strcmp(grpp->gr_name, "sudo") == 0) {
103                                break;
104                        }
105                }
106                if (i == ngroups) {
107                        errx(1, "command %s: permission denied", argv[1]);
108                }
109        }
[15]110
111        d = open(argv[0], O_RDWR | O_NOCTTY | O_NONBLOCK, 0);
112        if (d < 0) {
113                err(1, "open %s", argv[0]);
114        }
115
116        if (tcgetattr(d, &ot) < 0) {
117                err(1, "tcgetattr");
118        }
119
120        quit = 0;
121
122        if (signal(SIGINT, set_quit) == SIG_ERR) {
123                err(1, "signal(SIGINT)");
124        }
125        if (signal(SIGQUIT, set_quit) == SIG_ERR) {
126                err(1, "signal(SIGQUIT)");
127        }
128        if (signal(SIGPIPE, set_quit) == SIG_ERR) {
129                err(1, "signal(SIGPIPE)");
130        }
131        if (signal(SIGTERM, set_quit) == SIG_ERR) {
132                err(1, "signal(SIGTERM)");
133        }
134
135        t = ot;
136        cfmakeraw(&t);
137        t.c_cflag |= CLOCAL;
138        t.c_cflag &= ~CRTSCTS;
139        cfsetspeed(&t, B921600);
140
141        if (tcsetattr(d, TCSANOW | TCSAFLUSH, &t) < 0) {
142                err(1, "tcsetattr");
143        }
144        do {
145                write(d, "M0\n", 3);
146                readline(d, buf, sizeof(buf));
147                if (quit)
148                        goto quit;
149        } while (memcmp(buf, "OK", 2) != 0);
150
151        snprintf(buf, sizeof(buf) - 1, "%s\n", argv[1]);
152        write(d, buf, strlen(buf));
153        readline(d, buf, sizeof(buf));
154        if (quit)
155                goto quit;
156        printf("%s\n", buf);
157quit:
158        if (fflush(stdout) == EOF) {
159                warn("fflush");
160        }
161        if (tcsetattr(d, TCSANOW, &ot) < 0) {
162                err(1, "restore tcsetattr");
163        }
164        exit(0);
165}
Note: See TracBrowser for help on using the repository browser.