/***************************************************************************** * * File ..................: bbs/file.c * Purpose ...............: All the file functions. * Last modification date : 28-Jun-2001 * ***************************************************************************** * Copyright (C) 1997-2001 * * Michiel Broek FIDO: 2:280/2802 * Beekmansbos 10 * 1971 BV IJmuiden * the Netherlands * * This file is part of MBSE BBS. * * This BBS 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, or (at your option) any * later version. * * MBSE BBS 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 MBSE BBS; see the file COPYING. If not, write to the Free * Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. *****************************************************************************/ #include "../lib/libs.h" #include "../lib/mbse.h" #include "../lib/structs.h" #include "../lib/records.h" #include "../lib/common.h" #include "../lib/clcomm.h" #include "filesub.h" #include "file.h" #include "funcs.h" #include "funcs4.h" #include "language.h" #include "misc.h" #include "timeout.h" #include "exitinfo.h" #include "change.h" extern long arecno; /* File area number in xxxScan() functions */ int Strlen = 0; int FileRecno = 0; /* * Show filelist from current area, called from the menu. */ void File_List() { FILE *pFile; int FileCount = 0; unsigned FileBytes = 0; _Tag T; iLineCount = 0; WhosDoingWhat(FILELIST); Syslog('+', "Listing File Area # %d", iAreaNumber); if(Access(exitinfo.Security, area.LTSec) == FALSE) { colour(14, 0); /* You don't have enough security to list this area */ printf("\n%s\n", (char *) Language(236)); Pause(); return; } InitTag(); if ((pFile = OpenFileBase(iAreaNumber, FALSE)) == NULL) return; clear(); Header(); if (iLC(2) == 1) { fclose(pFile); return; } while (fread(&file, sizeof(file), 1, pFile) == 1) { T.Area = iAreaNumber; T.Active = FALSE; T.Cost = file.Cost; T.Size = file.Size; sprintf(T.File, "%s", file.Name); SetTag(T); if (ShowOneFile() == 1) { fclose(pFile); return; } if(file.Deleted) /* D E L E T E D */ /* Uploaded by: */ printf("%-15s %s [%ld] %s%s\n", file.Name, (char *) Language(239), file.TimesDL, (char *) Language(238), file.Uploader); if(file.Missing) /* M I S S I N G */ /* Uploaded by: */ printf("%-15s %s [%ld] %s%s\n", file.Name, (char *) Language(240), file.TimesDL, (char *) Language(238), file.Uploader); FileCount++; /* Increase File Counter by 1 */ FileBytes += file.Size; /* Increase File Byte Count */ } Mark(); colour(11,0); /* Total Files: */ printf("\n%s%d / %d bytes\n\n", (char *) Language(242), FileCount, FileBytes); iLineCount = 0; fclose(pFile); Pause(); } /* * Download files already tagged, called from the menu. */ void Download(void) { FILE *tf, *fp, *fd; int i, err, Count = 0; int OldArea; char *symTo, *symFrom; char *temp; long Size = 0, CostSize = 0; time_t ElapstimeStart, ElapstimeFin, iTime; long iTransfer = 0; Enter(2); OldArea = iAreaNumber; WhosDoingWhat(DOWNLOAD); unlink("./tag/filedesc.txt"); if ((tf = fopen("taglist", "r+")) == NULL) { /* No files marked for download. */ pout(12, 0, (char *) Language(258)); Enter(2); Pause(); return; } symTo = calloc(PATH_MAX, sizeof(char)); symFrom = calloc(PATH_MAX, sizeof(char)); colour(13, 0); /* Checking your marked downloads, please wait... */ printf("%s\n\n", (char *) Language(255)); ReadExitinfo(); while (fread(&Tag, sizeof(Tag), 1, tf) == 1) { if (Tag.Active) { SetFileArea(Tag.Area); /* * Check password for selected file */ memset(&file, 0, sizeof(file)); if ((fp = OpenFileBase(Tag.Area, FALSE)) != NULL) { while (fread(&file, sizeof(file), 1, fp) == 1) { if (strcmp(file.Name, Tag.File) == 0) break; } fclose(fp); } if (strcmp(file.Name, Tag.File) == 0) { Syslog('b', "Found file %s in area %d", file.Name, Tag.Area); if ((file.Deleted) || (file.Missing)) { pout(CFG.HiliteF, CFG.HiliteB, (char *) Language(248)); /* Sorry that file is unavailable for download */ printf("%s (%s)\n", (char *) Language(248), file.Name); Tag.Active = FALSE; } } if (Tag.Active) { /* * Create/Append file description list while we're * busy checking. If the users doesn't want it we * can unlink it aftwerwards. We also insert CR * characters to please the poor DOS (M$oft) users. */ sprintf(symTo, "./tag/filedesc.%ld", exitinfo.Downloads % 256); if ((fd = fopen(symTo, "a")) != NULL) { fprintf(fd, "%s\r\n", file.Name); for (i = 0; i < 25; i++) { if (strlen(file.Desc[i]) > 1) fprintf(fd, " %s\r\n", file.Desc[i]); } fprintf(fd, "\r\n"); fclose(fd); } /* * Make a symlink to the users download dir. * First unlink, in case there was an old one. */ chdir("./tag"); unlink(Tag.File); sprintf(symFrom, "%s", Tag.File); sprintf(symTo, "%s/%s", sAreaPath, Tag.File); if (symlink(symTo, symFrom)) { WriteError("$Can't create symlink %s %s %d", symTo, symFrom, errno); Tag.Active = FALSE; } Home(); } if (!Tag.Active) { /* * Update the download active flag in the * taglist */ fseek(tf, - sizeof(Tag), SEEK_CUR); fwrite(&Tag, sizeof(Tag), 1, tf); } else { /* * Count file and sizes. */ Count++; Size += file.Size; if ((!file.Free) && (!area.Free)) CostSize += file.Size; } } } /* * If anything left to download... */ if (!Count) { fclose(tf); SetFileArea(OldArea); unlink("taglist"); /* No files marked for download */ pout(12, 0, (char *) Language(258)); Enter(2); Pause(); free(symTo); free(symFrom); return; } colour(14, 0); /* You have */ /* files( */ /* bytes) marked for download */ printf("%s %d %s%ld %s\n\n", (char *) Language(249), Count, (char *) Language(280), Size, (char *) Language(281)); /* * If user has no default protocol, make sure he has one. */ if (!ForceProtocol()) { SetFileArea(OldArea); free(symTo); free(symFrom); return; } if (!CheckBytesAvailable(CostSize)) { SetFileArea(OldArea); free(symTo); free(symFrom); return; } Pause(); clear(); /* File(s) : */ pout(14, 0, (char *) Language(349)); printf("%d\n", Count); /* Size : */ pout( 3, 0, (char *) Language(350)); printf("%lu\n", Size); /* Protocol : */ pout( 3, 0, (char *) Language(351)); printf("%s\n", sProtName); Syslog('+', "Download tagged files start"); printf("%s\n\n", sProtAdvice); fflush(stdout); fflush(stdin); /* HERE WE SHOULD MAKE A DIFFERENCE BETWEEN BATCHING AND NON * BATCHING PROTOCOLS. */ /* * Wait a while before download */ sleep(2); time(&ElapstimeStart); temp = calloc(PATH_MAX, sizeof(char)); sprintf(temp, "%s ./tag/*", sProtDn); Syslog('+', "Download command %s", temp); /* * Transfer the files. Set the Client/Server time at the maximum * time the user has plus 10 minutes. The overall timer 10 seconds * less. Not a nice but working solution. */ alarm_set(((exitinfo.iTimeLeft + 10) * 60) - 10); Altime((exitinfo.iTimeLeft + 10) * 60); if ((err = system(temp)) != 0) { /* * Only log the error, we might have sent some files * instead of nothing. */ perror(""); colour(CFG.HiliteF, CFG.HiliteB); WriteError("Download error %d, prot: %s", err, sProtDn); } Altime(0); alarm_off(); alarm_on(); fflush(stdout); fflush(stdin); free(temp); time(&ElapstimeFin); /* * Get time from Before Download and After Download to get * download time, if the time is zero, it will be one. */ iTime = ElapstimeFin - ElapstimeStart; if (!iTime) iTime = 1; /* * Checking the successfull sent files, they are missing from * the ./tag directory. Failed files are still there. */ colour(11, 0); /* Updating download counters, please wait ... */ printf("\r%s\n\n", (char *) Language(352)); fflush(stdout); Count = Size = 0; if ((tf = fopen("taglist", "r+")) != NULL) { while (fread(&Tag, sizeof(Tag), 1, tf) == 1) { if (Tag.Active) { sprintf(symTo, "./tag/%s", Tag.File); /* * If symlink is gone the file is sent. */ if ((access(symTo, R_OK)) != 0) { Syslog('+', "File %s from area %d sent ok", Tag.File, Tag.Area); Tag.Active = FALSE; fseek(tf, - sizeof(Tag), SEEK_CUR); fwrite(&Tag, sizeof(Tag), 1, tf); /* * Update the download counter and the * last download date. */ SetFileArea(Tag.Area); if ((fp = OpenFileBase(Tag.Area, TRUE)) != NULL) { while (fread(&file, sizeof(file), 1, fp) == 1) { if (strcmp(file.Name, Tag.File) == 0) break; } Size += file.Size; file.TimesDL++; time(&file.LastDL); fseek(fp, - sizeof(file), SEEK_CUR); fwrite(&file, sizeof(file), 1, fp); fclose(fp); Count++; } } else { Syslog('+', "Failed to sent %s from area %d", Tag.File, Tag.Area); } } } } /* * Work out transfer rate in seconds by dividing the * Size of the File by the amount of time it took to download * the file. */ iTransfer = Size / iTime; Syslog('+', "Download time %ld seconds (%lu cps), %d files", iTime, iTransfer, Count); /* * Update the users record. */ ReadExitinfo(); exitinfo.Downloads += Count; /* Increase download counter */ exitinfo.DownloadK += (Size / 1024); /* Increase amount download today */ /* * Minus the amount downloaded today from downloadktoday * if less than zero, it won't let the user download anymore. */ exitinfo.DownloadKToday -= (Size / 1024); exitinfo.iTransferTime = iTransfer; WriteExitinfo(); Pause(); SetFileArea(OldArea); free(symTo); free(symFrom); } /* * Show Raw directory */ void File_RawDir(char *OpData) { DIR *dirp; char *FileName, *temp; int iFileCount = 0; int LineCount = 2; int iBytes = 0; struct dirent *dp; struct stat statfile; FileName = calloc(PATH_MAX, sizeof(char)); temp = calloc(PATH_MAX, sizeof(char)); if((strcmp(OpData, "/F")) == 0) strcpy(temp, sAreaPath); else strcpy(temp, OpData); if ((dirp = opendir(temp)) == NULL) { clear(); WriteError("$RawDir: Can't open dir: %s", temp); printf("\nCan't open directory for raw listing!\n\n"); Pause(); } else { clear(); colour(CFG.HiliteF, CFG.HiliteB); /* Filename Size Date */ printf("%s\n", (char *) Language(261)); fLine(42); while ((dp = readdir( dirp )) != NULL ) { sprintf(FileName, "%s/%s", temp, dp->d_name); if (*(dp->d_name) != '.') { iFileCount++; if(stat(FileName,&statfile) != 0) printf("Can't stat file %s\n",FileName); iBytes += statfile.st_size; colour(14,0); printf("%-20s", dp->d_name); colour(13,0); printf("%-12ld", statfile.st_size); colour(10,0); printf("%-10s\n", StrDateDMY(statfile.st_mtime)); LineCount++; if (LineCount == exitinfo.iScreenLen) { Pause(); LineCount = 0; } } } colour(CFG.HiliteF, CFG.HiliteB); fLine(42); /* Total Files: */ /* Bytes */ printf("%s %d, %d %s\n\n", (char *) Language(242), iFileCount, iBytes, (char *) Language(354)); Pause(); closedir(dirp); } free(temp); free(FileName); } /* * Search for keyword, called from menu. */ int KeywordScan() { FILE *pAreas, *pFile; int i, z, y, Found, Count = 0; char *Name; char *tmpname; char *BigDesc; char temp[81]; _Tag T; unsigned long OldArea; Name = calloc(81, sizeof(char)); tmpname = calloc(81, sizeof(char)); BigDesc = calloc(1230, sizeof(char)); OldArea = iAreaNumber; iLineCount = 2; /* Reset Line Counter to Zero */ arecno = 1; /* Reset Area Number to One */ Enter(2); /* Enter keyword to use for Search: */ pout(11, 0, (char *) Language(267)); colour(CFG.InputColourF, CFG.InputColourB); GetstrC(Name, 80); if((strcmp(Name, "")) == 0) return 0; strcpy(tmpname, tl(Name)); strcpy(Name, ""); y = strlen(tmpname); for (z = 0; z < y; z++) { if (tmpname[z] != '*') { sprintf(temp, "%c", tmpname[z]); strcat(Name, temp); } } Syslog('+', "KeywordScan(): \"%s\"", Name); clear(); /* File search by keyword */ pout(15, 0, (char *) Language(268)); Enter(1); InitTag(); for(i = 0; i < 25; i++) sprintf(BigDesc, "%s%s", BigDesc, *(file.Desc + i)); if ((pAreas = OpenFareas(FALSE)) == NULL) return 0; while (fread(&area, areahdr.recsize, 1, pAreas) == 1) { if ((Access(exitinfo.Security, area.LTSec)) && (area.Available) && (strlen(area.Password) == 0)) { if ((pFile = OpenFileBase(arecno, FALSE)) != NULL) { Nopper(); Found = FALSE; Sheader(); while (fread(&file, sizeof(file), 1, pFile) == 1) { for(i = 0; i < 25; i++) sprintf(BigDesc, "%s%s", BigDesc, *(file.Desc + i)); if ((strstr(file.Name,Name) != NULL) || (strstr(tl(BigDesc), Name) != NULL)) { if (!Found) { Enter(2); if (iLC(2) == 1) { free(BigDesc); free(Name); free(tmpname); SetFileArea(OldArea); return 1; } Found = TRUE; } T.Area = arecno; T.Active = FALSE; T.Cost = file.Cost; T.Size = file.Size; sprintf(T.File, "%s", file.Name); SetTag(T); Count++; if (ShowOneFile() == 1) { free(BigDesc); free(Name); free(tmpname); SetFileArea(OldArea); return 1; } } strcpy(BigDesc, ""); /* Clear BigDesc */ } /* while */ fclose(pFile); if (Found) { Enter(2); if (iLC(2) == 1) { free(BigDesc); free(Name); free(tmpname); SetFileArea(OldArea); return 1; } } } /* End check for LTSec */ } /* if access */ arecno++; /* Go to next file area */ } /* End of Main */ Syslog('+', "Found %d files", Count); free(BigDesc); free(Name); free(tmpname); fclose(pAreas); printf("\n"); if (Count) Mark(); else Pause(); SetFileArea(OldArea); return 1; } /* * Search for a file, called from the menu. */ int FilenameScan() { FILE *pAreas, *pFile; int z, y, Found, Count = 0; char *Name; char *tmpname; char temp[81]; _Tag T; unsigned long OldArea; Name = calloc(81, sizeof(char)); tmpname = calloc(81, sizeof(char)); OldArea = iAreaNumber; iLineCount = 2; /* Reset Line Counter to Zero */ arecno = 1; /* Reset Area Number to One */ Enter(2); /* Accepts wildcards such as : *.zip, *.gz, .tar */ pout(15, 0, (char *) Language(269)); Enter(1); /* : *.zip is the same as .zip */ pout(15, 0, (char *) Language(270)); Enter(2); /* Enter filename to search for : */ pout(11, 0, (char *) Language(271)); colour(CFG.InputColourF, CFG.InputColourB); GetstrC(Name, 80); if ((strcmp(Name, "")) == 0) { free(tmpname); free(Name); return 0; } /* * If there is a file extension, strip it off, it are mostly * archiver extensions, and who knows what we're using as * archiver. */ if (strchr(Name, '.') != NULL) strcpy(tmpname, strtok(Name, ".")); else strcpy(tmpname, tl(Name)); strcpy(Name, ""); y = strlen(tmpname); for(z = 0; z < y; z++) { if(tmpname[z] != '*') { sprintf(temp, "%c", tmpname[z]); strcat(Name, temp); } } Syslog('+', "FilenameScan(): \"%s\"", Name); clear(); /* File Search by Filename */ pout(15, 0, (char *) Language(272)); Enter(1); InitTag(); if ((pAreas = OpenFareas(FALSE)) == NULL) return 0; while (fread(&area, areahdr.recsize, 1, pAreas) == 1) { if ((Access(exitinfo.Security, area.LTSec)) && (area.Available) && (strlen(area.Password) == 0)) { if ((pFile = OpenFileBase(arecno, FALSE)) != NULL) { Found = FALSE; Sheader(); Nopper(); while (fread(&file, sizeof(file), 1, pFile) == 1) { strcpy(tmpname, tl(file.Name)); if ((strstr(tmpname, Name)) != NULL) { if (!Found) { Enter(2); if (iLC(2) == 1) { free(Name); free(tmpname); SetFileArea(OldArea); return 1; } Found = TRUE; } T.Area = arecno; T.Active = FALSE; T.Cost = file.Cost; T.Size = file.Size; sprintf(T.File, "%s", file.Name); SetTag(T); Count++; if (ShowOneFile() == 1) { free(Name); free(tmpname); SetFileArea(OldArea); return 1; } } } /* End of while */ fclose(pFile); if (Found) { Enter(2); if (iLC(2) == 1) { free(Name); free(tmpname); SetFileArea(OldArea); return 1; } } } /* End Check for LTSec */ } /* if access */ arecno++; /* Go to next file area */ } /* End of Main */ Syslog('+', "Found %d files", Count); fclose(pAreas); free(Name); free(tmpname); printf("\n"); if (Count) Mark(); else Pause(); SetFileArea(OldArea); return 1; } /* * Scan for new files, called from menu. */ int NewfileScan(int AskStart) { FILE *pAreas, *pFile; long ifDate, itDate; char *temp, *Date; int Found, Count = 0; _Tag T; Date = calloc(81, sizeof(char)); temp = calloc(81, sizeof(char)); iLineCount = 2; arecno = 1; /* Reset Area Number to One */ if (AskStart) { Enter(2); /* Search for new since your last call [Y/n]: */ pout(11, 0, (char *) Language(273)); colour(CFG.InputColourF, CFG.InputColourB); fflush(stdout); if (toupper(Getone()) == Keystroke(273, 1)) { Enter(1); /* Enter new date to search for [DD-MM-YYYY]: */ pout(2, 0, (char *) Language(274)); colour(CFG.InputColourF, CFG.InputColourB); fflush(stdout); GetDate(temp, 10); } else strcpy(temp, LastLoginDate); } else strcpy(temp, LastLoginDate); Syslog('+', "NewfileScan() since %s", temp); clear(); /* File Search by Date */ pout(15, 0, (char *) Language(275)); Enter(2); Date[0] = temp[6]; /* Swap the date around */ Date[1] = temp[7]; /* Instead of DD-MM-YYYY */ Date[2] = temp[8]; /* Let it equal YYYYMMDD */ Date[3] = temp[9]; /* Swap the date around */ Date[4] = temp[3]; /* Swap the date around */ Date[5] = temp[4]; /* because when you convert */ Date[6] = temp[0]; /* a string to an int you */ Date[7] = temp[1]; /* loose the front Zero */ Date[8] = '\0'; /* making the number smaller */ itDate = atol(Date); InitTag(); if ((pAreas = OpenFareas(FALSE)) == NULL) return 0; while (fread(&area, areahdr.recsize, 1, pAreas) == 1) { if ((Access(exitinfo.Security, area.LTSec)) && (area.Available) && (strlen(area.Password) == 0) && (area.New)) { if ((pFile = OpenFileBase(arecno, FALSE)) != NULL ) { Sheader(); Found = FALSE; Nopper(); while (fread(&file, sizeof(file), 1, pFile) == 1) { strcpy(temp, StrDateDMY(file.UploadDate)); /* Realloc Space for Date */ Date[0] = temp[6]; /* Swap the date around */ Date[1] = temp[7]; /* Instead of DD-MM-YYYY */ Date[2] = temp[8]; /* Let it equal YYYYMMDD */ Date[3] = temp[9]; /* Swap the date around */ Date[4] = temp[3]; /* Swap the date around */ Date[5] = temp[4]; /* because when you convert */ Date[6] = temp[0]; /* a string to an int you */ Date[7] = temp[1]; /* loose the front Zero */ Date[8] = '\0'; /* making the number smaller */ /* and invalid to this cause */ ifDate = atol(Date); if(ifDate >= itDate) { if (!Found) { printf("\n\n"); if (iLC(2) == 1) { free(Date); free(temp); return 1; } Found = TRUE; } T.Area = arecno; T.Active = FALSE; T.Cost = file.Cost; T.Size = file.Size; sprintf(T.File, "%s", file.Name); SetTag(T); Count++; if (ShowOneFile() == 1) { free(Date); free(temp); return 1; } } /* End of if */ } /* End of while */ fclose(pFile); /* * Add 2 blank lines after found files. */ if (Found) { printf("\n\n"); if (iLC(2) == 1) { free(Date); free(temp); return 1; } } } /* End of open filebase */ } /* End of check new files scan */ arecno++; /* Go to next file area */ } /* End of Main */ if (Count) Syslog('+', "Found %d new files", Count); fclose(pAreas); printf("\n"); if (Count) Mark(); else Pause(); free(temp); free(Date); return 1; } /* * Upload a file. */ int Upload() { char File[81], temp[81]; int Area, x = 0; int i, err; unsigned long OldArea; time_t ElapstimeStart, ElapstimeFin, iTime; DIR *dirp; struct dirent *dp; struct stat statfile; char *arc; WhosDoingWhat(UPLOAD); /* * Select default protocol if users hasn't any. */ if (!ForceProtocol()) return 0; Enter(1); Area = OldArea = iAreaNumber; /* * If there is a special upload area for the current area * then select it. */ if (area.Upload) Area = area.Upload; SetFileArea(Area); /* * Only ask for a filename for non-batching protocols, * ie. the stone age Xmodem for example. */ if (!uProtBatch) { /* Please enter file to upload: */ pout(14, 0, (char *) Language(276)); colour(CFG.InputColourF, CFG.InputColourB); GetstrC(File, 80); if((strcmp(File, "")) == 0) return 0; if (*(File) == '.' || *(File) == '*' || *(File) == ' ' || *(File) == '/') { colour(CFG.HiliteF, CFG.HiliteB); /* Illegal Filename! */ printf("\n%s\n\n", (char *) Language(247)); Pause(); return 0; } Strlen = strlen(File); Strlen--; if (*(File + Strlen) == '.' || *(File + Strlen) == '/' || *(File + Strlen) == ' ') { colour(CFG.HiliteF, CFG.HiliteB); /* Illegal Filename! */ printf("\n%s\n\n", (char *) Language(247)); Pause(); return 0; } if ((!strcmp(File, "files.bbs")) || (!strcmp(File, "00index")) || (strstr(File, (char *)".html"))) { colour(CFG.HiliteF, CFG.HiliteB); /* Illegal Filename! */ printf("\n%s\n\n", (char *) Language(247)); Syslog('!', "Attempted to upload %s", File); Pause(); return 0; } for (i = 0; i < strlen(File); i++) printf("%d ", File[i]); /* * Check for a space in filename being uploaded */ if ((strchr(File, 32)) != NULL) { colour(CFG.HiliteF, CFG.HiliteB); /* Illegal Filename! */ printf("\n%s\n\n", (char *) Language(247)); Pause(); return 0; } /* MOET IN ALLE AREAS ZOEKEN */ if (area.Dupes) { x = CheckFile(File, Area); if(x) { Enter(1); /* The file already exists on the system */ pout(15, 3, (char *) Language(282)); Enter(2); SetFileArea(OldArea); Pause(); return 0; } } SetFileArea(OldArea); } SetFileArea(Area); Syslog('+', "Upload area is %d %s", Area, area.Name); /* * Check upload access for the real upload directory. */ if (!Access(exitinfo.Security, area.UPSec)) { colour(CFG.HiliteF, CFG.HiliteB); /* You do not have enough access to upload to this area */ printf("\n%s\n\n", (char *) Language(278)); SetFileArea(OldArea); Pause(); return 0; } clear(); colour(CFG.HiliteF, CFG.HiliteB); /* Please start your upload now ...*/ printf("\n\n%s, %s\n\n", sProtAdvice, (char *) Language(283)); if (uProtBatch) Syslog('+', "Upload using %s", sProtName); else Syslog('+', "Upload \"%s\" using %s", File, sProtName); sprintf(temp, "%s/%s/upl", CFG.bbs_usersdir, exitinfo.Name); if (chdir(temp)) { WriteError("$Can't chdir to %s", temp); SetFileArea(OldArea); return 0; } sprintf(temp, "%s", sProtUp); Syslog('+', "Upload command %s", temp); fflush(stdout); fflush(stdin); sleep(2); time(&ElapstimeStart); /* * Get the file(s). Set the Client/Server time to 2 hours. * This is not a nice solution, at least it works and prevents * that the bbs will hang. */ Altime(7200); alarm_set(7190); if ((err = system(temp)) != 0) { /* * Log any errors */ colour(CFG.HiliteF, CFG.HiliteB); WriteError("$Upload error %d, prot: %s", err, sProtUp); } Altime(0); alarm_off(); alarm_on(); printf("\n\n\n"); fflush(stdout); fflush(stdin); time(&ElapstimeFin); /* * Get time from Before Upload and After Upload to get * upload time, if the time is zero, it will be one. */ iTime = ElapstimeFin - ElapstimeStart; if (!iTime) iTime = 1; Syslog('b', "Transfer time %ld", iTime); if ((dirp = opendir(".")) == NULL) { WriteError("$Upload: can't open ./upl"); Home(); SetFileArea(OldArea); return 1; } Syslog('b', "Start checking uploaded files"); pout(CFG.UnderlineColourF, CFG.UnderlineColourB, (char *)"\n\nChecking your upload(s)\n\n"); while ((dp = readdir(dirp)) != NULL) { if (*(dp->d_name) != '.') { stat(dp->d_name, &statfile); Syslog('+', "Uploaded \"%s\", %ld bytes", dp->d_name, statfile.st_size); if ((arc = GetFileType(dp->d_name)) == NULL) { /* * If the filetype is unknown, it is probably * a textfile or so. Import it direct. */ Syslog('b', "Unknown file type"); ImportFile(dp->d_name, Area, FALSE, iTime, statfile.st_size); } else { /* * We figured out the type of the uploaded file. */ Syslog('b', "File type is %s", arc); /* * MS-DOS executables are handled direct. */ if ((strcmp("EXE", arc) == 0) || (strcmp("COM", arc) == 0)) { if (!ScanDirect(dp->d_name)) ImportFile(dp->d_name, Area, FALSE, iTime, statfile.st_size); } else { switch(ScanArchive(dp->d_name, arc)) { case 0: ImportFile(dp->d_name, Area, TRUE, iTime, statfile.st_size); break; case 1: break; case 2: break; case 3: /* * No valid unarchiver found, just import */ ImportFile(dp->d_name, Area, FALSE, iTime, statfile.st_size); break; } } } } } closedir(dirp); Home(); SetFileArea(OldArea); Pause(); return 1; } /* * Function will download a specific file */ int DownloadDirect(char *Name, int Wait) { int err, rc; char *symTo, *symFrom; char *temp; long Size; time_t ElapstimeStart, ElapstimeFin, iTime; long iTransfer = 0; if ((Size = file_size(Name)) == -1) { WriteError("No file %s", Name); colour(CFG.HiliteF, CFG.HiliteB); printf("File not found\n\n"); Pause(); } /* * Make a symlink to the users tmp dir. */ symTo = calloc(PATH_MAX, sizeof(char)); symFrom = calloc(PATH_MAX, sizeof(char)); sprintf(symFrom, "%s/%s/tmp%s", CFG.bbs_usersdir, exitinfo.Name, strrchr(Name, '/')); sprintf(symTo, "%s", Name); if (symlink(symTo, symFrom)) { WriteError("$Can't create symlink %s %s", symTo, symFrom); free(symTo); free(symFrom); return FALSE; } /* * If user has no default protocol, make sure he has one. */ if (!ForceProtocol()) { unlink(symFrom); free(symTo); free(symFrom); return FALSE; } WhosDoingWhat(DOWNLOAD); ReadExitinfo(); clear(); /* File(s) : */ pout(14, 0, (char *) Language(349)); printf("%s\n", symFrom); /* Size : */ pout( 3, 0, (char *) Language(350)); printf("%lu\n", Size); /* Protocol : */ pout( 3, 0, (char *) Language(351)); printf("%s\n", sProtName); Syslog('+', "Download direct start %s", Name); printf("%s\n\n", sProtAdvice); fflush(stdout); fflush(stdin); /* * Wait a while before download */ sleep(2); time(&ElapstimeStart); temp = calloc(PATH_MAX, sizeof(char)); sprintf(temp, "%s %s", sProtDn, symFrom); Syslog('+', "Download command %s", temp); /* * Transfer the file. Set the Client/Server time at the maximum * time the user has plus 10 minutes. The overall timer 10 seconds * less. */ alarm_set(((exitinfo.iTimeLeft + 10) * 60) - 10); Altime((exitinfo.iTimeLeft + 10) * 60); if ((err = system(temp)) != 0) { /* * Only log the error, we might have sent some files * instead of nothing. */ perror(""); colour(CFG.HiliteF, CFG.HiliteB); WriteError("Download error %d, prot: %s", err, sProtDn); } Altime(0); alarm_off(); alarm_on(); fflush(stdout); fflush(stdin); free(temp); time(&ElapstimeFin); /* * Get time from Before Download and After Download to get * download time, if the time is zero, it will be one. */ iTime = ElapstimeFin - ElapstimeStart; if (!iTime) iTime = 1; if ((access(symFrom, R_OK)) != 0) { /* * Work out transfer rate in seconds by dividing the * Size of the File by the amount of time it took to download * the file. */ iTransfer = Size / iTime; Syslog('+', "Download ok, time %ld seconds (%lu cps)", iTime, iTransfer); /* * Update the users record. The file is free, so only statistics. */ ReadExitinfo(); exitinfo.Downloads++; /* Increase download counter */ exitinfo.iTransferTime = iTransfer; WriteExitinfo(); rc = TRUE; } else { Syslog('+', "Download failed to sent file"); unlink(symFrom); rc = FALSE; } if (Wait) Pause(); free(symTo); free(symFrom); return rc; } /* * Function will list users home directory */ void List_Home() { DIR *dirp; char *FileName, *temp; int iFileCount = 0; int iBytes = 0; struct dirent *dp; struct stat statfile; FileName = calloc(PATH_MAX, sizeof(char)); temp = calloc(PATH_MAX, sizeof(char)); iLineCount = 2; clear(); sprintf(temp, "%s/%s/wrk", CFG.bbs_usersdir, exitinfo.Name); if ((dirp = opendir(temp)) == NULL) { WriteError("$List_Home: Can't open dir: %s", temp); /* Can't open directory for listing: */ printf("\n%s\n\n", (char *) Language(290)); Pause(); } else { colour(1, 7); /* Home directory listing for */ printf(" %s", (char *) Language(291)); colour(4, 7); printf("%-51s\n", exitinfo.sUserName); while ((dp = readdir( dirp )) != NULL ) { sprintf(FileName, "%s/%s", temp, dp->d_name); /* * Check first letter of file for a ".", do not display hidden files * This includes the current directory and parent directory . & .. */ if (*(dp->d_name) != '.') { iFileCount++; if(stat(FileName, &statfile) != 0) WriteError("$Can't stat file %s",FileName); iBytes += statfile.st_size; colour(14,0); printf("%-20s", dp->d_name); colour(13,0); printf("%-12ld", statfile.st_size); colour(10,0); printf("%s ", StrDateDMY(statfile.st_mtime)); colour(11,0); printf("%s", StrTimeHMS(statfile.st_mtime)); printf("\n"); } if (iLC(1) == 1) return; } colour(11,0); /* Total Files: */ /* Bytes */ printf("\n\n%s%d / %d %s\n", (char *) Language(242), iFileCount, iBytes, (char *) Language(354)); Pause(); closedir(dirp); } free(temp); free(FileName); } /* * Delete files from home directory */ void Delete_Home() { char *temp, *temp1; int i; temp = calloc(PATH_MAX, sizeof(char)); temp1 = calloc(PATH_MAX, sizeof(char)); sprintf(temp, "%s/%s/wrk/", CFG.bbs_usersdir, exitinfo.Name); Enter(1); /* Please enter filename to delete: */ pout(9, 0, (char *) Language(292)); colour(CFG.InputColourF, CFG.InputColourB); fflush(stdout); GetstrC(temp1, 80); if(strcmp(temp1, "") == 0) { free(temp); free(temp1); return; } if(temp1[0] == '.') { Enter(1); /* Sorry you may not delete hidden files ...*/ pout(12, 0, (char *) Language(293)); } else { strcat(temp, temp1); if ((access(temp, R_OK)) == 0) { colour(10, 0); /* Delete file: */ /* Are you Sure? [Y/n]: */ printf("\n%s %s, %s", (char *) Language(368), temp1, (char *) Language(369)); fflush(stdout); i = toupper(Getone()); if (i == Keystroke(368, 0) || i == 13) { i = unlink(temp); if (i == -1) { Enter(1); /* Unable to delete file ... */ pout(12, 0, (char *) Language(294)); } else { Syslog('+', "Delete %s from homedir", temp1); } } else { Enter(2); /* Aborting ... */ pout(8, 0, (char *) Language(116)); } } else { Enter(1); /* Invalid filename, please try again ... */ pout(12, 0, (char *) Language(295)); } } free(temp); free(temp1); printf("\n"); Pause(); } /* * Function allows user to download from his/her home directory * but still does all the necessary checks */ int Download_Home() { char *temp, *File; struct stat statfile; int rc; File = calloc(PATH_MAX, sizeof(char)); temp = calloc(PATH_MAX, sizeof(char)); WhosDoingWhat(DOWNLOAD); colour(14,0); /* Please enter filename: */ printf("\n%s", (char *) Language(245)); colour(CFG.InputColourF, CFG.InputColourB); GetstrC(File, 80); if(( strcmp(File, "")) == 0) { colour(CFG.HiliteF, CFG.HiliteB); /* No filename entered, Aborting. */ printf("\n\n%s\n", (char *) Language(246)); Pause(); free(File); free(temp); return FALSE; } if( *(File) == '/' || *(File) == ' ') { colour(CFG.HiliteF, CFG.HiliteB); /* Illegal Filename! */ printf("\n%s\n\n", (char *) Language(247)); Pause(); free(File); free(temp); return FALSE; } /* * Get path for users home directory */ sprintf(temp, "%s/%s/wrk/%s", CFG.bbs_usersdir, exitinfo.Name, File); if (stat(temp, &statfile) != 0) { Enter(1); /* File does not exist, please try again ...*/ pout(12, 0, (char *) Language(296)); Enter(2); Pause(); free(File); free(temp); return FALSE; } rc = DownloadDirect(temp, TRUE); free(File); free(temp); return rc; } /* * Function will upload to users home directory */ int Upload_Home() { DIR *dirp; struct dirent *dp; char *File, *sFileName, *temp, *arc; time_t ElapstimeStart, ElapstimeFin, iTime; int err; struct stat statfile; WhosDoingWhat(UPLOAD); if (!ForceProtocol()) return 0; File = calloc(PATH_MAX, sizeof(char)); sFileName = calloc(PATH_MAX, sizeof(char)); temp = calloc(PATH_MAX, sizeof(char)); if (!uProtBatch) { Enter(1); /* Please enter file to upload: */ pout(14, 0, (char *) Language(276)); colour(CFG.InputColourF, CFG.InputColourB); GetstrC(File, 80); if((strcmp(File, "")) == 0) { free(File); free(sFileName); free(temp); return 0; } if(File[0] == '.' || File[0] == '*' || File[0] == ' ') { colour(CFG.HiliteF, CFG.HiliteB); /* Illegal Filename! */ printf("\n%s\n\n", (char *) Language(247)); Pause(); free(File); free(sFileName); free(temp); return 0; } Strlen = strlen(File); Strlen--; if(File[Strlen] == '.' || File[Strlen] == '/' || File[Strlen] == ' ') { colour(CFG.HiliteF, CFG.HiliteB); /* Illegal Filename! */ printf("\n%s\n\n", (char *) Language(247)); Pause(); free(File); free(sFileName); free(temp); return 0; } } clear(); colour(CFG.HiliteF, CFG.HiliteB); /* Please start your upload now ...*/ printf("\n\n%s, %s\n\n", sProtAdvice, (char *) Language(283)); if (uProtBatch) Syslog('+', "Upload using %s", sProtName); else Syslog('+', "Upload \"%s\" using %s", File, sProtName); sprintf(temp, "%s/%s/upl", CFG.bbs_usersdir, exitinfo.Name); if (chdir(temp)) { WriteError("$Can't chdir to %s", temp); free(File); free(sFileName); free(temp); return 0; } sprintf(temp, "%s", sProtUp); Syslog('+', "Upload command %s", temp); fflush(stdout); fflush(stdin); sleep(2); time(&ElapstimeStart); /* * Get the file(s). Set the Client/Server time to 2 hours. * This is not a nice solution, at least it works and prevents * that the bbs will hang. */ Altime(7200); alarm_set(7190); if ((err = system(temp)) != 0) { /* * Log any errors */ colour(CFG.HiliteF, CFG.HiliteB); WriteError("$Upload error %d, prot: %s", err, sProtUp); } Altime(0); alarm_off(); alarm_on(); printf("\n\n\n"); fflush(stdout); fflush(stdin); time(&ElapstimeFin); /* * Get time from Before Upload and After Upload to get * upload time, if the time is zero, it will be one. */ iTime = ElapstimeFin - ElapstimeStart; if (!iTime) iTime = 1; Syslog('b', "Transfer time %ld", iTime); if ((dirp = opendir(".")) == NULL) { WriteError("$Upload: can't open ./upl"); Home(); free(File); free(sFileName); free(temp); return 1; } Syslog('b', "Start checking uploaded files"); pout(CFG.UnderlineColourF, CFG.UnderlineColourB, (char *)"\n\nChecking your upload(s)\n\n"); while ((dp = readdir(dirp)) != NULL) { if (*(dp->d_name) != '.') { stat(dp->d_name, &statfile); Syslog('+', "Uploaded \"%s\", %ld bytes", dp->d_name, statfile.st_size); if ((arc = GetFileType(dp->d_name)) == NULL) { /* * If the filetype is unknown, it is probably * a textfile or so. Import it direct. */ Syslog('b', "Unknown file type"); ImportHome(dp->d_name); } else { /* * We figured out the type of the uploaded file. */ Syslog('b', "File type is %s", arc); /* * MS-DOS executables are handled direct. */ if ((strcmp("EXE", arc) == 0) || (strcmp("COM", arc) == 0)) { if (!ScanDirect(dp->d_name)) ImportHome(dp->d_name); } else { switch(ScanArchive(dp->d_name, arc)) { case 0: ImportHome(dp->d_name); break; case 1: break; case 2: break; case 3: /* * No valid unarchiver found, just import */ ImportHome(dp->d_name); break; } } } } } closedir(dirp); Home(); ReadExitinfo(); exitinfo.Uploads++; WriteExitinfo(); Pause(); free(File); free(sFileName); free(temp); return 1; } /* * Select filearea, called from menu. */ void FileArea_List(char *Option) { FILE *pAreas; int iAreaCount = 6, Recno = 1; int iOldArea, iAreaNum = 0; int iGotArea = FALSE; /* Flag to check if user typed in area */ long offset; char *temp; /* * Save old area, incase he picks a invalid area */ iOldArea = iAreaNumber; if ((pAreas = OpenFareas(FALSE)) == NULL) return; /* * Count howmany records there are */ fseek(pAreas, 0, SEEK_END); iAreaNum = (ftell(pAreas) - areahdr.hdrsize) / areahdr.recsize; /* * If there are menu options, select area direct. */ if (strlen(Option) != 0) { if (strcmp(Option, "F+") == 0) while(TRUE) { iAreaNumber++; if (iAreaNumber > iAreaNum) iAreaNumber = 1; offset = areahdr.hdrsize + ((iAreaNumber - 1) * areahdr.recsize); if (fseek(pAreas, offset, 0) != 0) { printf("Can't move pointer here"); } fread(&area, areahdr.recsize, 1, pAreas); if ((Access(exitinfo.Security, area.LTSec)) && (area.Available) && (strlen(area.Password) == 0)) break; } if (strcmp(Option, "F-") == 0) while(TRUE) { iAreaNumber--; if (iAreaNumber < 1) iAreaNumber = iAreaNum; offset = areahdr.hdrsize + ((iAreaNumber - 1) * areahdr.recsize); if (fseek(pAreas, offset, 0) != 0) { printf("Can't move pointer here"); } fread(&area, areahdr.recsize, 1, pAreas); if ((Access(exitinfo.Security, area.LTSec)) && (area.Available) && (strlen(area.Password) == 0)) break; } SetFileArea(iAreaNumber); Syslog('+', "File area %lu %s", iAreaNumber, sAreaDesc); fclose(pAreas); return; } /* * Interactive mode */ clear(); Enter(1); /* File Areas */ pout(CFG.HiliteF, CFG.HiliteB, (char *) Language(298)); Enter(2); temp = calloc(81, sizeof(char)); fseek(pAreas, areahdr.hdrsize, 0); while (fread(&area, areahdr.recsize, 1, pAreas) == 1) { if ((Access(exitinfo.Security, area.LTSec)) && (area.Available)) { area.Name[31] = '\0'; colour(15,0); printf("%5d", Recno); colour(9,0); printf(" %c ", 46); colour(3,0); printf("%-31s", area.Name); iAreaCount++; if ((iAreaCount % 2) == 0) printf("\n"); else printf(" "); } Recno++; if ((iAreaCount / 2) == exitinfo.iScreenLen) { /* More (Y/n/=/Area #): */ pout(CFG.MoreF, CFG.MoreB, (char *) Language(207)); /* * Ask user for Area or enter to continue */ colour(CFG.InputColourF, CFG.InputColourB); fflush(stdout); GetstrC(temp, 7); if (toupper(*(temp)) == Keystroke(207, 1)) break; if ((strcmp(temp, "")) != 0) { iGotArea = TRUE; break; } iAreaCount = 2; } } /* * If user type in area above during area listing * don't ask for it again */ if (!iGotArea) { Enter(1); /* Select Area: */ pout(CFG.HiliteF, CFG.HiliteB, (char *) Language(232)); colour(CFG.InputColourF, CFG.InputColourB); GetstrC(temp, 80); } /* * Check if user pressed ENTER */ if((strcmp(temp, "")) == 0) { fclose(pAreas); return; } iAreaNumber = atoi(temp); /* * Do a check in case user enters a negative value */ if (iAreaNumber < 1) iAreaNumber = 1; offset = areahdr.hdrsize + ((iAreaNumber - 1) * areahdr.recsize); if(fseek(pAreas, offset, 0) != 0) printf("Can't move pointer there."); else fread(&area, areahdr.recsize, 1, pAreas); /* * Do a check if area is greater or less number than allowed, * security access level, is oke, and the area is active. */ if (iAreaNumber > iAreaNum || iAreaNumber < 1 || (Access(exitinfo.Security, area.LTSec) == FALSE) || (strlen(area.Name) == 0)) { Enter(1); /* Invalid area specified - Please try again ...*/ pout(12, 0, (char *) Language(233)); Enter(2); Pause(); fclose(pAreas); iAreaNumber = iOldArea; SetFileArea(iAreaNumber); free(temp); return; } SetFileArea(iAreaNumber); Syslog('+', "File area %lu %s", iAreaNumber, sAreaDesc); /* * Check if file area has a password, if it does ask user for it */ if((strlen(area.Password)) > 2) { Enter(2); /* Please enter Area Password: */ pout(15, 0, (char *) Language(299)); fflush(stdout); colour(CFG.InputColourF, CFG.InputColourB); GetstrC(temp, 20); if((strcmp(temp, area.Password)) != 0) { Enter(1); /* Password is incorrect */ pout(15, 0, (char *) Language(234)); Enter(2); Syslog('!', "Incorrect File Area # %d password given: %s", iAreaNumber, temp); SetFileArea(iOldArea); } else { Enter(1); /* Password is correct */ pout(15, 0, (char *) Language(235)); Enter(2); } Pause(); } free(temp); fclose(pAreas); } /* * Show filelist from current area, called from the menu. */ void Copy_Home() { FILE *pFile; char *File, *temp1, *temp2; int err, Found = FALSE; File = calloc(81, sizeof(char)); temp1 = calloc(PATH_MAX, sizeof(char)); temp2 = calloc(PATH_MAX, sizeof(char)); colour(14,0); /* Please enter filename: */ printf("\n%s", (char *) Language(245)); colour(CFG.InputColourF, CFG.InputColourB); GetstrC(File, 80); if ((strcmp(File, "")) == 0) { colour(CFG.HiliteF, CFG.HiliteB); /* No filename entered, Aborting. */ printf("\n\n%s\n", (char *) Language(246)); Pause(); free(File); free(temp1); free(temp2); return; } if (*(File) == '/' || *(File) == ' ') { colour(CFG.HiliteF, CFG.HiliteB); /* Illegal Filename! */ printf("\n%s\n\n", (char *) Language(247)); Pause(); free(File); free(temp1); free(temp2); return; } if(Access(exitinfo.Security, area.DLSec) == FALSE) { colour(14, 0); printf("\n%s\n", (char *) Language(236)); Pause(); free(File); free(temp1); free(temp2); return; } if ((pFile = OpenFileBase(iAreaNumber, FALSE)) == NULL) { free(File); free(temp1); free(temp2); return; } while (fread(&file, sizeof(file), 1, pFile) == 1) { if (strcmp(File, file.Name) == 0) { Found = TRUE; if (((file.Size + Quota()) > (CFG.iQuota * 1048576))) { colour(CFG.HiliteF, CFG.HiliteB); /* You have not enough diskspace free to copy this file */ printf("%s\n", (char *) Language(279)); Syslog('+', "Copy homedir, not enough quota"); } else { sprintf(temp1, "%s/%s", area.Path, File); sprintf(temp2, "%s/%s/wrk/%s", CFG.bbs_usersdir, exitinfo.Name, File); colour(CFG.TextColourF, CFG.TextColourB); /* Start copy: */ printf("%s%s ", (char *) Language(289), File); fflush(stdout); Syslog('b', "Copy from : %s", temp1); Syslog('b', "Copy to : %s", temp2); if ((err = file_cp(temp1, temp2))) { colour(CFG.HiliteF, CFG.HiliteB); /* Failed! */ printf("%s\n", (char *) Language(353)); WriteError("Copy %s to homedir failed, code %d", File, err); } else { /* Ok */ printf("%s\n", (char *) Language(200)); Syslog('+', "Copied %s from area %d to homedir", File, iAreaNumber); } } } } fclose(pFile); if (!Found) { colour(CFG.HiliteF, CFG.HiliteB); /* File does not exist, please try again ... */ printf("%s\n", (char *) Language(296)); } Pause(); free(File); free(temp1); free(temp2); } /* * Edit the list of tagged files. */ void EditTaglist() { FILE *tf; int i, x, Fg, Count; char *temp; if ((tf = fopen("taglist", "r+")) == NULL) { colour(CFG.HiliteF, CFG.HiliteB); /* No files tagged. */ printf("\n%s\n\n", (char *) Language(361)); Pause(); return; } temp = calloc(81, sizeof(char)); while (TRUE) { clear(); fseek(tf, 0, SEEK_SET); Count = 0; colour(CFG.HiliteF, CFG.HiliteB); /* # Area Active File Size Cost */ printf("%s\n", (char *) Language(355)); colour(10, 0); fLine(48); while ((fread(&Tag, sizeof(Tag), 1, tf) == 1)) { Count++; if (Tag.Active) Fg = 15; else Fg = 7; colour(Fg, 0); printf("%3d ", Count); Fg--; colour(Fg, 0); printf("%5ld ", Tag.Area); Fg--; colour(Fg, 0); if (Tag.Active) /* Yes */ printf("%-6s ", (char *) Language(356)); else /* No */ printf("%-6s ", (char *) Language(357)); Fg--; colour(Fg, 0); printf("%-14s", Tag.File); Fg--; colour(Fg, 0); printf(" %8ld", Tag.Size); Fg--; colour(Fg, 0); printf(" %5d\n", Tag.Cost); } colour(10, 0); fLine(48); colour(15, 4); /* (T)oggle active, (E)rase all, (ENTER) to continue: */ printf("\n%s", (char *) Language(358)); fflush(stdout); fflush(stdin); i = toupper(Getone()); colour(CFG.CRColourF, CFG.CRColourB); if (i == Keystroke(358, 0)) { /* Enter file number, 1.. */ printf("\n\n%s%d ", (char *) Language(359), Count); fflush(stdout); fflush(stdin); GetstrC(temp, 5); x = atoi(temp); if ((x > 0) && (x <= Count)) { if (fseek(tf, (x - 1) * sizeof(Tag), SEEK_SET) == 0) { if (fread(&Tag, sizeof(Tag), 1, tf) == 1) { if (Tag.Active) Tag.Active = FALSE; else Tag.Active = TRUE; fseek(tf,(x - 1) * sizeof(Tag), SEEK_SET); fwrite(&Tag, sizeof(Tag), 1, tf); } } } } if (i == Keystroke(358, 1)) { fclose(tf); unlink("taglist"); free(temp); return; } if ((i == '\r') || (i == '\n')) { fclose(tf); free(temp); return; } } } /* * View a file in the current area. */ void ViewFile() { }