/* ** Safe string copy. ** ** If the source string is longer than will fit in the output buffer, ** then only copy as many as will fit, and then NUL terminate the destination ** string. ** ** Returns the number of characters in the output buffer (not including ** the terminating NUL), or -1 if the buffer is of zero size. */ int s_strcpy(char *dst, int dstsize, const char *src) { int srclen; if (dst == NULL) s_abort(); if (dstsize-- < 1) { s_abort(); /* Temp, just to find all bad uses of it */ return -1; } if (src == NULL) { *dst = '\0'; return 0; } srclen = strlen(src); if (srclen > dstsize) srclen = dstsize; if (srclen > 0) memcpy(dst, src, srclen); dst[srclen] = '\0'; return srclen; }
void a_free(void *p) { AAHDR *ap; if (p == NULL) return; if (aa_debug) { ap = (AAHDR *) p; --ap; if (!aahdr_valid(ap)) { syslog(LOG_ERR, "a_free: INVALID pointer"); s_abort(); } pthread_mutex_lock(&aa_mtx); if (ap->prev) ap->prev->next = ap->next; if (ap->next) ap->next->prev = ap->prev; if (top == ap) top = ap->next; pthread_mutex_unlock(&aa_mtx); } free(p); }
void s_rnge(char *varn, int32 offset, char *procn, int32 line) { register int32 i; int32 len; len=varlen(procn); fprintf(stderr, "Subscript out of range on file line %d, procedure ", line); /*for(i = 0 ; i < 2 && (*procn!='_' && *(procn+1) != '\0'); ++i)*/ for(i = 0 ; i < len ; ++i) putc(*procn++, stderr); fprintf(stderr, ".\nAttempt to access the %d-th element of variable ", offset+1); #ifdef sgi for(i = 0; i < 32 && *varn!=' '; ++i) putc(*varn++, stderr); #else for(i = 0 ; i < 6 && *varn!=' ' ; ++i) putc(*varn++, stderr); #endif fprintf(stderr, ".\n"); s_abort(99); }
static inline void * safe_malloc(size_t size, const char *fun, const char *what) { int rsize; void *p; AAHDR *ap; unsigned char *cp; if (aa_debug) rsize = size + sizeof(AAHDR) + 1; else rsize = size; p = malloc(rsize); if (p == NULL) { syslog(LOG_ERR, "%s: %s: malloc(%lu - real=%lu): %m", fun ? fun : "<unknown function>", what ? what : "<unknown object>", (unsigned long) size, (unsigned long) rsize); s_abort(); } if (aa_debug) { ap = (AAHDR *) p; pthread_mutex_lock(&aa_mtx); ap->prev = NULL; if (top) top->prev = ap; ap->next = top; top = ap; ap->size = size; strlcpy(ap->fun, fun, sizeof(ap->fun)); strlcpy(ap->what, what, sizeof(ap->what)); ap->magic = AAHDR_MAGIC_1; cp = (unsigned char *) (ap+1); cp[size] = AAHDR_MAGIC_2; p = (void *) cp; pthread_mutex_unlock(&aa_mtx); } return p; }
/* ** Safe string limited concatenation. ** ** If the source string is longer than will fit in the output buffer, ** then only copy as many as will fit, and then NUL terminate the destination ** string. ** ** Returns the number of characters in the output buffer (not including ** the terminating NUL), or -1 if the buffer is of zero size. */ int s_strncat(char *dst, int dstsize, const char *src, int maxcopy) { int srclen; int dstlen; if (dst == NULL) s_abort(); if (dstsize-- < 1) { s_abort(); /* Temp, just to find all bad uses of it */ return -1; } dstlen = strlen(dst); if (src == NULL) return dstlen; srclen = strlen(src); if (srclen > maxcopy) srclen = maxcopy; if (srclen+dstlen > dstsize) srclen = dstsize-dstlen; if (srclen < 0) { syslog(LOG_ERR, "s_strncat(..., %d, ..., %d): buffer overflow", dstsize, maxcopy); return dstlen; } if (srclen > 0) memcpy(dst+dstlen, src, srclen); dst[dstlen+srclen] = '\0'; return srclen+dstlen; }
void * a_realloc(void *oldp, size_t nsize, const char *what) { void *p; if (!oldp) return safe_malloc(nsize, "a_realloc", what); if (aa_debug) { AAHDR *ap; ap = (AAHDR *) oldp; --ap; if (!aahdr_valid(ap)) { syslog(LOG_ERR, "a_realloc: INVALID pointer"); s_abort(); } p = safe_malloc(nsize, "a_realloc", what); memcpy(p, oldp, ap->size > nsize ? nsize : ap->size); a_free(oldp); return p; } p = (void *) realloc(oldp, nsize); if (p == NULL) { syslog(LOG_ERR, "a_realloc: %s: realloc(...,%lu): %m", what ? what : "<unknown object>", (unsigned long) nsize); s_abort(); } return p; }
int s_vsprintf(char *buf, int size, const char *format, va_list ap) { int len; #ifdef HAVE_VSNPRINTF len = __vsnprintf(buf, size, format, ap); #else len = vsprintf(buf, format, ap); if (len > size) s_abort(); #endif return len; }
void s_srng(char *varn, int32 lower, int32 upper, char *procn, int32 line) { register int32 i; extern void s_abort(int32); fprintf(stderr, "Substring bound(s) out of range on file line %d, procedure ", line); for(i = 0 ; i < 8 && *procn!='_' ; ++i) putc(*procn++, stderr); fprintf(stderr, ".\nAttempt to access the %d-th through the %d-th characters of variable ", lower, upper); for(i = 0 ; i < 6 && *varn!=' ' ; ++i) putc(*varn++, stderr); fprintf(stderr, ".\n"); s_abort(99); }
int server_run_one(SERVER *sp, int client_fd, int nofork) { CLIENT *cp; pthread_t tid; #ifndef HAVE_THREADS pid_t pid; int status; #endif int ecode; socklen_t slen; pthread_mutex_lock(&sp->clients_mtx); sp->clients_cur++; if (debug) fprintf(stderr, "server_run_one: Number of clients is now: %d\n", sp->clients_cur); pthread_mutex_unlock(&sp->clients_mtx); if (debug) fprintf(stderr, "server_run_one(..., %d, %d): Start\n", client_fd, nofork); A_NEW(cp); cp->fd = client_fd; cp->sp = sp; slen = sizeof(cp->rsin); if (getpeername(cp->fd, (struct sockaddr *) &cp->rsin, &slen) < 0) { syslog(LOG_ERR, "getpeername(%d): %m", cp->fd); if (debug) fprintf(stderr, "server_run_one(...): End: FAILURE\n"); return EXIT_FAILURE; } slen = sizeof(cp->lsin); if (getsockname(cp->fd, (struct sockaddr *) &cp->lsin, &slen) < 0) { syslog(LOG_ERR, "getsockname(%d): %m", cp->fd); if (debug) fprintf(stderr, "server_run_one(...): End: FAILURE\n"); return EXIT_FAILURE; } if (nofork) { (void) client_thread(cp); if (debug) fprintf(stderr, "server_run_one(...): End: OK\n"); return EXIT_SUCCESS; } else { #ifdef HAVE_THREADS ecode = pthread_create(&tid, &sp->ca_detached, client_thread, (void *) cp); if (ecode) { syslog(LOG_ERR, "pthread_create(client_thread) failed: %s", strerror(ecode)); if (debug) fprintf(stderr, "server_run_one(...): End: FAILURE\n"); return EXIT_FAILURE; } #else /* Try to reap the status of as many subprocesses as possible */ /* ** XXX: This will break if we are using multiple ** SERVER's in a single process and aren't using ** threads. */ while (sp->clients_cur > 0 && (pid = waitpid((pid_t) -1, &status, WNOHANG)) > 0) { if (WIFEXITED(status) || WIFSIGNALED(status)) { sp->clients_cur--; } } if (sp->clients_max > 0) { /* Wait for atleast one slot to be available */ while (sp->clients_cur >= sp->clients_max && (pid = waitpid((pid_t) -1, &status, 0)) > 0) { if (WIFEXITED(status) || WIFSIGNALED(status)) { sp->clients_cur--; } } } while ((status = fork()) < 0 && errno == EAGAIN) { /* Fork failed - too many processes */ sleep(1); pid = waitpid((pid_t) -1, &status, (sp->clients_cur > 0) ? 0 : WNOHANG); if (pid > 0 && (WIFEXITED(status) || WIFSIGNALED(status))) { sp->clients_cur--; } } if (status < 0) { syslog(LOG_ERR, "fork() failed: %m"); s_abort(); } if (status == 0) { /* In child process */ (void) client_thread(cp); _exit(EXIT_SUCCESS); } sp->clients_cur++; s_close(cp->fd); a_free(cp); #endif } if (debug) fprintf(stderr, "server_run_one(...): End: OK\n"); return EXIT_SUCCESS; }