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

Last change on this file since 16 was 16, checked in by bouyer, 7 weeks 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.