/* Add command (remove old one if necessary) */ static int bind_bind_entry(tcl_bind_list_t *tl, const char *flags, const char *cmd, const char *proc) { tcl_cmd_t *tc; tcl_bind_mask_t *tm; /* Search for matching bind in bind list. */ for (tm = tl->first; tm; tm = tm->next) { if (tm->flags & TBM_DELETED) continue; if (!strcmp(cmd, tm->mask)) break; /* Found it! fall out! */ } /* Create bind if it doesn't exist yet. */ if (!tm) { tm = nmalloc_null(sizeof *tm); tm->mask = nmalloc(strlen(cmd) + 1); strcpy(tm->mask, cmd); /* Link into linked list of binds. */ tm->next = tl->first; tl->first = tm; } /* Proc already defined? If so, replace. */ for (tc = tm->first; tc; tc = tc->next) { if (tc->attributes & TC_DELETED) continue; if (!egg_strcasecmp(tc->func_name, proc)) { tc->flags.match = FR_GLOBAL | FR_CHAN; break_down_flags(flags, &(tc->flags), NULL); return 1; } } /* If this bind list is not stackable, remove the * old entry from this bind. */ if (!(tl->flags & HT_STACKABLE)) { for (tc = tm->first; tc; tc = tc->next) { if (tc->attributes & TC_DELETED) continue; /* NOTE: We assume there's only one not-yet-deleted entry. */ tc->attributes |= TC_DELETED; break; } } tc = nmalloc_null(sizeof *tc); tc->flags.match = FR_GLOBAL | FR_CHAN; break_down_flags(flags, &(tc->flags), NULL); tc->func_name = nmalloc(strlen(proc) + 1); strcpy(tc->func_name, proc); /* Link into linked list of the bind's command list. */ tc->next = tm->first; tm->first = tc; return 1; }
static int tcl_setflags(ClientData cd, Tcl_Interp *irp, int argc, char *argv[]) { FILE *fdb; filedb_entry *fdbe; char *s = NULL, *p, *d; BADARGS(3, 4, " dir ?flags ?channel??"); malloc_strcpy(s, argv[1]); if (s[strlen(s) - 1] == '/') s[strlen(s) - 1] = 0; p = strrchr(s, '/'); if (p == NULL) { p = s; d = ""; } else { *p = 0; p++; d = s; } fdb = filedb_open(d, 0); if (!fdb) { Tcl_AppendResult(irp, "-3", NULL); /* filedb access failed */ my_free(s); return TCL_OK; } filedb_readtop(fdb, NULL); fdbe = filedb_matchfile(fdb, ftell(fdb), p); my_free(s); if (!fdbe) { Tcl_AppendResult(irp, "-1", NULL); /* No such dir */ return TCL_OK; } if (!(fdbe->stat & FILE_DIR)) { Tcl_AppendResult(irp, "-2", NULL); /* Not a dir */ return TCL_OK; } if (argc >= 3) { struct flag_record fr = { FR_GLOBAL | FR_CHAN, 0, 0, 0, 0, 0 }; char f[100]; break_down_flags(argv[2], &fr, NULL); build_flags(f, &fr, NULL); malloc_strcpy(fdbe->flags_req, f); } else my_free(fdbe->flags_req); if (argc == 4) malloc_strcpy(fdbe->chan, argv[3]); filedb_updatefile(fdb, fdbe->pos, fdbe, UPDATE_ALL); free_fdbe(&fdbe); filedb_close(fdb); Tcl_AppendResult(irp, "0", NULL); return TCL_OK; }
static int botfl_unpack(struct userrec *u, struct user_entry *e) { struct flag_record fr = { FR_BOT, 0, 0, 0, 0, 0 }; break_down_flags(e->u.list->extra, &fr, NULL); list_type_kill(e->u.list); e->u.ulong = fr.bot; return 1; }
static int botfl_tcl_set(Tcl_Interp * irp, struct userrec *u, struct user_entry *e, int argc, char **argv) { struct flag_record fr = {FR_BOT, 0, 0, 0, 0, 0}; BADARGS(4, 4, " handle BOTFL flags"); if (u->flags & USER_BOT) { /* silently ignore for users */ break_down_flags(argv[3], &fr, NULL); botfl_set(u, e, (void *) fr.bot); } return TCL_OK; }
/* Outputs a sorted list of files/directories matching the mask, * to idx. */ static void filedb_ls(FILE *fdb, int idx, char *mask, int showall) { int ok = 0, cnt = 0, is = 0; char s1[81], *p = NULL; struct flag_record user = { FR_GLOBAL | FR_CHAN, 0, 0, 0, 0, 0 }; filedb_entry *fdbe = NULL; filelist_t *flist = NULL; flist = filelist_new(); filedb_readtop(fdb, NULL); fdbe = filedb_getfile(fdb, ftell(fdb), GET_FULL); while (fdbe) { ok = 1; if (fdbe->stat & FILE_UNUSED) ok = 0; if (ok && (fdbe->stat & FILE_DIR) && fdbe->flags_req) { /* Check permissions */ struct flag_record req = { FR_GLOBAL | FR_CHAN, 0, 0, 0, 0, 0 }; break_down_flags(fdbe->flags_req, &req, NULL); get_user_flagrec(dcc[idx].user, &user, dcc[idx].u.file->chat->con_chan); if (!flagrec_ok(&req, &user)) { ok = 0; } } if (ok) is = 1; if (ok && !wild_match_file(mask, fdbe->filename)) ok = 0; if (ok && (fdbe->stat & FILE_HIDDEN) && !(showall)) ok = 0; if (ok) { /* Display it! */ if (cnt == 0) { dprintf(idx, FILES_LSHEAD1); dprintf(idx, FILES_LSHEAD2); } filelist_add(flist, fdbe->filename); if (fdbe->stat & FILE_DIR) { char *s2 = NULL, *s3 = NULL; /* Too long? */ if (strlen(fdbe->filename) > 45) { /* Display the filename on its own line. */ s2 = nmalloc(strlen(fdbe->filename) + 3); sprintf(s2, "%s/\n", fdbe->filename); filelist_addout(flist, s2); my_free(s2); } else { s2 = nmalloc(strlen(fdbe->filename) + 2); sprintf(s2, "%s/", fdbe->filename); } /* Note: You have to keep the sprintf and the nmalloc statements * in sync, i.e. always check that you allocate enough * memory. */ if ((fdbe->flags_req) && (user.global &(USER_MASTER | USER_JANITOR))) { s3 = nmalloc(42 + strlen(s2 ? s2 : "") + 6 + strlen(FILES_REQUIRES) + strlen(fdbe->flags_req) + 1 + strlen(fdbe->chan ? fdbe->chan : "") + 1); sprintf(s3, "%-30s <DIR%s> (%s %s%s%s)\n", s2, fdbe->stat & FILE_SHARE ? " SHARE" : "", FILES_REQUIRES, fdbe->flags_req, fdbe->chan ? " " : "", fdbe->chan ? fdbe->chan : ""); } else { s3 = nmalloc(38 + strlen(s2 ? s2 : "")); sprintf(s3, "%-30s <DIR>\n", s2 ? s2 : ""); } if (s2) my_free(s2); filelist_addout(flist, s3); my_free(s3); } else { char s2[41], t[50], *s3 = NULL, *s4; s2[0] = 0; if (showall) { if (fdbe->stat & FILE_SHARE) strcat(s2, " (shr)"); if (fdbe->stat & FILE_HIDDEN) strcat(s2, " (hid)"); } egg_strftime(t, 10, "%d%b%Y", localtime(&fdbe->uploaded)); if (fdbe->size < 1024) sprintf(s1, "%5d", fdbe->size); else sprintf(s1, "%4dk", (int) (fdbe->size / 1024)); if (fdbe->sharelink) strcpy(s1, " "); /* Too long? */ if (strlen(fdbe->filename) > 30) { s3 = nmalloc(strlen(fdbe->filename) + 2); sprintf(s3, "%s\n", fdbe->filename); filelist_addout(flist, s3); my_free(s3); /* Causes filename to be displayed on its own line */ } else malloc_strcpy(s3, fdbe->filename); s4 = nmalloc(69 + strlen(s3 ? s3 : "") + strlen(s1) + strlen(fdbe->uploader) + strlen(t) + strlen(s2)); sprintf(s4, "%-30s %s %-9s (%s) %6d%s\n", s3 ? s3 : "", s1, fdbe->uploader, t, fdbe->gots, s2); if (s3) my_free(s3); filelist_addout(flist, s4); my_free(s4); if (fdbe->sharelink) { s4 = nmalloc(9 + strlen(fdbe->sharelink)); sprintf(s4, " --> %s\n", fdbe->sharelink); filelist_addout(flist, s4); my_free(s4); } } if (fdbe->desc) { p = strchr(fdbe->desc, '\n'); while (p != NULL) { *p = 0; if ((fdbe->desc)[0]) { char *sd; sd = nmalloc(strlen(fdbe->desc) + 5); sprintf(sd, " %s\n", fdbe->desc); filelist_addout(flist, sd); my_free(sd); } strcpy(fdbe->desc, p + 1); p = strchr(fdbe->desc, '\n'); } if ((fdbe->desc)[0]) { char *sd; sd = nmalloc(strlen(fdbe->desc) + 5); sprintf(sd, " %s\n", fdbe->desc); filelist_addout(flist, sd); my_free(sd); } } cnt++; } free_fdbe(&fdbe); fdbe = filedb_getfile(fdb, ftell(fdb), GET_FULL); } if (is == 0) dprintf(idx, FILES_NOFILES); else if (cnt == 0) dprintf(idx, FILES_NOMATCH); else { filelist_sort(flist); filelist_idxshow(flist, idx); dprintf(idx, "--- %d file%s.\n", cnt, cnt != 1 ? "s" : ""); } filelist_free(flist); }
static void filedb_ls(FILE *f, int idx, char *mask, int showall) { filedb fdb; int ok = 0, cnt = 0, is = 0; char s[81], s1[81], *p; struct flag_record user = {FR_GLOBAL | FR_CHAN, 0, 0, 0, 0, 0}; rewind(f); while (!feof(f)) { fread(&fdb, sizeof(filedb), 1, f); if (!feof(f)) { ok = 1; if (fdb.stat & FILE_UNUSED) ok = 0; if (fdb.stat & FILE_DIR) { /* check permissions */ struct flag_record req = {FR_GLOBAL | FR_CHAN, 0, 0, 0, 0, 0}; break_down_flags(fdb.flags_req, &req, NULL); get_user_flagrec(dcc[idx].user, &user, dcc[idx].u.file->chat->con_chan); if (!flagrec_ok(&req, &user)) ok = 0; } if (ok) is = 1; if (!wild_match_file(mask, fdb.filename)) ok = 0; if ((fdb.stat & FILE_HIDDEN) && !(showall)) ok = 0; if (ok) { /* display it! */ if (cnt == 0) { dprintf(idx, FILES_LSHEAD1); dprintf(idx, FILES_LSHEAD2); } if (fdb.stat & FILE_DIR) { char s2[50]; /* too long? */ if (strlen(fdb.filename) > 45) { dprintf(idx, "%s/\n", fdb.filename); s2[0] = 0; /* causes filename to be displayed on its own line */ } else sprintf(s2, "%s/", fdb.filename); if ((fdb.flags_req[0]) && (user.global &(USER_MASTER | USER_JANITOR))) { dprintf(idx, "%-30s <DIR%s> (%s %s%s%s)\n", s2, fdb.stat & FILE_SHARE ? " SHARE" : "", FILES_REQUIRES, fdb.flags_req, fdb.chname[0] ? " " : "", fdb.chname); } else dprintf(idx, "%-30s <DIR>\n", s2); } else { char s2[41]; s2[0] = 0; if (showall) { if (fdb.stat & FILE_SHARE) strcat(s2, " (shr)"); if (fdb.stat & FILE_HIDDEN) strcat(s2, " (hid)"); } strcpy(s, ctime(&fdb.uploaded)); s[10] = 0; s[7] = 0; s[24] = 0; strcpy(s, &s[8]); strcpy(&s[2], &s[4]); strcpy(&s[5], &s[22]); if (fdb.size < 1024) sprintf(s1, "%5d", fdb.size); else sprintf(s1, "%4dk", (int) (fdb.size / 1024)); if (fdb.sharelink[0]) strcpy(s1, " "); /* too long? */ if (strlen(fdb.filename) > 30) { dprintf(idx, "%s\n", fdb.filename); fdb.filename[0] = 0; /* causes filename to be displayed on its own line */ } dprintf(idx, "%-30s %s %-9s (%s) %6d%s\n", fdb.filename, s1, fdb.uploader, s, fdb.gots, s2); if (fdb.sharelink[0]) { dprintf(idx, " --> %s\n", fdb.sharelink); } } if (fdb.desc[0]) { p = strchr(fdb.desc, '\n'); while (p != NULL) { *p = 0; if (fdb.desc[0]) dprintf(idx, " %s\n", fdb.desc); strcpy(fdb.desc, p + 1); p = strchr(fdb.desc, '\n'); } if (fdb.desc[0]) dprintf(idx, " %s\n", fdb.desc); } cnt++; } } } if (is == 0) dprintf(idx, FILES_NOFILES); else if (cnt == 0) dprintf(idx, FILES_NOMATCH); else dprintf(idx, "--- %d file%s.\n", cnt, cnt > 1 ? "s" : ""); }
/* return 1 if i find a '.files' and convert it */ static int convert_old_db(char *path, char *newfiledb) { FILE *f, *g; char s[256], *fn, *nick, *tm, *s1 = s; filedb fdb; int in_file = 0, i; long where; struct stat st; sprintf(s, "%s/.files", path); f = fopen(s, "r"); if (f == NULL) return 0; g = fopen(newfiledb, "w+b"); if (g == NULL) { putlog(LOG_MISC, "(!) Can't create filedb in %s", newfiledb); fclose(f); return 0; } putlog(LOG_FILES, "*", FILES_CONVERT, path); where = ftell(g); /* scan contents of .files and painstakingly create .filedb entries */ while (!feof(f)) { fgets(s, 120, f); if (s[strlen(s) - 1] == '\n') s[strlen(s) - 1] = 0; if (!feof(f)) { fn = newsplit(&s1); rmspace(fn); if ((fn[0]) && (fn[0] != ';') && (fn[0] != '#')) { /* not comment */ if (fn[0] == '-') { /* adjust comment for current file */ if (in_file) { rmspace(s); if (strlen(s) + strlen(fdb.desc) <= 600) { strcat(fdb.desc, "\n"); strcat(fdb.desc, s); fseek(g, where, SEEK_SET); fwrite(&fdb, sizeof(filedb), 1, g); } } } else { in_file = 1; where = ftell(g); nick = newsplit(&s1); rmspace(nick); tm = newsplit(&s1); rmspace(tm); rmspace(s1); i = strlen(fn) - 1; if (fn[i] == '/') fn[i] = 0; fdb.version = FILEVERSION; fdb.stat = 0; fdb.desc[0] = 0; fdb.chname[0] = 0; fdb.flags_req[0] = 0; strcpy(fdb.filename, fn); strcpy(fdb.uploader, nick); fdb.gots = atoi(s1); fdb.sharelink[0] = 0; fdb.uploaded = atoi(tm); sprintf(s, "%s/%s", path, fn); if (stat(s, &st) == 0) { /* file is okay */ if (S_ISDIR(st.st_mode)) { fdb.stat |= FILE_DIR; if (nick[0] == '+') { char x[100]; /* only do global flags, it's an old one */ struct flag_record fr = {FR_GLOBAL, 0, 0, 0, 0, 0}; break_down_flags(nick + 1, &fr, NULL); build_flags(x, &fr, NULL); /* we only want valid flags */ strncpy(fdb.flags_req, x, 21); fdb.flags_req[21] = 0; } } fdb.size = st.st_size; fwrite(&fdb, sizeof(filedb), 1, g); } else in_file = 0; /* skip */ } } } } fseek(g, 0, SEEK_END); fclose(g); fclose(f); return 1; }
void showhelp(int idx, struct flag_record *flags, const char *string) { struct flag_record fr = {FR_GLOBAL | FR_CHAN, 0, 0, 0 }; size_t help_siz = strlen(string) + 1000 + 1; char *helpstr = (char *) my_calloc(1, help_siz); char tmp[2] = "", flagstr[10] = ""; bool ok = 1; while (string && string[0]) { if (*string == '%') { if (!strncmp(string + 1, "{+", 2)) { while (*string && *string != '+') { string++; } flagstr[0] = 0; while (*string && *string != '}') { simple_snprintf(tmp, sizeof(tmp), "%c", *string); strlcat(flagstr, tmp, sizeof(flagstr)); string++; } string++; break_down_flags(flagstr, &fr, NULL); if (flagrec_ok(&fr, flags)) { ok = 1; while (*string && *string != '%') { simple_snprintf(tmp, sizeof(tmp), "%c", *string); strlcat(helpstr, tmp, help_siz); string++; } if (!strncmp(string + 1, "{-", 2)) { ok = 1; while (*string && *string != '}') { string++; } string++; } } else { ok = 0; } } else if (!strncmp(string + 1, "{-", 2)) { ok = 1; while (*string && *string != '}') { string++; } string++; } else if (*string == '{') { while (*string && *string != '}') { string++; } } else if (*(string + 1) == 'd') { string += 2; if (dcc[idx].u.chat->channel >= 0) strlcat(helpstr, settings.dcc_prefix, help_siz); } else if (*(string + 1) == '%') { string += 2; strlcat(helpstr, "%", help_siz); } else { if (ok) { simple_snprintf(tmp, sizeof(tmp), "%c", *string); strlcat(helpstr, tmp, help_siz); } string++; } } else { if (ok) { simple_snprintf(tmp, sizeof(tmp), "%c", *string); strlcat(helpstr, tmp, help_siz); } string++; } } helpstr[strlen(helpstr)] = 0; if (helpstr[0]) dumplots(idx, "", helpstr); free(helpstr); }
/* Convert '.files' db to newest db. Returns 1 if a valid file is * found and could be converted, 0 in all other cases. * * '.files' is a text file which contains file records built up in the * following way: * '<filename> <nick> <tm> <gots>\n' * '- <comment>\n' * '- <comment>\n' * ... */ static int convert_old_files(char *path, char *newfiledb) { FILE *f, *fdb; char *s, *fn, *nick, *tm, *s1; filedb_entry *fdbe = NULL; int in_file = 0, i; struct stat st; s = nmalloc(strlen(path) + 8); sprintf(s, "%s/.files", path); f = fopen(s, "r"); my_free(s); if (f == NULL) return 0; fdb = fopen(newfiledb, "w+b"); if (!fdb) { putlog(LOG_MISC, "(!) Can't create filedb in %s", newfiledb); fclose(f); return 0; } lockfile(fdb); lockfile(f); filedb_initdb(fdb); putlog(LOG_FILES, "*", FILES_CONVERT, path); /* Scan contents of .files and painstakingly create .filedb entries */ while (!feof(f)) { s = nmalloc(121); s1 = s; fgets(s, 120, f); if (s[strlen(s) - 1] == '\n') s[strlen(s) - 1] = 0; if (!feof(f)) { fn = newsplit(&s1); rmspace(fn); if ((fn[0]) && (fn[0] != ';') && (fn[0] != '#')) { /* Not comment */ if (fn[0] == '-') { /* Adjust comment for current file */ if (in_file && fdbe) { rmspace(s); if (fdbe->desc) { fdbe->desc = nrealloc(fdbe->desc, strlen(fdbe->desc) + strlen(s) + 2); strcat(fdbe->desc, "\n"); } else fdbe->desc = nmalloc(strlen(s) + 2); strcat(fdbe->desc, s); } } else { if (fdbe) { /* File pending. Write to DB */ filedb_addfile(fdb, fdbe); free_fdbe(&fdbe); } fdbe = malloc_fdbe(); in_file = 1; nick = newsplit(&s1); rmspace(nick); tm = newsplit(&s1); rmspace(tm); rmspace(s1); i = strlen(fn) - 1; if (fn[i] == '/') fn[i] = 0; malloc_strcpy(fdbe->filename, fn); malloc_strcpy(fdbe->uploader, nick); fdbe->gots = atoi(s1); fdbe->uploaded = atoi(tm); sprintf(s, "%s/%s", path, fn); if (stat(s, &st) == 0) { /* File is okay */ if (S_ISDIR(st.st_mode)) { fdbe->stat |= FILE_DIR; if (nick[0] == '+') { char x[100]; /* Only do global flags, it's an old one */ struct flag_record fr = { FR_GLOBAL, 0, 0, 0, 0, 0 }; break_down_flags(nick + 1, &fr, NULL); build_flags(x, &fr, NULL); /* We only want valid flags */ malloc_strcpy_nocheck(fdbe->flags_req, x); } } fdbe->size = st.st_size; } else in_file = 0; /* skip */ } } } my_free(s); } if (fdbe) { /* File pending. Write to DB */ filedb_addfile(fdb, fdbe); free_fdbe(&fdbe); } fseek(fdb, 0L, SEEK_END); unlockfile(f); unlockfile(fdb); fclose(fdb); fclose(f); return 1; }
static int tcl_mkdir(ClientData cd, Tcl_Interp *irp, int argc, char *argv[]) { FILE *fdb; filedb_entry *fdbe; char *s = NULL, *t, *d, *p; struct flag_record fr = { FR_GLOBAL | FR_CHAN, 0, 0, 0, 0, 0 }; BADARGS(2, 4, " dir ?required-flags ?channel??"); malloc_strcpy(s, argv[1]); if (s[strlen(s) - 1] == '/') s[strlen(s) - 1] = 0; p = strrchr(s, '/'); if (p == NULL) { p = s; d = ""; } else { *p = 0; p++; d = s; } fdb = filedb_open(d, 0); if (!fdb) { Tcl_AppendResult(irp, "-3", NULL); /* filedb access failed */ my_free(s); return TCL_OK; } filedb_readtop(fdb, NULL); fdbe = filedb_matchfile(fdb, ftell(fdb), p); if (!fdbe) { t = nmalloc(strlen(dccdir) + strlen(d) + strlen(p) + 2); sprintf(t, "%s%s/%s", dccdir, d, p); if (mkdir(t, 0755) != 0) { Tcl_AppendResult(irp, "1", NULL); my_free(t); my_free(s); filedb_close(fdb); return TCL_OK; } fdbe = malloc_fdbe(); fdbe->stat = FILE_DIR; malloc_strcpy(fdbe->filename, argv[1]); fdbe->uploaded = now; } else if (!(fdbe->stat & FILE_DIR)) { Tcl_AppendResult(irp, "2", NULL); free_fdbe(&fdbe); my_free(s); filedb_close(fdb); return TCL_OK; } if (argc >= 3) { char f[100]; break_down_flags(argv[2], &fr, NULL); build_flags(f, &fr, NULL); malloc_strcpy(fdbe->flags_req, f); } else if (fdbe->flags_req) { my_free(fdbe->flags_req); } if (argc == 4) { malloc_strcpy(fdbe->chan, argv[3]); } else if (fdbe->chan) my_free(fdbe->chan); if (!fdbe->pos) fdbe->pos = POS_NEW; filedb_updatefile(fdb, fdbe->pos, fdbe, UPDATE_ALL); filedb_close(fdb); free_fdbe(&fdbe); Tcl_AppendResult(irp, "0", NULL); return TCL_OK; }