/* PIPClient - A client for finger protocol v2 * * Copyright (C) 1999 Michael Baumer * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ #include #include #include #include #include #ifdef HAVE_STRINGS_H #include #endif /* HAVE_STRINGS_H */ #include #include #include #include #if HAVE_SYS_WAIT_H # include #endif #ifndef WEXITSTATUS # define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8) #endif #ifndef WIFEXITED # define WIFEXITED(stat_val) (((stat_val) & 255) == 0) #endif #include "parser.h" #include "configfile.h" #include "conn.h" #include "request.h" #include "compat.h" #ifndef HAVE_GETOPT_DECL int getopt(int argc, char **argv, char *optstring); extern char *optarg; extern int optind; #endif int debug = 0; int gnufinger = 0; int realnames = 0; int test = 0; Node *cf; char *configfile; extern void addText(char *txt, int font); extern void create_gui_gtk(); extern void gui_add_user(char *name, int status); /* Create the GUI */ void create_gui() { create_gui_gtk(); } /* Start the in.fingerd via exec & pipes * * Used for testing a fresh compilation of in.fingerd * Note: in.fingerd is started in the current working dir! * * parameters: * debug: verbose output or not * cmd : the command string to send. Must include "" */ void test_connection(int debug, char *cmd) { /* make a sample connection for testing the client */ int pid; int status; int pin[2]; int pout[2]; if (setvbuf(stdout, NULL, _IOLBF, 0) < 0) { perror("setvbuf(stdout)"); exit(1); } /* open pipes */ if (pipe(pin) || pipe(pout)) { perror("opening pipe"); exit(1); } /* fork */ pid = fork(); if(!pid) { /* child */ /* redirect filedes */ /* pin[read] auf stdin legen*/ close(0); dup(pin[0]); /*pout[write] auf stdout legen*/ close(1); dup(pout[1]); close(pin[1]); close(pout[0]); close(pin[0]); close(pout[1]); if (gnufinger) execl("in.fingerd", "in.fingerd", "-g", NULL); else execl("in.fingerd", "in.fingerd", NULL); perror("Starting child"); exit(-15); } if (debug) printf("started client : pid=%d\n", pid); /* * parent */ close(pin[0]); close(pout[1]); send_request(pin[1], pout[0], cmd); if (debug) printf("Waiting for Child to terminate\n"); wait(&status); if (debug) printf("Child terminated with status: %d\n", status); /* close all open filedesc */ close(pin[1]); close(pout[0]); } void show_online_user(Node *node) { Node *subnode; Node *s2node; char *login; char *realname; int status; subnode = node->child; while(subnode) { login = NULL; status = 0; s2node = subnode->child; while (s2node) { if (!strcmp(s2node->id, "login")) { login = s2node->value; } else if (!strcmp(s2node->id, "status")) { if (!strcmp(s2node->value, "active")) status = 1; } else if (!strcmp(s2node->id, "realname")) { realname = s2node->value; } s2node = s2node->next; } if (login) { if (realnames) gui_add_user(realname, status); else gui_add_user(login, status); } subnode = subnode->next; } } /* Show userinfo */ void show_userinfo(Node *node) { Node *cur_node; char txt[120]; /* Output everything */ cur_node = node->child; while (cur_node) { if (!strcmp(cur_node->id, "userinfo")) { cur_node = cur_node->child; while(cur_node) { /* Handle specials */ /* if (strcmp(cur_node->id, "first") && strcmp(cur_node->id, "last")) { */ /* Make it simple */ /* this is probably a hack */ cur_node->id[0] = toupper(cur_node->id[0]); if (!*cur_node->value) { sprintf(txt, "\n%s\n", cur_node->id); addText(txt, 2); } else { if (index(cur_node->value, '\n')) sprintf(txt, "%s: \n", cur_node->id); else sprintf(txt, "%s: ", cur_node->id); addText(txt, (strcmp(cur_node->id, "Plan")) ? 0 : 2); addText(cur_node->value, (strcmp(cur_node->id, "Plan")) ? 1 : 0); addText("\n", 0); } /* } */ if (cur_node->child) cur_node = cur_node->child; else { while (!cur_node->next) { if (!cur_node->parent) break; cur_node = cur_node->parent; } cur_node = cur_node->next; } } } else cur_node = cur_node->next; } } /* Send a request in finger v1 protocol and hope... * Since the output is arbitrary this may fail miserably * If the user doesn't help us, we try to do the best... * * At least we should be compatible to GNU Finger, Win NT Finger * and Sun's Finger. * * Since we only want to know the online status we dont ask for a username. * We can only check for a userlist because we simply search the output * for these names. If we want to have a list of all poeple online, we should * parse the output which is currently not implemented. This also means we * don't have any idle time information. */ int send_request_v1(int fdin, int fdout, char **username) { int retval = 0; char *nl = "\r\n"; int nread; int len; char *scan; char *line; int offset; int i; char inbuf[2048]; /* Send a newline to get all online users */ write(fdin, nl, sizeof(nl)+1); scan = inbuf; len = sizeof(inbuf) - 1; offset = 0; line = inbuf; while ((nread = read(fdout, inbuf+offset, len-offset))) { if (nread == -1) { perror("Reading from remote end"); break; } offset += nread; inbuf[offset] = '\0'; if (debug) printf("inbuf:%s\n", inbuf); while(scan < inbuf + offset) { if ((*scan == '\n') || (*scan == '\r')) { *scan = '\0'; if (line=0) send_request_v1(s, s, usertest); return; } s = make_conn("localhost", NULL); send_request(s, s, cmd); close(s); return; /* only a test yet */ s = make_conn("some.host", NULL); if (s >=0) send_request_v1(s, s, usertest); } void Usage(char *progname) { printf("Usage: %s [-c file] [-h] [-V] [-d] [-t]\n", progname); printf("\t-c file\tuse \"file\" as configuration file\n" "\t-h\tprint this screen and exit\n" "\t-V\tprint version number and exit\n" "\t-d\tdebug modus\n" "\t-t\ttest modus: start in.fingerd locally\n"); } int main( int argc, char *argv[] ) { int flag; char *progname; char *home; /* extraxt base name */ progname = strrchr(argv[0], '/'); if (!progname) progname = argv[0]; else progname++; /* set defaults */ configfile = ".fingerconf"; if ((home = getenv("HOME"))) { configfile = (char *)malloc(strlen(configfile) + strlen(home) + 3); sprintf(configfile, "%s/.fingerconf", home); } /* parse the command line arguments */ while ((flag = getopt(argc, argv, "c:Vdghrt")) != EOF) switch (flag) { case 'c': configfile = strdup(optarg); break; case 'V': printf("%s: %s Version %s\n", progname, PACKAGE, VERSION); exit(0); case 'd': debug = 1; break; case 'g': gnufinger = 1; break; case 't': test = 1; break; case 'r': realnames = 1; break; case 'h': default: Usage(progname); exit(0); break; } gtk_init (&argc, &argv); create_gui(); init(); cf = readFingerconf(configfile); if (cf) { } poll_servers(); gtk_main(); return(0); }