3 * .../summon <real-summoner> <calling-nick> <calling-path> <channel>
14 #include <sys/types.h>
18 static void check(const char *string
, const char *what
, int maxlen
) {
21 if (strlen(string
) > maxlen
) { fprintf(stderr
,"%s too long\n",what
); exit(8); }
22 while ((c
= *string
++)) {
23 if (isspace((unsigned char)c
) || !isprint((unsigned char)c
))
24 { fprintf(stderr
,"bad char in %s\n",what
); exit(8); }
28 static void die(const char *msg
) {
29 fprintf(stderr
,"%s\n",msg
); exit(8);
32 static void problem(const char *msg
) {
33 printf("problem %s\n",msg
);
37 enum howbad
{ hb_notlogon
, hb_noterminal
, hb_nomessages
, hb_ok
};
38 static enum howbad closest
= hb_notlogon
;
40 static time_t best_idle
;
41 static char best_line
[UT_LINESIZE
+1];
43 static void thisis(enum howbad hb
) {
44 if (hb
> closest
) closest
= hb
;
47 int main(int argc
, const char *const *argv
) {
54 if (argc
!= 5) die("bad usage");
56 myself
= getenv("USER");
57 if (!myself
) die("USER not set");
58 if (strlen(myself
) > UT_NAMESIZE
) die("own username too long");
60 check(argv
[2],"nick",20);
61 check(argv
[3],"path",60);
62 check(argv
[4],"channel",20);
64 if (chdir("/dev")) { perror("chdir /dev"); exit(8); }
66 while ((errno
=0, ue
= getutent())) {
67 if (ue
->ut_type
!= USER_PROCESS
) continue;
68 if (strncmp(ue
->ut_user
,myself
,UT_NAMESIZE
)) continue;
69 if (!ue
->ut_line
[0]) { thisis(hb_noterminal
); continue; }
70 ue
->ut_line
[UT_LINESIZE
]= 0; /* overflows into next field :-/ */
71 if (stat(ue
->ut_line
,&stab
)) {
72 printf("warning could not stat %s: %s\n",ue
->ut_line
,strerror(errno
));
73 thisis(hb_noterminal
); continue;
75 if (!(stab
.st_mode
& S_IWGRP
)) { thisis(hb_nomessages
); continue; }
77 if (closest
== hb_ok
&& stab
.st_atime
<= best_idle
) continue;
78 strcpy(best_line
,ue
->ut_line
);
79 best_idle
= stab
.st_atime
;
81 if (errno
) { perror("getutent set errno"); exit(8); }
84 case hb_notlogon
: problem("is not logged on");
85 case hb_noterminal
: problem("does not have any terminal/shell sessions");
86 case hb_nomessages
: problem("is refusing messages");
91 sprintf(idlebuf
,"%lu",(unsigned long)best_idle
);
93 fd
= open(best_line
, O_NOCTTY
|O_NONBLOCK
|O_WRONLY
);
95 fprintf(stderr
,"unable to open terminal (%s): %s",best_line
,strerror(errno
));
98 if (dup2(fd
,0)) { perror("dup2"); exit(8); }
99 execlp(argv
[1],argv
[1], best_line
,idlebuf
,argv
[2],argv
[3],argv
[4], (const char*)0);
100 perror(argv
[1]); exit(8);