Lines 18-23
Link Here
|
18 |
#include <sys/socket.h> |
18 |
#include <sys/socket.h> |
19 |
#include <sys/ioctl.h> |
19 |
#include <sys/ioctl.h> |
20 |
|
20 |
|
|
|
21 |
#include <pwd.h> |
22 |
#include <grp.h> |
23 |
|
21 |
#include <net/if.h> |
24 |
#include <net/if.h> |
22 |
#include <netax25/ax25.h> |
25 |
#include <netax25/ax25.h> |
23 |
#include <netrose/rose.h> |
26 |
#include <netrose/rose.h> |
Lines 32-37
Link Here
|
32 |
#define N_6PACK 7 /* This is valid for all architectures in 2.2.x */ |
35 |
#define N_6PACK 7 /* This is valid for all architectures in 2.2.x */ |
33 |
#endif |
36 |
#endif |
34 |
|
37 |
|
|
|
38 |
#define PTMX_TTY "/dev/ptmx" |
39 |
|
35 |
static char *callsign; |
40 |
static char *callsign; |
36 |
static int speed = 0; |
41 |
static int speed = 0; |
37 |
static int mtu = 0; |
42 |
static int mtu = 0; |
Lines 42-47
Link Here
|
42 |
static char *inetaddr = NULL; |
47 |
static char *inetaddr = NULL; |
43 |
static int allow_broadcast = 0; |
48 |
static int allow_broadcast = 0; |
44 |
static int i_am_unix98_pty_master = 0; /* unix98 ptmx support */ |
49 |
static int i_am_unix98_pty_master = 0; /* unix98 ptmx support */ |
|
|
50 |
static int symlink_pty = 0; |
45 |
|
51 |
|
46 |
static char *kiss_basename(char *s) |
52 |
static char *kiss_basename(char *s) |
47 |
{ |
53 |
{ |
Lines 58-63
Link Here
|
58 |
|
64 |
|
59 |
if (!i_am_unix98_pty_master) |
65 |
if (!i_am_unix98_pty_master) |
60 |
tty_unlock(kttyname); |
66 |
tty_unlock(kttyname); |
|
|
67 |
else if (symlink_pty) |
68 |
unlink(kttyname); |
61 |
|
69 |
|
62 |
exit(0); |
70 |
exit(0); |
63 |
} |
71 |
} |
Lines 214-220
Link Here
|
214 |
|
222 |
|
215 |
static void usage(void) |
223 |
static void usage(void) |
216 |
{ |
224 |
{ |
217 |
fprintf(stderr, "usage: %s [-b] [-l] [-m mtu] [-v] tty port [inetaddr]\n", progname); |
225 |
fprintf(stderr, "usage: %s [-b] [-l] [-m mtu] [-v] [-o user:group] [-p mode] tty port [inetaddr]\n", |
|
|
226 |
progname); |
218 |
} |
227 |
} |
219 |
|
228 |
|
220 |
int main(int argc, char *argv[]) |
229 |
int main(int argc, char *argv[]) |
Lines 227-238
Link Here
|
227 |
* the client has to use */ |
236 |
* the client has to use */ |
228 |
struct hostent *hp = NULL; |
237 |
struct hostent *hp = NULL; |
229 |
|
238 |
|
|
|
239 |
/* Name of the user and group who will "own" the pty */ |
240 |
char* pty_owner_user = NULL; |
241 |
char* pty_owner_group = NULL; |
242 |
/* Mode for pty: if 0; use defaults */ |
243 |
mode_t pty_mode = 0; |
244 |
|
230 |
progname = kiss_basename(argv[0]); |
245 |
progname = kiss_basename(argv[0]); |
231 |
|
246 |
|
232 |
if (!strcmp(progname, "spattach")) |
247 |
if (!strcmp(progname, "spattach")) |
233 |
disc = N_6PACK; |
248 |
disc = N_6PACK; |
234 |
|
249 |
|
235 |
while ((fd = getopt(argc, argv, "b6i:lm:v")) != -1) { |
250 |
while ((fd = getopt(argc, argv, "b6i:lm:o:p:v")) != -1) { |
236 |
switch (fd) { |
251 |
switch (fd) { |
237 |
case '6': |
252 |
case '6': |
238 |
disc = N_6PACK; |
253 |
disc = N_6PACK; |
Lines 253-258
Link Here
|
253 |
return 1; |
268 |
return 1; |
254 |
} |
269 |
} |
255 |
break; |
270 |
break; |
|
|
271 |
case 'o': |
272 |
/* Change the owner of the pty */ |
273 |
{ |
274 |
char* colon = index(optarg,':'); |
275 |
if (colon) { |
276 |
pty_owner_user = optarg; |
277 |
pty_owner_group = colon + 1; |
278 |
*colon = 0; |
279 |
} else { |
280 |
fprintf(stderr, "%s: Must specify user:group\n", progname); |
281 |
return 1; |
282 |
} |
283 |
} |
284 |
break; |
285 |
case 'p': |
286 |
/* Change the permissions (mode) of the pty */ |
287 |
pty_mode = (mode_t)strtoul(optarg, NULL, 8); |
288 |
break; |
256 |
case 'v': |
289 |
case 'v': |
257 |
printf("%s: %s\n", progname, VERSION); |
290 |
printf("%s: %s\n", progname, VERSION); |
258 |
return 0; |
291 |
return 0; |
Lines 278-285
Link Here
|
278 |
if (argc-1 >= optind && !inetaddr) |
311 |
if (argc-1 >= optind && !inetaddr) |
279 |
inetaddr = argv[optind]; |
312 |
inetaddr = argv[optind]; |
280 |
|
313 |
|
281 |
if (!strcmp("/dev/ptmx", kttyname)) |
314 |
if (!strcmp(PTMX_TTY, kttyname)) { |
|
|
315 |
i_am_unix98_pty_master = 1; |
316 |
} else if (strstr(kttyname, "pty:") == kttyname) { |
317 |
/* |
318 |
* If the path starts with pty:, then create a |
319 |
* new pty (Unix98 style) and make a symlink to it |
320 |
*/ |
282 |
i_am_unix98_pty_master = 1; |
321 |
i_am_unix98_pty_master = 1; |
|
|
322 |
kttyname = index(kttyname, ':') + 1; |
323 |
symlink_pty = 1; |
324 |
} |
283 |
|
325 |
|
284 |
if (!i_am_unix98_pty_master) { |
326 |
if (!i_am_unix98_pty_master) { |
285 |
if (tty_is_locked(kttyname)) { |
327 |
if (tty_is_locked(kttyname)) { |
Lines 296-302
Link Here
|
296 |
return 1; |
338 |
return 1; |
297 |
} |
339 |
} |
298 |
|
340 |
|
299 |
if ((fd = open(kttyname, O_RDONLY | O_NONBLOCK)) == -1) { |
341 |
if ((fd = open((symlink_pty ? PTMX_TTY : kttyname), O_RDONLY | O_NONBLOCK)) == -1) { |
300 |
if (errno == ENOENT) { |
342 |
if (errno == ENOENT) { |
301 |
fprintf(stderr, "%s: Cannot find serial device %s, no such file or directory.\n", progname, kttyname); |
343 |
fprintf(stderr, "%s: Cannot find serial device %s, no such file or directory.\n", progname, kttyname); |
302 |
} else { |
344 |
} else { |
Lines 353-364
Link Here
|
353 |
|
395 |
|
354 |
printf("AX.25 port %s bound to device %s\n", portname, dev); |
396 |
printf("AX.25 port %s bound to device %s\n", portname, dev); |
355 |
if (i_am_unix98_pty_master) { |
397 |
if (i_am_unix98_pty_master) { |
356 |
/* Users await the slave pty to be referenced in the 3d line */ |
398 |
/* Are we being asked to chown? */ |
357 |
printf("Awaiting client connects on\n%s\n", namepts); |
399 |
if (pty_owner_user) { |
|
|
400 |
/* Look up the user */ |
401 |
struct passwd user; |
402 |
struct passwd* user_ptr = NULL; |
403 |
struct group grp; |
404 |
struct group* grp_ptr = NULL; |
405 |
char buffer[512]; |
406 |
int err = getpwnam_r(pty_owner_user, &user, |
407 |
buffer, sizeof(buffer)-1, &user_ptr); |
408 |
if (err) { |
409 |
fprintf(stderr, |
410 |
"Failed to look up user: %s (%d)\n", |
411 |
strerror(err), err); |
412 |
return 1; |
413 |
} |
414 |
|
415 |
err = getgrnam_r(pty_owner_group, &grp, |
416 |
buffer, sizeof(buffer)-1, &grp_ptr); |
417 |
if (err) { |
418 |
fprintf(stderr, |
419 |
"Failed to look up group: %s (%d)\n", |
420 |
strerror(err), err); |
421 |
return 1; |
422 |
} |
423 |
|
424 |
if (user_ptr && grp_ptr && |
425 |
chown(namepts, user_ptr->pw_uid, |
426 |
grp_ptr->gr_gid)) { |
427 |
fprintf(stderr, |
428 |
"Failed to change ownership: %s (%d)\n", |
429 |
strerror(errno), errno); |
430 |
return 1; |
431 |
} |
432 |
} |
433 |
|
434 |
/* Are we being asked to chmod? */ |
435 |
if (pty_mode) { |
436 |
if (chmod(namepts, pty_mode)) { |
437 |
fprintf(stderr, |
438 |
"Failed to change mode: %s (%d)\n", |
439 |
strerror(errno), errno); |
440 |
} |
441 |
} |
442 |
|
443 |
if (symlink_pty) { |
444 |
/* Create the symlink */ |
445 |
if (symlink(namepts, kttyname)) { |
446 |
fprintf(stderr, |
447 |
"Failed to symlink PTY %s to %s: %s (%d)\n", |
448 |
kttyname, namepts, strerror(errno), errno); |
449 |
return 1; |
450 |
} |
451 |
} else { |
452 |
/* Users await the slave pty to be referenced in the 3d line */ |
453 |
printf("Awaiting client connects on\n%s\n", namepts); |
454 |
} |
358 |
} |
455 |
} |
359 |
if (logging) { |
456 |
if (logging) { |
360 |
openlog(progname, LOG_PID, LOG_DAEMON); |
457 |
openlog(progname, LOG_PID, LOG_DAEMON); |
361 |
syslog(LOG_INFO, "AX.25 port %s bound to device %s%s%s\n", portname, dev, (i_am_unix98_pty_master ? " with slave pty " : ""), (i_am_unix98_pty_master ? namepts : "")); |
458 |
syslog(LOG_INFO, "AX.25 port %s bound to device %s%s%s\n", portname, dev, (i_am_unix98_pty_master ? " with slave pty " : ""), (i_am_unix98_pty_master ? namepts : "")); |
|
|
459 |
if (symlink_pty) |
460 |
syslog(LOG_INFO, "Slave pty %s is symlinked to %s.", namepts, kttyname); |
362 |
|
461 |
|
363 |
} |
462 |
} |
364 |
|
463 |
|