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

Last change on this file since 16 was 16, checked in by bouyer, 11 months ago

For the 'P' command, check that the user is in group wheel or sudo

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                }
91                if ((i = getgrouplist(pwp->pw_name, pwp->pw_gid, mygroups, &ngroups))
92                    != 0) {
93                        fprintf(stderr, "getgrouplist(%s,%d) fail: %d %d\n",
94                            pwp->pw_name, pwp->pw_gid, i, ngroups);
95                        exit(1);
96                }
97                for (i = 0; i < ngroups; i++) {
98                        struct group *grpp = getgrgid(mygroups[i]);
99                        if (grpp == NULL) {
100                                err(1, "getgrgid(%d)", mygroups[i]);
101                        }
102                        if (strcmp(grpp->gr_name, "wheel") == 0 ||
103                            strcmp(grpp->gr_name, "sudo") == 0) {
104                                break;
105                        }
106                }
107                if (i == ngroups) {
108                        errx(1, "command %s: permission denied", argv[1]);
109                }
110        }
[15]111
112        d = open(argv[0], O_RDWR | O_NOCTTY | O_NONBLOCK, 0);
113        if (d < 0) {
114                err(1, "open %s", argv[0]);
115        }
116
117        if (tcgetattr(d, &ot) < 0) {
118                err(1, "tcgetattr");
119        }
120
121        quit = 0;
122
123        if (signal(SIGINT, set_quit) == SIG_ERR) {
124                err(1, "signal(SIGINT)");
125        }
126        if (signal(SIGQUIT, set_quit) == SIG_ERR) {
127                err(1, "signal(SIGQUIT)");
128        }
129        if (signal(SIGPIPE, set_quit) == SIG_ERR) {
130                err(1, "signal(SIGPIPE)");
131        }
132        if (signal(SIGTERM, set_quit) == SIG_ERR) {
133                err(1, "signal(SIGTERM)");
134        }
135
136        t = ot;
137        cfmakeraw(&t);
138        t.c_cflag |= CLOCAL;
139        t.c_cflag &= ~CRTSCTS;
140        cfsetspeed(&t, B921600);
141
142        if (tcsetattr(d, TCSANOW | TCSAFLUSH, &t) < 0) {
143                err(1, "tcsetattr");
144        }
145        do {
146                write(d, "M0\n", 3);
147                readline(d, buf, sizeof(buf));
148                if (quit)
149                        goto quit;
150        } while (memcmp(buf, "OK", 2) != 0);
151
152        snprintf(buf, sizeof(buf) - 1, "%s\n", argv[1]);
153        write(d, buf, strlen(buf));
154        readline(d, buf, sizeof(buf));
155        if (quit)
156                goto quit;
157        printf("%s\n", buf);
158quit:
159        if (fflush(stdout) == EOF) {
160                warn("fflush");
161        }
162        if (tcsetattr(d, TCSANOW, &ot) < 0) {
163                err(1, "restore tcsetattr");
164        }
165        exit(0);
166}
Note: See TracBrowser for help on using the repository browser.