/****************************************************************************** * This file is part of a software distribution, which is furnished under the * * terms of a license. Use of this software by any means is subject to this * * license and signifies the acceptance of the licensing terms stated * * therein. Please see the file LICENSE in the top-level directory of this * * software distribution for detailed copyright disclaimers and licensing * * terms. * ****************************************************************************** * Copryight (c) by Andreas S. Wetzel - All rights reserved. * ******************************************************************************/ /* $Id: subr.c,v 1.5 2002/06/23 23:29:37 mickey Exp $ */ #include #include #include #include #if HAVE_SYS_SELECT_H #include #endif /*** Externals ***/ extern int in_chat_window; extern ED *ed; extern VP vp; extern VCONN sconn; extern VTCAP vtcap; extern VTIMER vtimer; /* * void history_init(void); * * Initialize command history buffer. */ void history_init(void) { if(vp.history_lines > 0) { ++vp.history_lines; if((vp.history = (u_char **)calloc(vp.history_lines, sizeof(u_char *))) == NULL) { /*** FAILURE: Disable command history ***/ vp.history_lines = 0; } } else { vp.history = NULL; vp.history_lines = 0; } vp.history_start = 0; vp.history_current = 0; vp.history_next = 0; vp.history_cycle = 0; } /* * void history_exit(void); * * Free all buffers used for the command history */ void history_exit(void) { int i; u_char *ptr; if(vp.history != NULL) { for(i = 0; i < vp.history_lines; i++) { ptr = vp.history[i]; if(ptr != NULL) { free(ptr); } } free(vp.history); } } /* * void history_save(u_char *text); * * Store the commandline pointed to by at the * next buffer position in the command history. */ void history_save(u_char *text) { size_t size = strlen(text) + 1; u_char *newbuf; /* * If command history is disabled, there is * nothing left to to in here. */ if(!vp.history_lines) return; /* * Allocate a new buffer to store the text into. * If this fails the history will be unmodified. */ if((newbuf = (u_char *)calloc(1, size)) == NULL) { return; } /* * If the buffer to which vp.history_next points * was already used then free the buffer at first. */ if(vp.history[vp.history_next] != NULL) { free(vp.history[vp.history_next]); } /* * Store the text into the newly allocated buffer * and store address of new buffer in the history vector */ strncpy(newbuf, text, size); vp.history[vp.history_next++] = newbuf; /* * Set the index to the next buffer */ if(vp.history_next >= vp.history_lines) { /* * History buffer has filled up, enable cycling */ vp.history_cycle = 1; vp.history_next = 0; } vp.history_current = vp.history_next; /* * If the cycle history flag is set, then * move the starting position up one place. */ if(vp.history_cycle) { if(++vp.history_start >= vp.history_lines) vp.history_start = 0; } } /* * void vsleep(u_long sec, u_long usec); * * Suspend program execution for seconds * plus microseconds. */ void vsleep(u_long sec, u_long usec) { int ret; struct timeval tm; struct timeval start; struct timeval end; struct timeval elapsed; struct timeval remain; tm.tv_sec = sec; tm.tv_usec = usec; restart: timestamp(&start); ret = select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tm); timestamp(&end); if(ret == -1 && errno != EINTR) return; BCOPY(diff_t(&start, &end), &elapsed, sizeof(struct timeval)); BCOPY(diff_t(&elapsed, &tm), &remain, sizeof(struct timeval)); if(remain.tv_sec >= 0 && remain.tv_usec >= 0) { tm = remain; goto restart; } } /* * void str_lower(char *s); * * Convert the string pointed to by into lowercase */ void str_lower(char *s) { while(*s != '\0') { *s = (*s >= 'A' && *s <= 'Z') ? *s + 0x20 : *s; ++s; } } /* * char *pr_timer(time_t tim); * * Return a pointer to a sring representing the date/time from */ char *pr_timer(time_t tim) { static char prt[30]; strftime((char *)&prt, 30, "%a %R", localtime(&tim)); return(prt); } /* * void pbc_enable(void); * * Enable put-back-cursor timer event */ void pbc_enable(void) { vtimer.pbc_timer = vp.cursordelay; vp.vclock_pbc_enable = 0xff; } /* * void pbc_disable(void); * * Disable put-back-cursor timer event */ void pbc_disable(void) { vtimer.pbc_timer = vp.vclock_pbc_enable = 0; } /* * void line_update(void); * * Clear and redraw the current input line pointed to by * the global ED *ed pointer. */ void line_update(void) { char *cptr; char *endp; /* * Prevent us from being interrupted */ vlock(LOCK, (V_IO | V_TIMER | V_WINCH)); /* * Print the prompt (if any) */ mv(1, vtcap.rows); in_chat_window = 0; if(ed->prompt) cprintf(input, "%s", ed->prompt); /* * Redraw input line */ if(!(ed->flags & ED_NO_ECHO)) { endp = (ed->margin + (vtcap.cols - ed->offset)); for(cptr = ed->margin; cptr < endp && *cptr != '\0'; cptr++) putchar(*cptr); if(cptr < endp) { if(vtcap.clear2eol) tputs(vtcap.clear2eol, 1, (void *)outc); else if(vtcap.clear2eod) tputs(vtcap.clear2eod, 1, (void *)outc); } if(ED_SCRPOS != ((endp - ed->margin) + ed->offset)) mv(ED_SCRPOS, vtcap.rows); } else { /* * Clear the line remaining right of the prompt */ if(vtcap.clear2eol) tputs(vtcap.clear2eol, 1, (void *)outc); else if(vtcap.clear2eod) tputs(vtcap.clear2eod, 1, (void *)outc); } vlock(UNLOCK, (V_IO | V_TIMER | V_WINCH)); } /* * void nop(void) * * Simply do nothing - this is used for unknown keys in input_line(); */ void nop(void) { /* PENG! */ } /* * int escape_str(u_char *str, u_char *buf, size_t len); * * Read input from the string pointed to by escaping * all occurances of a CSI or space character with a CSI * character. At most bytes of output will be written * to the buffer pointed to by . */ int escape_str(u_char *str, u_char *buf, size_t len) { int cnt = 0; if(str == NULL || buf == NULL) return(0); for(;;) { if(*str == '\0') { *buf = '\0'; return(cnt); } else if(*str == CSI) { if(cnt < (len -1)) { *buf++ = CSI; ++cnt; } else { *buf = '\0'; return(cnt); } if(cnt < (len -1)) { *buf++ = CSI; ++cnt; } else { *buf = '\0'; return(cnt); } ++str; } else if(*str == ' ') { if(cnt < (len -1)) { *buf++ = CSI; ++cnt; } else { *buf = '\0'; return(cnt); } if(cnt < (len - 1)) { *buf++ = ' '; ++cnt; } else { *buf = '\0'; return(cnt); } ++str; } else { if(cnt < (len - 1)) { *buf++ = *str++; ++cnt; } else { *buf = '\0'; return(cnt); } } } } /* * int netmask_bits(struct in_addr netmask); * * Get the number of mask bits in the specified netmask */ int netmask_bits(struct in_addr netmask) { u_int32_t mask = ntohl(netmask.s_addr); int bits = 0; int flg = 0; int i; for(i = 0; i < (CHAR_BIT * sizeof(u_int32_t)); i++) { if(mask & 0x00000001) { flg = 1; ++bits; } else { if(flg) return(-1); } mask = (mask >> 1); } return(bits); } /* * void netmask_create(int bits, struct in_addr *netmask); * * Create a netmask with the number of specified, and store * it into the in_addr struct pointed to by . */ void netmask_create(int bits, struct in_addr *netmask) { netmask->s_addr = htonl(~0 << ((CHAR_BIT * sizeof(u_int32_t)) - bits)); } /* * int permission_mask(char *privname, u_int32_t *maskptr); * * Store the binary representation for the permission named * by the parameter into the permission mask pointed * to by the parameter. Returns 0 if successfull or * -1 in case the specified permission name was invalid. */ int permission_mask(char *permname, u_int32_t *maskptr) { str_lower(permname); if(!strcmp(permname, "add")) *maskptr = AUTH_ADD; else if(!strcmp(permname, "delete")) *maskptr = AUTH_DELETE; else if(!strcmp(permname, "chacc")) *maskptr = AUTH_CHACCPERM; else if(!strcmp(permname, "chmod")) *maskptr = AUTH_CHMODPERM; else if(!strcmp(permname, "kill")) *maskptr = AUTH_KILL; else if(!strcmp(permname, "bcast")) *maskptr = AUTH_BROADCAST; else if(!strcmp(permname, "acl")) *maskptr = AUTH_ACL; else if(!strcmp(permname, "query")) *maskptr = AUTH_QUERY; else if(!strcmp(permname, "sopt")) *maskptr = AUTH_SOPT; else if(!strcmp(permname, "fix")) *maskptr = AUTH_FIXCHAN; else if(!strcmp(permname, "status")) *maskptr = AUTH_STATUS; else if(!strcmp(permname, "exclude")) *maskptr = AUTH_EXCLUDE; else return(-1); return(0); } /* * int clopt_mask(char *optname, u_int32_t *maskptr); * * Store the binary representation for the client option named * by the parameter into the client option mask pointed * to by the parameter. Returns 0 if successfull or * -1 in case the specified client option name was invalid. */ int clopt_mask(char *optname, u_int32_t *maskptr) { str_lower(optname); if(!strcmp(optname, "wakeup")) *maskptr = CL_OPT_WAKEUP; else if(!strcmp(optname, "sgnmsg")) *maskptr = CL_OPT_SGNMSG; else if(!strcmp(optname, "prvecho")) *maskptr = CL_OPT_PRVECHO; else return(-1); return(0); } /* * int svopt_mask(char *optname, u_int32_t *maskptr); * * Store the binary representation for the server option named * by the parameter into the server option mask pointed * to by the parameter. Returns 0 if successfull or * -1 in case the specified server option name was invalid. */ int svopt_mask(char *optname, u_int32_t *maskptr) { str_lower(optname); if(!strcmp(optname, "show_ip")) *maskptr = SV_OPT_SHOW_IP; else if(!strcmp(optname, "mail_inv")) *maskptr = SV_OPT_MAIL_INV; else if(!strcmp(optname, "reg_only")) *maskptr = SV_OPT_REG_ONLY; else if(!strcmp(optname, "flood_guard")) *maskptr = SV_OPT_FLOOD_GUARD; else return(-1); return(0); }