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);